Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Dependabot configuration for Go modules
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
43 changes: 43 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# CodeQL analysis for Go
# https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '37 7 * * 0'

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write

strategy:
fail-fast: false
matrix:
language: [go]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-and-quality

- name: Autobuild
uses: github/codeql-action/autobuild@v3

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
5 changes: 5 additions & 0 deletions .well-known/security.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Contact: mailto:codethor@gmail.com
Expires: 2027-12-31T23:59:59.000Z
Preferred-Languages: en
Canonical: https://github.com/codethor0/deadend-lab/.well-known/security.txt
Policy: https://github.com/codethor0/deadend-lab/blob/main/SECURITY.md
10 changes: 10 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ Commits that show "Verified" on GitHub indicate the author cryptographically sig

No private key material or key-generation scripts belong in this repo.

## Local commit guardrail (optional)

To reject Co-authored-by trailers before commit creation:

```bash
cp scripts/hooks/commit-msg .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
```

This does not modify global git config.

## Requirements

- **`make verify` must pass** before any PR is merged.
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fmt:
go fmt ./...

lint:
golangci-lint run
@command -v golangci-lint >/dev/null 2>&1 && golangci-lint run || (echo "golangci-lint not found, skipping"; exit 0)

test:
go test ./...
Expand Down
88 changes: 57 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,32 +79,20 @@ If port 8080 is busy, override: `DEE_PORT=9188 docker compose up -d`
- **TestSAFERejectsCallerNonce**: EncryptNaiveWithNonce returns ErrDecrypt in SAFE.
- **TestUniformFailure**: Tamper, wrong key, wrong AD all return identical ErrDecrypt (no oracle).

## Threat model

See [spec/threat-model.md](spec/threat-model.md) for the attacker model and assumptions.

## Specs

- spec/dee.md - Protocol, key schedule, modes
- spec/stegopq.md - Carrier encoding
- spec/threat-model.md - Attacker model
- spec/security-goals.md - Test mapping

## Challenge

- challenge/break-me.md - Rules and win conditions
- challenge/scoreboard.md - Scoring rubric
- challenge/datasets/ - Generated corpuses

## Releases

See [CHANGELOG.md](CHANGELOG.md).

### Local release-candidate run (stop-the-line gate)
## How to validate

From a clean working tree:

```bash
./scripts/pre-push-gate.sh
```

Or manually (paste-and-run from repo root):
Single paste-and-run from repo root (requires clean tree, Go 1.22+, Docker):

```bash
set -euo pipefail
Expand All @@ -121,40 +109,78 @@ curl -fsS -X POST http://localhost:9188/scenario/safe >/dev/null
curl -fsS -X POST http://localhost:9188/scenario/naive >/dev/null
go run ./cmd/attacks/nonce-reuse
go run ./cmd/attacks/replay
DEE_PORT=9188 docker compose down
```

## Design constraints and invariants

- Nonce uniqueness (SAFE): every (counter, AD) yields a unique nonce; no caller-supplied nonce.
- Counter monotonicity: replay and out-of-order ciphertexts rejected.
- Uniform failure: tamper, wrong key, wrong AD all return identical ErrDecrypt (no oracle).
- Policy tests enforce: deterministic DRBG, handshake vectors only, no secrets in logs.

## Documentation map

Wiki disabled; docs live in `spec/` (protocol, threat model) and `challenge/` (CTF rules, scoring).

## Packages

No packages published; run from source or Docker only.

## Challenge

- challenge/break-me.md - Rules and win conditions
- challenge/scoreboard.md - Scoring rubric
- challenge/datasets/ - Generated corpuses

## Releases

See [CHANGELOG.md](CHANGELOG.md). Releases are signed; tags use SSH or GPG signing.

### Verify signatures

```bash
git log -1 --show-signature
git tag -v v0.1.0
```

Or step-by-step:
### Local release-candidate run

From a clean working tree, run the full validation block (see "How to validate" above) or:

```bash
make verify-clean
docker build -t deadend-lab .
DEE_PORT=9188 docker compose up -d
curl http://localhost:9188/health
curl -X POST http://localhost:9188/scenario/safe
curl -X POST http://localhost:9188/scenario/naive
go run ./cmd/attacks/nonce-reuse
go run ./cmd/attacks/replay
./scripts/pre-push-gate.sh
```

### Tag and push

```bash
git tag -a v0.1.0 -m "deadend-lab research preview v0.1.0"
git tag -a v0.1.1 -m "deadend-lab v0.1.1"
git push origin main --tags
```

### GitHub release notes

Include:

- **How to run Docker**: `docker build -t deadend-lab .` then `DEE_PORT=9188 docker compose up -d` (override port if 8080 is busy)
- **How to break NAIVE**: `make attack-nonce-reuse` (nonce reuse), `make attack-replay` (replay)
- **Why SAFE resists**: Invariant tests (nonce uniqueness, counter monotonicity, uniform failure); policy tests (deterministic DRBG/handshake vector-only); see README "Why SAFE Resists"
- **Research / CTF only** - not for production use.
- **How to reproduce validation**: Run the "How to validate" block from README.
- **How to run Docker**: `docker build -t deadend-lab .` then `DEE_PORT=9188 docker compose up -d` (override port if 8080 is busy).
- **How to break NAIVE**: `make attack-nonce-reuse` (nonce reuse), `make attack-replay` (replay).
- **Why SAFE resists**: Invariant tests (nonce uniqueness, counter monotonicity, uniform failure); policy tests (deterministic DRBG/handshake vector-only); see README "Why SAFE Resists".

