Skip to content

Deliver callbacks only to operator-approved origins - #32

Merged
jacobprall merged 5 commits into
mainfrom
codex/issue-22-callback-destination-policy
Oct 28, 2026
Merged

jacobprall merged 5 commits into
mainfrom
codex/issue-22-callback-destination-policy

Conversation

@starmorph

@starmorph starmorph commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Callback delivery runs on the workflow host, outside Sandbox egress rules, and followed redirects. An API caller could make the workflow POST to internal hosts.

  • The workflow reads CALLBACK_ALLOWED_ORIGINS, a comma-separated list of HTTPS origins (http://localhost:<port> allowed off Render). Unset means callbacks are off.
  • answerQuestion skips a callback whose origin isn't listed and logs deliver_skipped, so the parent doesn't wait on delivery retries. The reply is still available by polling.
  • deliverCallback re-checks the origin and sets redirect: "error".

The original version of this PR enforced the list on both the API and the workflow, with matching values required on both. That was trimmed to the workflow only, which is the trust boundary. The API keeps its existing URL check, so deployers set one optional value on one service. The variable isn't declared in render.yaml, so the Blueprint form doesn't get an extra prompt.

Upgrade note: a deployment that already uses callbacks must set CALLBACK_ALLOWED_ORIGINS on the workflow, or deliveries are skipped.

Fixes #22.

starmorph and others added 4 commits October 27, 2026 08:00
Delivery is the trust boundary: it runs on the workflow host, outside Sandbox
egress rules. The workflow skips a callback whose origin isn't listed in
CALLBACK_ALLOWED_ORIGINS (logged as deliver_skipped, so the parent doesn't
wait on retries), deliverCallback re-checks the origin, and fetch refuses
redirects. The API keeps its existing URL check, so deployers set one value
on one service instead of matching values on two.

Co-authored-by: Cursor <cursoragent@cursor.com>
Delivery is the trust boundary: it runs on the workflow host, outside Sandbox
egress rules. The workflow skips a callback whose origin isn't listed in
CALLBACK_ALLOWED_ORIGINS (logged as deliver_skipped, so the parent doesn't
wait on retries), deliverCallback re-checks the origin, and fetch refuses
redirects. The API keeps its existing URL check, so deployers set one value
on one service instead of matching values on two.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jacobprall jacobprall changed the title Restrict callbacks to operator-approved origins Deliver callbacks only to operator-approved origins Oct 28, 2026
@jacobprall
jacobprall merged commit 0c8f3d6 into main Oct 28, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[P1] Enforce approved callback destinations and reject unsafe redirects

2 participants