Skip to content

fix(security): the webhook receiver answers every refusal with the same 403 - #534

Merged
jwvanderstam merged 2 commits into
mainfrom
fix/webhook-no-existence-oracle
Nov 11, 2026
Merged

jwvanderstam merged 2 commits into
mainfrom
fix/webhook-no-existence-oracle

Conversation

@jwvanderstam

Copy link
Copy Markdown
Owner

What

A follow-up from the separate security review of #528 (Info/Low).

POST /api/connectors/{connector_id}/webhook is the one public receiver: the connector id plus its mandatory secret is the credential. It answered 404 for an unknown id and 400 ("Not a webhook connector") for a connector of another type, both before checking the secret. An anonymous caller could therefore enumerate which connector ids exist and which of them are webhooks.

Change

The following refusals now return one identical response, 403 {"success": false, "message": "Forbidden"}:

  • a missing connector;
  • a connector of another type;
  • a webhook connector without a secret;
  • a wrong secret.

The server-side logs still distinguish a missing secret from a bad one. Nothing changes after the secret is proven (503 when inactive, 400 for an invalid payload, 200).

Tests

  • test_every_refusal_before_the_secret_reads_the_same, parametrised over missing, other type and wrong secret, asserts the exact status and body. It fails on the old code for the missing and other-type cases.
  • The over-the-wire contract test now expects 403 for an unknown connector.
  • Connector route, RBAC and authz-by-default suites: 115 passed. ruff is clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KkWPqAcWbxfqz1aCP6Qsdx

…me 403

POST /api/connectors/{id}/webhook is public, and answered 404 for an unknown
connector and 400 for one of another type before checking the secret, so an
anonymous caller could learn which connector ids exist and which are webhooks.
A missing connector, another type, a connector without a secret and a wrong
secret now all return the same 403.

Found by the separate review of #528. The parametrised test fails on the old
code for the missing and wrong-type cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkWPqAcWbxfqz1aCP6Qsdx
Copilot AI balanced review requested due to automatic review settings November 8, 2026 21:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Conflicts were side-by-side additions to CHANGELOG, file-map and the docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 00:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@sonarqubecloud

Copy link
Copy Markdown

@jwvanderstam
jwvanderstam merged commit 3cc5b32 into main Nov 11, 2026
17 checks passed
@jwvanderstam
jwvanderstam deleted the fix/webhook-no-existence-oracle branch November 11, 2026 01:17
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.

2 participants