{ "suppressions": [ { "id": "AUTHZ-CLEAN-AUTOAPPROVE-INJECTION-001", "title": "Clean-review auto-approve derives APPROVE authority from a model-controlled signal on the untrusted auto-review path (prompt-injection-mintable APPROVE)", "file": "agent/tools/publish_review.py", "severity": "high", "status": "confirmed", "suppression_justification": "ACCEPTED (Adam, 2026-07-21) as a knowingly-deferred risk merged into the dev integration branch via admin merge in PR #217. /sh-security-review returned BLOCK: moving `approve` authorization from the deterministic verdict_requested flag to open_findings_count==0 lets a prompt-injected auto-review (which never sets verdict_requested) land a real bot APPROVE on an attacker-controlled external/fork PR, potentially satisfying branch protection. This reintroduces the hole PR #214 closed. Merged to dev only (NOT main/prod). Compensating controls: (a) confirm dev does not auto-deploy to sh-openswe; (b) on sensitive repos, esp. payments-dashboard, configure rulesets so the seahaven-openswe[bot] APPROVE does not by itself satisfy required approvals. Tracked in issue #218 with the full redesign checklist. REVISIT TRIGGER: MUST be resolved before this change promotes from dev to main/prod, and immediately if dev is found to auto-deploy. Verified HIGH by the sh-security-review detector fan-out (6 independent detectors converged).", "owner": "adam@seahavenind.com", "added": "2026-07-21" }, { "id": "AUTHZ-CLEAN-AUTOAPPROVE-THREADLAUNDER-002", "title": "Clean-review auto-approve gate reads reconcile-derived finding status, so a PR author can launder a dirty PR to clean via GitHub thread resolve/outdate", "file": "agent/tools/publish_review.py", "severity": "high", "status": "confirmed", "suppression_justification": "ACCEPTED (Adam, 2026-07-21), deferred with AUTHZ-CLEAN-AUTOAPPROVE-INJECTION-001 in PR #217 (admin-merged to dev). The open_findings_count gate reads finding status after reconcile_findings_with_review_threads, which flips open->resolved when the GitHub thread is is_resolved/is_outdated — both author-controllable ('Resolve conversation' or a trivial hunk-outdating commit) without fixing the defect, yielding an auto-approve on an unfixed PR. Same compensating controls and revisit trigger as ...-001. Tracked in issue #218 (redesign: compute the gate from the reviewer's own authoritative finding state, not author-influenced thread state). Verified HIGH by /sh-security-review.", "owner": "adam@seahavenind.com", "added": "2026-07-21" }, { "id": "AUTHZ-SLACK-BOT-DEFAULT-001", "title": "Slack entrypoint lacks a per-user repo-access check; default-bot PR authoring removes the implicit per-user repo boundary", "file": "agent/webapp.py", "severity": "medium", "status": "confirmed", "suppression_justification": "ACCEPTED (Adam, 2026-06-29) while Open SWE has a SINGLE user. The Slack run entrypoint does not call require_repo_access_for_user (dashboard/schedule do), so with the default App installation token a mapped Slack user could act on any repo in the App's installation regardless of their own access. Bounded by the compensating controls: the seahaven-openswe App is installed on open-swe-pilot ONLY and ALLOWED_GITHUB_REPOS is locked, so the bot token cannot reach repos outside the pilot, and the only triggering user is the owner. Tracked as open issue #59 with three remediation options. REVISIT TRIGGER: before expanding the user base OR broadening the App's installation beyond open-swe-pilot — at that point this becomes HIGH and a gate (option (c): per-user check when a token exists) must be added. Verified medium (not high) by /sh-security-review proof-or-kill verifier.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-89", "title": "Hardcoded credential flagged in encryption-roundtrip test fixture (CWE-798)", "file": "tests/test_team_credentials.py", "line": 89, "rule": "CWE-798", "severity": "low", "status": "false-positive", "justification": "Test fixture, not a real credential. The value \"secret-api-1234\" is a fake Datadog API key used by test_datadog_roundtrip_and_redaction to assert that the plaintext key is recoverable after an encrypt/decrypt round-trip (and that the stored record holds ciphertext, not the plaintext). It is never a live secret and is scoped to the unit test only.", "suppression_justification": "Test fixture, not a real credential. The value \"secret-api-1234\" is a fake Datadog API key used by test_datadog_roundtrip_and_redaction to assert that the plaintext key is recoverable after an encrypt/decrypt round-trip. It is never a live secret and is scoped to the unit test only.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-79", "title": "Hardcoded credential flagged in encryption-roundtrip test fixture (CWE-798)", "file": "tests/test_team_credentials.py", "line": 79, "rule": "CWE-798", "severity": "low", "status": "false-positive", "justification": "Test fixture, not a real credential. Same fake Datadog API key \"secret-api-1234\" passed into connect_datadog by test_datadog_roundtrip_and_redaction. Never a live secret; scoped to the unit test only.", "suppression_justification": "Test fixture, not a real credential. Same fake Datadog API key \"secret-api-1234\" passed into connect_datadog by test_datadog_roundtrip_and_redaction. Never a live secret; scoped to the unit test only.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-23", "title": "Hardcoded credential flagged in GitHub-token TTL test fixture (CWE-798)", "file": "tests/test_github_token_ttl.py", "line": 23, "rule": "CWE-798", "severity": "high", "status": "false-positive", "justification": "Test fixture, not a real credential. The literal \"ghp_secret\" is a fake GitHub token used by the cached-token TTL/revocation unit tests. Not a valid 40-char GitHub PAT, never a live secret, scoped to the unit test only.", "suppression_justification": "Test fixture, not a real credential. The literal \"ghp_secret\" is a fake GitHub token used by the cached-token TTL/revocation unit tests. Not a valid 40-char GitHub PAT, never a live secret, scoped to the unit test only.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-24", "title": "Dev-only CI env value flagged in .env.ci (history-only; file not at HEAD)", "file": ".env.ci", "line": 24, "rule": "gitleaks-generic-api-key", "severity": "high", "status": "false-positive", "justification": "False positive. .env.ci is the e2e CI env file (added in commit 5a52b9b2 'ci: run playwright e2e tests') holding DELIBERATELY-FAKE, dev-only values explicitly marked 'committed intentionally' (e.g. GITHUB_WEBHOOK_SECRET=dev-secret and a dev-only Fernet TOKEN_ENCRYPTION_KEY used solely by the Playwright e2e suite). No production secret: real prod values live in Secrets Manager (open-swe-prod/*). gitleaks scans committed history so it flags this even though the file is not present at HEAD.", "suppression_justification": "Dev-only CI fixture value, intentionally committed for the e2e suite; not a production secret (prod secrets are in Secrets Manager). Flagged from git history; file not present at HEAD.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-3", "title": "Placeholder flagged in .env.example (history-only; file not at HEAD)", "file": ".env.example", "line": 3, "rule": "gitleaks-generic-api-key", "severity": "high", "status": "false-positive", "justification": "False positive. .env.example contains placeholder/example values only, by definition not real secrets. gitleaks scans committed history so it flags the placeholder even though the file is not present at HEAD.", "suppression_justification": "Example/placeholder value in a committed .env.example; flagged from git history. Not a real secret.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-private-key-1", "title": "Fake CI RSA key flagged in .github/ci/fake_github_app_key.pem (history-only)", "file": ".github/ci/fake_github_app_key.pem", "line": 1, "rule": "gitleaks-private-key", "severity": "high", "status": "false-positive", "justification": "False positive. This is a throwaway test RSA key (the filename is literally 'fake_github_app_key.pem') referenced by .env.ci for the Playwright e2e suite. It is not a production GitHub App key (the real prod key is in Secrets Manager open-swe-prod/GITHUB_APP_PRIVATE_KEY). gitleaks scans committed history; the file is not present at HEAD.", "suppression_justification": "Deliberately-fake CI test key for the e2e suite; not a production GitHub App key. Flagged from git history; file not present at HEAD.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-private-key-185", "title": "Documentation example PEM flagged in INSTALLATION.md (CWE-798)", "file": "INSTALLATION.md", "line": 185, "rule": "gitleaks-private-key", "severity": "high", "status": "false-positive", "justification": "False positive. INSTALLATION.md shows the .env format with an example GITHUB_APP_PRIVATE_KEY=\"-----BEGIN RSA PRIVATE KEY-----...\" block in the setup instructions. It is illustrative documentation, not a real key.", "suppression_justification": "Documentation example of the GITHUB_APP_PRIVATE_KEY .env format in INSTALLATION.md; not a real key.", "owner": "adam@seahavenind.com", "added": "2026-06-29" }, { "id": "gitleaks-generic-api-key-29", "title": "README prose flagged as a generic API key (CWE-798)", "file": "README.md", "line": 29, "rule": "gitleaks-generic-api-key", "severity": "high", "status": "false-positive", "justification": "False positive. README.md line 29 is descriptive project prose (the 'Open SWE is the open-source version...' paragraph / blog link); gitleaks' generic-api-key entropy heuristic mis-matched a token in the text. No secret is present.", "suppression_justification": "README descriptive prose mis-matched by the generic-api-key entropy heuristic; no secret present.", "owner": "adam@seahavenind.com", "added": "2026-06-29" } ] }