docs(ai): spec binding the II delegation guard to the derivation origin - #13956
docs(ai): spec binding the II delegation guard to the derivation origin#13956AntonioVentilii wants to merge 1 commit into
Conversation
The guard proves a delegation came from Internet Identity but never checks which frontend origin it was derived for, so one anchor can mint a distinct principal per origin and multiply its signer allowance and rate-limit buckets. The origin cannot be recovered from the chain: II hashes it into the seed with a canister-private salt, and the signed delegation message omits it. The spec uses II certified attributes instead, whose signature is made under the same origin-derived user key and whose message carries implicit:origin.
|
✅ No security or compliance issues detected. Reviewed everything up to 7560542. Security Overview
Detected Code Changes
|
There was a problem hiding this comment.
🟢 Approval recommended
It is a docs-only change that adds a well-scoped implementation spec and does not modify runtime behavior.
Pull request overview
Adds a new spec document describing a defense-in-depth design to bind the backend’s Internet Identity (II) delegation guard to the configured derivation origin, addressing a quota-multiplication vector where a single II anchor can mint multiple principals by varying the frontend origin. The spec proposes using II’s ICRC-3 certified attributes (implicit:origin + canister-signature verification) as a second signed artifact to cryptographically bind the caller to an allowed origin, and outlines a staged rollout across several PRs.
Changes:
- Added a spec detailing the threat model, constraints (origin not recoverable from delegation chain), and proposed origin-proof mechanism.
- Defined the expected backend/frontend/config changes and a multi-PR rollout plan (with enforcement last).
- Captured open questions and pending decisions to resolve before implementation.
File summaries
| File | Description |
|---|---|
| docs/ai/spec-driven-development/specs/2026-09-07-impr-bind-ii-delegation-guard-to-derivation-origin.md | New spec documenting the origin-binding approach and rollout plan for the II delegation guard. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Motivation
The backend's II delegation guard (
src/backend/src/delegation.rs) proves that a caller holds a delegation issued by the configured Internet Identity canister, but it never checks which frontend origin that delegation was derived for. The backend already stores a canonicalderivation_originin its config;read_ii_verification_confignever reads it.II folds a caller-supplied frontend origin into the seed it derives the user identity from, so one ordinary anchor can obtain many valid chains, one per origin string, each authenticating as a different principal. Because allowances and rate limits are keyed by principal, a single anchor multiplies its quota: a fresh signer allowance over the shared patron per origin, and a fresh per-caller Bitcoin bucket per origin. This was reported through the bug-bounty programme and accepted as a defence-in-depth hardening; the blast radius is OISY's own operational cycles, not user funds or keys.
The reason this is a spec and not a one-line guard change: the origin is not recoverable from the delegation chain. II derives the seed as
SHA256(salt ‖ anchor ‖ frontend)with a canister-private salt, and the signed delegation message is("ic-request-auth-delegation", pubkey, expiration, targets)with no origin in it. No extra check on the existing payload can recover it, and a caller-supplied plaintext origin would be forgeable. The binding has to come from a second signed artifact.Changes
Adds
docs/ai/spec-driven-development/specs/2026-09-07-impr-bind-ii-delegation-guard-to-derivation-origin.md. Docs only, no code.The spec proposes II certified attributes (
prepare_icrc3_attributes/get_icrc3_attributes) as the binding. Their signature is made under the same origin-derived user key already carried inIIDelegationChain.public_key, and the signed message containsimplicit:origin,implicit:nonceandimplicit:issued_at_timestamp_ns. Since the guard already ties that key to the caller, verifying this second signature binds caller to origin transitively, using only the IC root key andverify_canister_sig, which the guard already uses. An empty attribute list is supported, so the proof carries no personal data.It also covers:
betasign in withderivationOriginset while other deployments do not), which needs a newalternative_originsconfig field and therefore a breaking-interface PR;dfx.jsonpins IIrelease-2026-03-06, which predates these methods; they land inrelease-2026-07-31;derivationOriginis set.Tests
None. Docs-only change; the format gate covers it. The verification steps, unit-test table and integration-test helper are specified for the implementation PRs.