docs(sec): CanisterWorm umbrella + 4 APPROVED sibling wishes#1360
Conversation
Splits monolithic sec-scan-progress into 4 parallel-shippable siblings
after dual-reviewer BLOCKED verdict on the monolith (H1 circular dep,
H2 three wish-sized scopes bundled, H3 unmerged base branch).
Artifacts:
- .genie/brainstorms/canisterworm-incident-response/DESIGN.md (umbrella)
- .genie/brainstorms/sec-scan-progress/{DESIGN,DRAFT}.md (source)
- .genie/wishes/sec-scan-progress/WISH.md (APPROVED, 5 groups)
- .genie/wishes/sec-scan-progress/REVIEW_GROUP_1.md (provisional SHIP)
- .genie/wishes/sec-remediate/WISH.md (APPROVED, 2 groups)
- .genie/wishes/genie-supply-chain-signing/WISH.md (APPROVED, 2 groups)
- .genie/wishes/sec-incident-runbook/WISH.md (APPROVED, 2 groups)
- .genie/brainstorm.md (sibling index entry)
Plan edits vs overnight drafts:
- Dropped fallback-key scope from signing (OIDC-keyless sufficient v1)
- Replaced two-officer ceremony with OIDC-identity rotation procedure
- Explicit merge gate: remediate G1 integration tests blocked on
signing G2 landing on dev (fixes the G6/G7 CI-failure trap)
- Flipped all 4 wish statuses DRAFT to APPROVED
Next: dispatch reviewer on wish/sec-scan-progress to validate G1.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
61a7203 to
ada610b
Compare
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 61a7203f34
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| | **Repos touched** | `automagik-dev/genie` | | ||
| | **Umbrella** | [canisterworm-incident-response/DESIGN.md](../../brainstorms/canisterworm-incident-response/DESIGN.md) | | ||
| | **Design** | [DESIGN.md](../../brainstorms/sec-scan-progress/DESIGN.md) | | ||
| | **Council** | [COUNCIL.md](../../brainstorms/sec-scan-progress/COUNCIL.md) | |
There was a problem hiding this comment.
Fix broken council link target in sibling wish headers
The new council links point to ../../brainstorms/sec-scan-progress/COUNCIL.md, but that file is not present in the repo, so bun run wishes:lint now fails and the standard check pipeline is blocked. This same missing target is repeated across the four new sibling wishes, so either the COUNCIL.md artifact must be committed or these header links must be updated to an existing path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Code Review
This pull request introduces a comprehensive incident response framework for the CanisterWorm compromise, splitting a previously monolithic plan into four distinct, parallelizable wishes: scanner progress and observability, auditable remediation (quarantine and rollback), supply-chain signing using Cosign and SLSA, and a formal incident runbook. The changes include detailed design documents, execution strategies, and success criteria for each component. Feedback provided addresses regex inconsistencies for incident IDs in the signing wish, filesystem compatibility issues for quarantine directories on Windows, and the use of more effective AWS credential revocation commands in the remediation templates.
| - Verification is offline-capable: pinned key travels with the package; cosign verify runs without network if `--offline` is passed (degrades to signature-only, no transparency-log check). | ||
|
|
||
| **`--unsafe-unverified <INCIDENT_ID>` exact contract** | ||
| - `INCIDENT_ID` must match regex `^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$` (e.g., `BURNED_KEY_2026_04_23`, `CI_PRE_SIGNING_2026_04_23_TEST_HARNESS`). |
There was a problem hiding this comment.
The specified regex ^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2} is inconsistent with the provided examples (e.g., BURNED_KEY_2026_04_23). The regex only allows a single uppercase word before the date, whereas the examples contain multiple words separated by underscores. Updating the regex to allow multiple prefix segments will ensure the contract matches the intended usage.
| - `INCIDENT_ID` must match regex `^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$` (e.g., `BURNED_KEY_2026_04_23`, `CI_PRE_SIGNING_2026_04_23_TEST_HARNESS`). | |
| - INCIDENT_ID must match regex ^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$ (e.g., BURNED_KEY_2026_04_23, CI_PRE_SIGNING_2026_04_23_TEST_HARNESS). | |
| + INCIDENT_ID must match regex ^([A-Z]+_)+[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$ (e.g., BURNED_KEY_2026_04_23, CI_PRE_SIGNING_2026_04_23_TEST_HARNESS). |
|
|
||
| **Deliverables:** | ||
| 1. `src/sec/unsafe-verify.ts` helper module: | ||
| - Exports `INCIDENT_ID_REGEX` = `/^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$/`. |
There was a problem hiding this comment.
This regex definition has the same inconsistency as noted in the summary section. It should be updated to support multi-word prefixes as shown in the test cases.
| - Exports `INCIDENT_ID_REGEX` = `/^[A-Z]+_[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$/`. | |
| - Exports INCIDENT_ID_REGEX = /^([A-Z]+_)+[0-9]{4}_[0-9]{2}_[0-9]{2}(_[A-Za-z0-9_]+)?$/. |
| - Prompt text per action: IOC hit, absolute path, action verb, sha256 prefix, one-line reason. | ||
|
|
||
| **Quarantine semantics** | ||
| - Quarantine is atomic `rename` into `~/.genie/sec-scan/quarantine/<iso-timestamp>/<action_id>/<original-basename>`. |
There was a problem hiding this comment.
Using a raw ISO timestamp in a directory name will cause failures on Windows systems (including NTFS and FAT32) because colons are prohibited in filenames. It is recommended to use a filesystem-safe timestamp format (e.g., YYYYMMDD-HHMMSS) or to explicitly state that colons must be replaced.
| - Quarantine is atomic `rename` into `~/.genie/sec-scan/quarantine/<iso-timestamp>/<action_id>/<original-basename>`. | |
| - Quarantine is atomic rename into ~/.genie/sec-scan/quarantine/<iso-timestamp>/<action_id>/<original-basename>. | |
| + Quarantine is atomic rename into ~/.genie/sec-scan/quarantine/<timestamp-safe>/<action_id>/<original-basename>. |
|
|
||
| **Credential rotation (command-emission only in v1)** | ||
| - `--apply` on a credential-rotation finding prints exact rotation commands to stdout and appends them to the audit log. Never calls APIs. | ||
| - Per-provider templates: npm (`npm token revoke`, with `npm token list` preamble), GitHub (`gh auth refresh --scopes` + manual URL for PAT rotation), cloud IAM (`aws sts get-caller-identity`, `gcloud auth revoke`, `az logout`), Anthropic/OpenAI (manual web-UI URLs with warning that no CLI rotation exists). |
There was a problem hiding this comment.
The command aws sts get-caller-identity is an informational command that returns the current identity but does not perform any revocation or rotation. To align with the other examples (gcloud auth revoke, az logout), consider suggesting a command that actually disables the credentials, such as aws iam update-access-key --access-key-id <ID> --status Inactive (after using get-caller-identity to find the ID).
| - Per-provider templates: npm (`npm token revoke`, with `npm token list` preamble), GitHub (`gh auth refresh --scopes` + manual URL for PAT rotation), cloud IAM (`aws sts get-caller-identity`, `gcloud auth revoke`, `az logout`), Anthropic/OpenAI (manual web-UI URLs with warning that no CLI rotation exists). | |
| - Per-provider templates: npm (npm token revoke, with npm token list preamble), GitHub (gh auth refresh --scopes + manual URL for PAT rotation), cloud IAM (aws sts get-caller-identity, gcloud auth revoke, az logout), Anthropic/OpenAI (manual web-UI URLs with warning that no CLI rotation exists). | |
| + Per-provider templates: npm (npm token revoke, with npm token list preamble), GitHub (gh auth refresh --scopes + manual URL for PAT rotation), cloud IAM (aws iam update-access-key --status Inactive, gcloud auth revoke, az logout), Anthropic/OpenAI (manual web-UI URLs with warning that no CLI rotation exists). |
…d contract (genie-supply-chain-signing) G1 — Release signing pipeline: - .github/workflows/release.yml: cosign KEYLESS signing + SLSA L3 provenance, signed before GitHub Release publish; self-verify + tamper-detection self-test gate the release. No long-lived fallback key anywhere. - .github/cosign.pub: explicit NO-PINNED-KEY sentinel (not a PEM); documents the keyless contract and instructs tooling to fail closed on the sentinel. - .github/ISSUE_TEMPLATE/signing-key-fingerprint.md: redirects pinned-key questions toward certificate-identity + OIDC-issuer verification. - scripts/verify-release.sh: operator-facing verification script pinning cert-identity-regexp + cert-oidc-issuer + provenance source-uri. - package.json: expose `bun run verify:release` alias. G2 — verify-install subcommand + --unsafe-unverified contract: - src/sec/unsafe-verify.ts: single source of truth for --unsafe-unverified <INCIDENT_ID>: INCIDENT_ID_REGEX, TYPED_ACK_PREFIX, LEGITIMATE_CONTEXTS, validateUnsafeUnverified. Council-mandated (M2→HIGH) to prevent divergent implementations eroding friction. - src/sec/unsafe-verify.test.ts: 35 tests covering regex edges, ack format, legitimate-context enumeration. - src/term-commands/sec.ts: `genie sec verify-install` — cosign verify-blob + slsa-verifier verify-artifact, pinned identity + OIDC issuer, --offline/ --json/--tarball/--bundle-dir flags. Public exit-code contract: VERIFIED(0), SIGNATURE_INVALID(2), SIGNER_IDENTITY_MISMATCH(3), PROVENANCE_INVALID(4), NO_SIGNATURE_MATERIAL(5), MISSING_BINARY(127). Sentinel detected → exit 5. - src/term-commands/sec.test.ts: 18 tests, including the sentinel→exit-5 guard. - docs/security/key-rotation.md: operator runbook for cosign keyless — there is no "key" to rotate, only cert-identity or OIDC-issuer changes. Follow-up: sec-remediate (#1361) currently holds a stub validator for its --unsafe-unverified flag; a separate integration PR will wire that flag to validateUnsafeUnverified from src/sec/unsafe-verify.ts. scripts/sec-scan.cjs and scripts/sec-remediate.cjs are intentionally untouched in this PR. Unblocks sec-incident-runbook (last wish in the canisterworm umbrella #1360). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits monolithic sec-scan-progress into 4 parallel-shippable siblings
after dual-reviewer BLOCKED verdict on the monolith (H1 circular dep,
H2 three wish-sized scopes bundled, H3 unmerged base branch).
Artifacts:
- .genie/brainstorms/canisterworm-incident-response/DESIGN.md (umbrella)
- .genie/brainstorms/sec-scan-progress/{DESIGN,DRAFT}.md (source)
- .genie/wishes/sec-scan-progress/WISH.md (APPROVED, 5 groups)
- .genie/wishes/sec-scan-progress/REVIEW_GROUP_1.md (provisional SHIP)
- .genie/wishes/sec-remediate/WISH.md (APPROVED, 2 groups)
- .genie/wishes/genie-supply-chain-signing/WISH.md (APPROVED, 2 groups)
- .genie/wishes/sec-incident-runbook/WISH.md (APPROVED, 2 groups)
- .genie/brainstorm.md (sibling index entry)
Plan edits vs overnight drafts:
- Dropped fallback-key scope from signing (OIDC-keyless sufficient v1)
- Replaced two-officer ceremony with OIDC-identity rotation procedure
- Explicit merge gate: remediate G1 integration tests blocked on
signing G2 landing on dev (fixes the G6/G7 CI-failure trap)
- Flipped all 4 wish statuses DRAFT to APPROVED
Next: dispatch reviewer on wish/sec-scan-progress to validate G1.
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
Splits the monolithic
sec-scan-progresswish into 4 parallel-shippable sibling wishes under thecanisterworm-incident-responseumbrella after dual-reviewer BLOCKED verdict on the monolith.Why the split
sec remediate --applyand release signingcodex/sec-scan-commandbasedevArtifacts shipped in this PR
Key plan edits vs. the drafts that were staged overnight
Execution pipeline after merge
Test plan
🤖 Generated with Claude Code