Skip to content

fix: fail fast when WEBHOOK_SECRET is unset or equals "development" - #41

Merged
avrabe merged 1 commit into
mainfrom
fix/webhook-secret-fail-fast
May 1, 2026
Merged

fix: fail fast when WEBHOOK_SECRET is unset or equals "development"#41
avrabe merged 1 commit into
mainfrom
fix/webhook-secret-fail-fast

Conversation

@avrabe

@avrabe avrabe commented May 1, 2026

Copy link
Copy Markdown
Contributor

Fixes Bug #2 from docs/agent-fleet/bugs.md — wave-1 Security auditor's #1 high-severity finding.

Probot's webhook secret silently defaults to the literal "development" when env unset, so a misconfigured deploy accepts forged webhooks. Now assertWebhookSecret throws on unset / empty / whitespace / exact-development (substrings like development-secret-9f2c still accepted).

  • 813 tests pass (+7)
  • eslint clean

🤖 Generated with Claude Code

## Why
Probot defaults its webhook secret to the literal string `"development"`
when `WEBHOOK_SECRET` is unset. Without it, the bot **silently accepts forged
webhooks signed with that trivially-known string** — a complete trust-boundary
collapse on a misconfigured deploy.

Wave-1 Security auditor flagged this as Bug #2 in `docs/agent-fleet/bugs.md`,
the single highest-impact trust issue in the codebase.

## What
New exported `assertWebhookSecret(env = process.env)` in `src/app.js`. Throws
`Error` when `WEBHOOK_SECRET`:
- is missing or empty
- is whitespace-only
- equals the literal string `"development"` (exact match — substrings like
  `"development-secret-9f2c"` are accepted, since they could be legitimate
  in a dev environment)

`index.js` calls it after `mapLegacyEnvVars()` (so legacy
`GITHUB_WEBHOOK_SECRET → WEBHOOK_SECRET` mapping happens first) and before
`run(registerApp)`. The existing `try/catch` produces the standard
`Error starting Probot:` console output and exits non-zero.

`.env.example` updated with a comment explaining the constraint.

## Source
Wave-1 Security auditor (Bug #2, `docs/agent-fleet/bugs.md`).

## Test plan
- [x] 813 tests pass (was 806; +7 covering missing / empty / whitespace /
      exact-`development` / substring-`development*` / valid secret /
      reads-from-process.env-by-default)
- [x] eslint clean
- [ ] After deploy: stop pm2, unset `WEBHOOK_SECRET` in `/opt/temper/.env`,
      `pm2 start temper`. Bot should fail to start with a clear message
      instead of silently running with the fail-open default.

## Risk & rollout
- Risk: low for any deployment that already has a real secret configured.
  Will fail-fast for misconfigured deploys, which is the point.
- Rollout: self-update on merge. Operator must verify the env var is set
  before the bot tries to restart — the current netcup deploy already has
  it set.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avrabe
avrabe merged commit 86c5bdf into main May 1, 2026
5 checks passed
@avrabe
avrabe deleted the fix/webhook-secret-fail-fast branch May 1, 2026 07:15
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.

1 participant