Skip to content

feat(policy): classify raw extension proposals as untrusted - #78

Draft
seonghobae wants to merge 10 commits into
feat/extension-action-proposal-policyfrom
feat/extension-message-action-proposal
Draft

feat(policy): classify raw extension proposals as untrusted#78
seonghobae wants to merge 10 commits into
feat/extension-action-proposal-policyfrom
feat/extension-message-action-proposal

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Partial implementation of #27, stacked on PR #76.

Buyer/security gap

PR #76 composes exact extension proposal authority with ordinary action policy, but it accepts an already-constructed ActionRequest. A raw extension-message adapter must not be able to construct that request with InstructionSource::User or EnterprisePolicy merely because extension transport delivered the message, and it must retain the parent’s current origin and trusted-time/expiry authority checks.

Live dependency / stack state

This Draft is stacked on current exact PR #76 head fc9c7348d367a0b6295d8e2f0289b0262ef3675f. Current exact contributor head is 663eb89c55cf6c2505c2cc115b491bda49d89bf5.

Fresh exact compare is ahead 10 / behind 0, with merge base exactly equal to the live prerequisite. Relative to #76 the child delta is limited to:

  • CHANGELOG.md;
  • crates/originweave-policy/src/lib.rs; and
  • crates/originweave-policy/tests/extension_message_action_proposal.rs.

Keep Draft while #76/#74 remain active. No prerequisite check, review, status, coverage, mergeability, or predecessor result transfers to this child.

TDD / dependency repair lineage

  1. Original test-only head dbe06efc006fda316201ba295af4b933a4b41f14 established the missing raw-message trust boundary before production exposed it.
  2. Production introduced ExtensionMessageActionProposal and evaluate_extension_message_action_proposal so raw extension-produced message content has no instruction-source selector and is internally classified as InstructionSource::WebContent.
  3. The live feat(policy): compose extension proposals with action policy #76 prerequisite later advanced its extension-access contract to bind proposal authority to request source origin plus caller-supplied trusted current time and exclusive grant expiry. The old child 0579e7a27c6dadd56b653938ed0fcd1ff08fef93 had diverged from the new parent: exact compare from live feat(policy): compose extension proposals with action policy #76 to that child was ahead 5 / behind 8 with an obsolete merge base.
  4. This branch was repaired non-destructively rather than abandoned or force-rebased. The current parent tree was merged into the existing canonical child, then only the child-owned raw-message boundary was reconstructed on top of the current parent API.
  5. Focused regressions now additionally prove that a raw extension message cannot reuse a proposal grant for another source origin and cannot reuse an expired grant. The existing missing-grant, untrusted-instruction, and secret-material regressions remain intact.
  6. CI on reconstruction head 581ff56d91212b12c66ce9e20a95442a7949924f reached full tests/Clippy/rustdoc behavior but exposed only canonical rustfmt import wrapping. Current head 663eb89c55cf6c2505c2cc115b491bda49d89bf5 applies only that formatting correction; no authority or evidence gate was weakened.

Implemented boundary

ExtensionMessageActionProposal and evaluate_extension_message_action_proposal now:

  • carry typed action, source/target origin, secret-delivery metadata, and immutable intent digest but expose no instruction-source selector;
  • require exact extension identity, browser session, browsing context, proposal capability, proposal source origin, and trusted current time through the existing feat(policy): compose extension proposals with action policy #76 composition boundary;
  • fail closed when the proposal grant is absent, mismatched, bound to another origin, or expired;
  • construct the ordinary ActionRequest internally with InstructionSource::WebContent;
  • preserve the proposal’s action/origin/secret/digest fields unchanged when delegating to ordinary policy; and
  • therefore prevent extension-produced message content from minting human or enterprise instruction trust merely because extension transport delivered it.

now_epoch_seconds remains a trusted caller input; extension/page content cannot provide or attest it through this API.

Exact-current GREEN evidence

On unchanged exact head 663eb89c55cf6c2505c2cc115b491bda49d89bf5 against unchanged exact prerequisite fc9c7348d367a0b6295d8e2f0289b0262ef3675f:

  • ancestry: ahead 10 / behind 0, merge base exactly the live prerequisite;
  • CI run 32084014823: success;
  • Rust contracts job 95552634445: repository contracts, canonical formatting, locked workspace/all-target check, full tests, strict Clippy, and rustdoc success;
  • Production coverage job 95552634441: exact owned-production function, line, region, and branch measurement and enforcement success;
  • exact combined commit status returns CodeRabbit success;
  • formal reviews currently returned: none; and
  • inline review threads currently returned: none.

Security Scan, SAST, and central OpenCode/Noema/Strix/required-workflow evidence are not returned for this exact stacked head and are therefore absent, not passing. No predecessor, prerequisite, pre-reconstruction, queued, skipped, cancelled, absent, synthetic-merge, stale, status-only, or model-only evidence is promoted as current proof.

Truth boundary / remaining #27 work

A separately trusted future adapter may authenticate independent user or managed-policy provenance through a different explicit boundary. This lane does not parse Chromium extension messages, establish transport sender authenticity beyond the existing extension/session/context/origin/time grant, execute browser input, resolve secrets, verify post-conditions, persist managed-extension policy, or complete issue #27.

This scheduled actor does not merge, self-approve, alter workflows, add secrets, weaken checks, tag, or publish.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8bb98944-178b-4ec9-85a9-9ed31a00fc6d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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