### Post-release feedback

Contributions welcome: break NAIVE via demos, add attacks as `cmd/attacks/*`, add invariants/policy tests (do not weaken existing ones). File issues with repro steps and `make release-check` output.

## Security Features

- **Private vulnerability reporting:** Report sensitive findings via [GitHub advisory](https://github.com/codethor0/deadend-lab/security/advisories/new).
- **Dependabot alerts:** Go module vulnerabilities monitored weekly.
- **CodeQL scanning:** Static analysis on push, PR, and weekly schedule.
- **Secret scanning:** Detection of accidentally committed secrets.
- **Policy:** See [SECURITY.md](SECURITY.md).

## Author / Maintainer

- **Thor Thor**
Expand Down
5 changes: 3 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ This project is a **research and CTF (Capture The Flag) harness** for studying D

If you discover a vulnerability in this research harness:

1. **For research/CTF issues:** Open a GitHub Issue in this repository.
2. **For sensitive disclosures:** Contact the maintainers privately (see README maintainers section) if the finding could affect other research tooling or documentation.
1. **Preferred:** Use [Private vulnerability reporting](https://github.com/codethor0/deadend-lab/security/advisories/new) on GitHub for sensitive disclosures.
2. **For research/CTF issues:** Open a GitHub Issue in this repository.
3. **Alternative:** Email codethor@gmail.com if the finding could affect other research tooling or documentation.

We do not offer bug bounties. This is a learning and research project.
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module deadend-lab

go 1.22
go 1.22.0

require (
github.com/cloudflare/circl v1.3.7
golang.org/x/crypto v0.22.0
github.com/cloudflare/circl v1.6.3
golang.org/x/crypto v0.30.0
)

require golang.org/x/sys v0.19.0 // indirect
require golang.org/x/sys v0.28.0 // indirect
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
7 changes: 6 additions & 1 deletion scripts/audit-rewrite-push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,12 @@ if hasattr(tag, 'tagger_name') and tag.tagger_name:
"

echo "== Local gate on rewritten clone =="
./scripts/pre-push-gate.sh
if [ "${GATE_SKIP:-0}" != "1" ]; then
./scripts/pre-push-gate.sh
else
echo "GATE_SKIP=1: skipping pre-push-gate (run make verify locally to validate)"
go test ./tests/policy/... -count=1 || { echo "Policy tests failed"; exit 1; }
fi

echo "== Force-push rewritten main and re-tag =="
git remote add origin "$REPO_HTTPS" 2>/dev/null || true
Expand Down
8 changes: 8 additions & 0 deletions scripts/hooks/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
# Reject commit messages containing Co-authored-by trailer.
# Install: cp scripts/hooks/commit-msg .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg
if grep -qi 'co-authored-by:' "$1"; then
echo "commit-msg: Co-authored-by trailer not allowed" >&2
exit 1
fi
exit 0
27 changes: 15 additions & 12 deletions tests/policy/commits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,19 @@ const (
allowedAuthorName = "Thor Thor"
)

// TestCommitAttribution enforces that every commit (author and committer) uses the maintainer identity.
// allowedCommit is true if author+committer match maintainer or Dependabot (GitHub's dependency bot).
func allowedCommit(an, ae, cn, ce string) bool {
if an == allowedAuthorName && ae == allowedAuthorEmail && cn == allowedAuthorName && ce == allowedAuthorEmail {
return true
}
// Dependabot dependency update commits (author: dependabot[bot], committer: GitHub)
if an == "dependabot[bot]" && cn == "GitHub" {
return true
}
return false
}

// TestCommitAttribution enforces that every commit uses maintainer identity or allowed automation (Dependabot).
// No Co-authored-by trailers are allowed.
func TestCommitAttribution(t *testing.T) {
modDir := mustGoModDir(t)
Expand All @@ -32,17 +44,8 @@ func TestCommitAttribution(t *testing.T) {
continue
}
hash, an, ae, cn, ce := parts[0], parts[1], parts[2], parts[3], parts[4]
if ae != allowedAuthorEmail {
t.Errorf("commit %s: author email %q != allowed %q", hash[:12], ae, allowedAuthorEmail)
}
if an != allowedAuthorName {
t.Errorf("commit %s: author name %q != allowed %q", hash[:12], an, allowedAuthorName)
}
if ce != allowedAuthorEmail {
t.Errorf("commit %s: committer email %q != allowed %q", hash[:12], ce, allowedAuthorEmail)
}
if cn != allowedAuthorName {
t.Errorf("commit %s: committer name %q != allowed %q", hash[:12], cn, allowedAuthorName)
if !allowedCommit(an, ae, cn, ce) {
t.Errorf("commit %s: disallowed author %q <%s> committer %q <%s>", hash[:12], an, ae, cn, ce)
}
}
}
Expand Down
Loading