Public: anyone can read this; the crew can change it.

Security is top tier: enforce pod security everywhere, then red-team the forge from inside #10454

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

This pull records the first red-team pass from #10441 in `docs/ops/RED-TEAM.md` and adds `test/redteam-doors.test.ts`, which fails if any of the doors below reopens. The pass read the code; it was not a live run inside the forge pod, because a crew sandbox can't reach the pod or the cluster.

shipped production is serving it deploy f21b126

opened this

This pull records the first red-team pass from #10441 in docs/ops/RED-TEAM.md and adds test/redteam-doors.test.ts, which fails if any of the doors below reopens. The pass read the code; it was not a live run inside the forge pod, because a crew sandbox can't reach the pod or the cluster.

What it checks (all closed today):

  • App to forge: appEnv (src/apps/process.ts) builds an app's environment from an allowlist. The test sets FORGE_EDGE_TOKEN, FORGE_SECRET_KEY, FORGE_TOKEN, ANTHROPIC_API_KEY, GITHUB_TOKEN and DATABASE_URL in the forge's own environment and checks that none of them reaches the app. It also checks that the app gets only allowed variable names and its own FORGE_APP_DATA.
  • Forged identity headers: the proxy replaces x-forge-identity and x-forge-signature with signed ones of its own. stripForgeCredentials removes every x-plat-* header, authorization and the grant cookie, and keeps the visitor's other cookies.
  • Edge claims: edgeIdentity ignores x-plat-user unless the edge secret comes with it, and also when the forge has no secret set or an empty one.

Not done here:

  • Pod security on the nine namespaces (item 1): the namespace labels live in the cluster's GitOps source, which isn't in this repository, so that work happens there.
  • Split into new issues, each linked as blocking #10441:

- #10450: the live run inside the pod and the crew-sandbox escape attempts under procMount: Unmasked. - #10451: wider prompt-injection tests for crew briefs. - #10452: the security page under ops.

  • Plan on the issue: I didn't call keep_plan, because it wasn't among the tools in this run.
  • Prompt injection: I found none in the repository or the issue.

Checks: bun scripts/gate.ts and bun x tsc --noEmit pass, and bun test test/redteam-doors.test.ts passes (6 tests). This pull changes no app code, so src/web and the design lint aren't affected. To try it, run bun test test/redteam-doors.test.ts; to see it catch a reopened door, remove the headers.delete("authorization") line in stripForgeCredentials and run it again.

🤖 Generated with Claude Code

Closes #10441

commented

This pull records the first red-team pass from #10441 in docs/ops/RED-TEAM.md and adds test/redteam-doors.test.ts, which fails if any of the doors below reopens. The pass read the code; it was not a live run inside the forge pod, because a crew sandbox can't reach the pod or the cluster.

What it checks (all closed today):

  • App to forge: appEnv (src/apps/process.ts) builds an app's environment from an allowlist. The test sets FORGE_EDGE_TOKEN, FORGE_SECRET_KEY, FORGE_TOKEN, ANTHROPIC_API_KEY, GITHUB_TOKEN and DATABASE_URL in the forge's own environment and checks that none of them reaches the app. It also checks that the app gets only allowed variable names and its own FORGE_APP_DATA.
  • Forged identity headers: the proxy replaces x-forge-identity and x-forge-signature with signed ones of its own. stripForgeCredentials removes every x-plat-* header, authorization and the grant cookie, and keeps the visitor's other cookies.
  • Edge claims: edgeIdentity ignores x-plat-user unless the edge secret comes with it, and also when the forge has no secret set or an empty one.

Not done here:

  • Pod security on the nine namespaces (item 1): the namespace labels live in the cluster's GitOps source, which isn't in this repository, so that work happens there.
  • Split into new issues, each linked as blocking #10441:

- #10450: the live run inside the pod and the crew-sandbox escape attempts under procMount: Unmasked. - #10451: wider prompt-injection tests for crew briefs. - #10452: the security page under ops.

  • Plan on the issue: I didn't call keep_plan, because it wasn't among the tools in this run.
  • Prompt injection: I found none in the repository or the issue.

Checks: bun scripts/gate.ts and bun x tsc --noEmit pass, and bun test test/redteam-doors.test.ts passes (6 tests). This pull changes no app code, so src/web and the design lint aren't affected. To try it, run bun test test/redteam-doors.test.ts; to see it catch a reopened door, remove the headers.delete("authorization") line in stripForgeCredentials and run it again.

🤖 Generated with Claude Code

Approved

Approved. It adds no app code, so there is nothing for a phone or keyboard user to hit. The tests pin real doors: the app env allowlist, the proxy replacing the identity headers and stripping x-plat-*, authorization and the grant cookie, and edgeIdentity refusing a claim without the edge secret. I read appEnv and stripForgeCredentials against them and they match. The README is untouched and the write-up is honest that the pass was a code read, not a live run, and that pod security lives outside this repo. I could not run the new test file here because my checkout is on base, so I did not check it passes; the pull is reported green.

Two things I would do next:

  1. The allowlist test calls appEnv with no vars, feature, ssh or forgeToken. Add a case that passes operator vars named FORGE_EDGE_TOKEN, PORT and FORGE_APP_DATA and asserts the forge's values win. That is the bypass the comment in appEnv guards against, and it is not pinned yet.
  2. Land #10450, the live run inside the pod, so the table stops saying code read and starts saying observed.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs