Skip to content

fix(github-webhook): configurable target; fail closed when unconfigured - #44

Merged
carbon-evolution merged 1 commit into
mainfrom
fix/github-webhook-target
Oct 18, 2026
Merged

carbon-evolution merged 1 commit into
mainfrom
fix/github-webhook-target

Conversation

@carbon-evolution

Copy link
Copy Markdown
Owner

Summary

/api/github-webhook forwarded every delivery to a hardcoded Tailscale IP, http://100.68.100.15:3005/github/webhook, apparently the upstream author's Discord bot. Fixing that exposed a worse problem: with GITHUB_WEBHOOK_SECRET unset, the HMAC check was skipped entirely and any anonymous POST was relayed to that internal target.

Changes

  • Configurable target: GITHUB_WEBHOOK_FORWARD_URL.
  • Fail closed: unless both GITHUB_WEBHOOK_SECRET and GITHUB_WEBHOOK_FORWARD_URL are set, the route returns 503 "not configured" and forwards nothing.
  • Always verify: when configured, a valid x-hub-signature-256 (HMAC-SHA256, timingSafeEqual) is required: missing → 401, wrong → 401.
  • 10 s timeout on the forward request.
  • Documented in .env.example; README API table row updated.

Tests (route-hardening.test.ts, fetch stubbed)

Case Result
nothing set / secret only / URL only 503, no forward
configured, no signature / wrong signature 401, no forward
configured, signed non-JSON body rejected, no forward
configured, correctly signed forwarded to the configured URL with body, signature header and a timeout signal

4 of these fail against the previous code. The 3 that pass check behaviour it already had right.

tsc 0 · eslint . 0 errors · vitest (non-DB) 66/66 · next build ✅ · no 100.68.100.15 left in the repo.

Note for deployers

If you relied on the old behaviour, set both variables, e.g. GITHUB_WEBHOOK_FORWARD_URL=http://<bot-host>:3005/github/webhook, and configure the same secret on the GitHub webhook.

🤖 Generated with Claude Code

- Forward target comes from GITHUB_WEBHOOK_FORWARD_URL instead of the
  hardcoded Tailscale IP http://100.68.100.15:3005 (apparently the
  upstream author's Discord bot).
- Fail closed: the route returns 503 and forwards nothing unless both
  GITHUB_WEBHOOK_SECRET and GITHUB_WEBHOOK_FORWARD_URL are set. Before,
  with no secret the HMAC check was skipped and any anonymous POST was
  relayed to the internal target.
- With both set, a valid x-hub-signature-256 is always required.
- 10s timeout on the forward request.
- Documented in .env.example and the README API table.

7 tests in route-hardening.test.ts; 4 fail against the previous code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@carbon-evolution
carbon-evolution merged commit 45da475 into main Oct 18, 2026
7 checks passed
@carbon-evolution
carbon-evolution deleted the fix/github-webhook-target branch October 18, 2026 02:35
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