Skip to content

fix(authz): discard typed approvals from non-local ingress - #1422

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-10678-security-authenticate-approval-correlation-validator-gate
Oct 15, 2026
Merged

TheGreatAxios merged 1 commit into
mainfrom
cl-10678-security-authenticate-approval-correlation-validator-gate

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • Typed approval.granted / approval.denied messages are now provenance-authenticated at the app's single inbound-delivery funnel: any typed approval lacking the local approval-delivery sender + mailbox is discarded before it can correlate a parked call — fail-closed on missing mailbox — and the discard emits a structured receipt so forgery probes are visible instead of silent.
  • Rationale: a correlation ID on the approval rail is a bearer capability. Upstream removed expectedFrom and ships a CorrelationValidator seam no production layer injects into (the vendored agent layer has no field to carry one), so a learned ID plus a forged approval re-granted grantOneShot and re-dispatched the parked call. The same policy ships as a conforming CorrelationValidator and is exercised through the vendored injection point by an e2e regression, so the delivery gate and the validator cannot drift.
  • GateID/liveness binding remains owned by the vendored isLiveApproval; docs/VENDORING.md documents correlation IDs as bearer capabilities and the provenance model. decisionMessage now draws its sender/mailbox from the same shared constants, so the authentic sender and the allowlist are one source of truth.
  • Rule-out notes for review: agent.send call sites are all app-authored operator/completion flows (no ingress constructs approvals through them) — a follow-up ticket should exist if a future lane adds external feeds that build InboundMessages for agent.send.

Verification

  • Failing-test-first: e2e/reactor-approval-acceptance.test.ts regressed red on the untouched tree (foreign-ingress approval.granted with a live correlation id accepted — the exact bypass), then green: forgery discarded, real operator approval succeeds after (correlated resume + grant + tool run + resume observed).
  • bun run check exit 0: full suite 8952 pass / 0 fail across 581 files (failing-test +1 test count visible in the delta).
  • Targeted: src/session/approval-provenance.test.ts (12 tests; fail-closed matrix incl. ref-less forgery discard + receipt assertions), e2e/reactor-approval-acceptance.test.ts, src/session/approval-resume.test.ts, src/session/approval-resume-interrupt.test.ts.
  • git diff --stat -- vendor/ on the branch is empty; the vendored layer is untouched.

Fixes CL-10678

A correlation ID on the approval rail is a bearer capability: upstream
deleted expectedFrom and shipped a validator seam no production layer
injected into, so any message carrying a live correlation id re-granted
a parked call. Approval delivery is now provenance-authenticated at the
app's single inbound funnel, fail-closed on unknown mailboxes, with a
forged-message receipt so probes are visible; the same policy ships as
a conforming CorrelationValidator for the vendored injection point.
@linear-code

linear-code Bot commented Oct 14, 2026

Copy link
Copy Markdown

CL-10678

@corbits-triage

corbits-triage Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by the comment below.

@corbits-triage

Copy link
Copy Markdown
Contributor

This supersedes the comment above because the rules changed: repository policy version 4 → version 16.

Triage: Unsure

Not yet confirmed, a maintainer will check:

  • meets "this is bug free?"
  • meets "t"

@TheGreatAxios
TheGreatAxios merged commit 152139f into main Oct 15, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant