open-swe/.security-review/suppressions.json
Adam Moussa 8a9974c3c4
Some checks failed
CI / Lint (push) Waiting to run
CI / Format check (push) Waiting to run
CI / Unit tests (push) Waiting to run
CI / Playwright E2E (push) Waiting to run
Build & publish app artifacts / Publish + deploy (dev) (push) Has been cancelled
Build & publish app artifacts / Publish + deploy (prod) (push) Has been cancelled
Infra CD / Infra CI (pre-deploy) (push) Has been cancelled
Infra CD / Deploy open-swe-dev (push) Has been cancelled
Infra CD / Deploy open-swe-prod (push) Has been cancelled
feat: author Slack/dashboard/schedule commits + PRs as the app by default (#57) (#60)
* feat: default Slack/dashboard/schedule PRs + commits to the app identity (#57)

Slack/dashboard/schedule runs now author PRs and run git/gh operations as the
GitHub App seahaven-openswe[bot] by default (matching GitHub-issue runs), so the
self-review 422 is impossible by construction rather than guarded in the prompt.
A profile flag author_prs_as_user restores per-user attribution.

- open_pull_request._resolve_pr_author_token + auth.resolve_github_token: default
  to the installation token for these sources; per-user only when opted in.
- authorship: commit identity -> seahaven-openswe[bot] (numeric noreply;
  accepted Vercel-resolution risk, documented inline).
- self-trigger safety: INTERNAL_BOT_LOGINS + webapp/reviewer_reconcile/reply
  markers recognize seahaven-openswe[bot] (bot-authored events are now ours).

Supersedes the prompt-only guard in #58.

* fix: author commits as the app bot in the default path (SH-IDSPLIT-01)

Security review found the commit identity was NOT actually unified to the bot:
resolve_triggering_user_identity got a 403 from the installation token and fell
back to configurable['github_login'], so commits were still authored as the
triggering user (commit=user, push+PR=bot — a three-way split that missed the
stated goal). Now gate the triggering-user identity resolution on the same
default-bot decision as the token: slack/dashboard/schedule default to the app
bot identity unless author_prs_as_user is set.

* docs(security): record AUTHZ-SLACK-BOT-DEFAULT-001 as an accepted residual (#59)

Single-user deployment; bounded by App-on-pilot + ALLOWED_GITHUB_REPOS lock.
Revisit (add a per-user gate) before expanding users or the App installation.
2026-06-29 14:22:33 -04:00

128 lines
9.2 KiB
JSON

{
"suppressions": [
{
"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": "OSWE-IAC-SECRETS-LIST-01",
"title": "EC2 instance role grants BatchGetSecretValue on \"*\" (operation-level; secret-NAME existence enumeration account-wide)",
"file": "infra/lib/constructs/instance-role.ts",
"severity": "low",
"status": "confirmed",
"suppression_justification": "ACCEPTED LOW residual, metadata-only. secretsmanager:BatchGetSecretValue is a collection action that AWS cannot scope to a per-secret ARN, so it is granted on `*` (documented in commit 3c69dd9d and the construct comment). Secret VALUES remain strictly gated by the PREFIX-scoped GetSecretValue/DescribeSecret on secret:open-swe-<env>/* (checked per-secret even within the batch), so cross-env VALUE isolation is preserved; only a name EXISTENCE oracle remains, within Sea Haven's single-tenant account 328440206208. ListSecrets is intentionally NOT granted (so name FILTER enumeration AccessDenies). Confirmed by GPT-4.1 IAM cross-review (no BLOCK) and the iac-iam detector (one low residual, no critical/high).",
"owner": "adam@seahavenind.com",
"added": "2026-06-26"
},
{
"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"
}
]
}