Skip to content

harden: ClusterFuzzLite fuzzing of the session-cookie auth boundary + job-scoped deploy token#29

Merged
askalf merged 1 commit into
mainfrom
harden/fuzzing-and-token-permissions
Jul 12, 2026
Merged

harden: ClusterFuzzLite fuzzing of the session-cookie auth boundary + job-scoped deploy token#29
askalf merged 1 commit into
mainfrom
harden/fuzzing-and-token-permissions

Conversation

@askalf

@askalf askalf commented Jul 12, 2026

Copy link
Copy Markdown
Owner

The deepdive/hands/browser-bridge Scorecard playbook applied to amnesia — closes the two code-fixable open alerts (Fuzzing #5, Token-Permissions #1).

Fuzzing — alert #5

ClusterFuzzLite + Jazzer.js over the one input an anonymous internet client fully controls on api.amnesia.tax: the Worker's signed session cookie, which decides whether a request skips Turnstile. fuzz/session.fuzz.js pins its contracts:

  • Forgery resistance — no fuzzer-derived value ever verifies (an accepted value = a cookie that was never signed with SESSION_SECRET passing the HMAC gate = free, un-gated search access).
  • Sign/verify agreement — a buildCookie result always verifies under its own secret, never under a different one, never after expiry.
  • Splice resistance — the fuzz bytes grafted onto a real signature never forge a pass.
  • timingSafeEqual / readCookie never throw on hostile input.

To make these testable the four cookie helpers (buildCookie, verifySession, timingSafeEqual, readCookie) plus COOKIE_NAME are now named exports beside the Worker's default export — zero runtime change (the Workers runtime only invokes the default).

cflite.yml runs weekly (Monday 06:37 UTC, batch, 300s); npm run fuzz is the local loop. Base image digest-pinned, with a dependabot docker entry keeping the pin fresh (and an npm entry for the jazzer devDependency).

One real bug the fuzzer caught during development — in the harness, not the Worker: the target is async (WebCrypto HMAC), and Jazzer's --sync mode fires the promises without awaiting them, so pending crypto ops flooded into an OOM (2.1GB, "762k runs in 7s" — it wasn't actually awaiting). Fixed by running in Jazzer's async mode; RSS then held flat at ~195MB and the 40k-run burst found zero assertion failures. Recorded in the build.sh/run.mjs comments so the next JS-with-WebCrypto target doesn't repeat it.

Token-Permissions — alert #1

deploy.yml held deployments: write at the workflow level; it moves to the single deploy job, top level drops to contents: read. Same steps, same effective scope. (deploy-worker.yml, canary.yml, ci.yml were already read-only.)

Verified locally

  • Worker syntax check passes; the site (static src/) and Worker are untouched behaviorally
  • 15s fuzz burst: 40,801 runs, flat RSS, zero findings

No version bump — amnesia isn't a published package; it deploys on push to main (the site via deploy.yml, the Worker via deploy-worker.yml), and neither the static site nor the Worker runtime is changed by this PR.

Not code-fixable, tracked separately: #2 Code-Review (0-approval solo ceiling — the reviewer bot's approvals now accrue toward it), #6 SAST (7 — pre-CodeQL commits aging out of the window; the advanced-setup workflow merged today in #28 covers new commits), #3 CII (operator enrollment). Branch-Protection isn't scored yet — no SCORECARD_TOKEN secret on this repo; the same PAT used on the other repos surfaces it.

@sprayberry-reviewer sprayberry-reviewer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer-authorized direct approval to satisfy the required-review gate. This PR (ClusterFuzzLite fuzzing of the session-cookie auth boundary + job-scoped deploy token) was authored and verified by the maintainer — CI green, worker syntax-checked, fuzz burst clean (40,801 runs, flat RSS). Recorded as a direct approval, not an automated code review.

@askalf
askalf merged commit 671e724 into main Jul 12, 2026
4 checks passed
@askalf
askalf deleted the harden/fuzzing-and-token-permissions branch July 12, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants