Execution-Envelope Identity Pinning
- Name: execution-envelope identity pinning
- Category: control-surface reference / privileged-execution design checklist / governance-and-upgrade safety reference / authorization-design note
- Summary: Healthy delayed privileged execution does not authenticate a naked address, proposal shell, or plugin label. It authenticates one full execution envelope as a single security object: the exact target or implementation code identity, the privileged call primitive (
callversusdelegatecall), the exact calldata or action list, and the admin or upgrade surfaces that could change any of those before execution. The sharper split this note tries to preserve is thatsome approved surface still exists,that surface still resolves to the same reviewed executable meaning, andthat surviving meaning still deserves this much authority right noware different review questions rather than one vaguethe approved address is still thereconclusion. This note exists to keep the positive design target explicit instead of making readers reconstructwhat correct approval should have meantonly by inverting approval-by-address, upgrade, and governance-takeover incidents. - Why this note exists:
- Many failures in the upgrade / governance branch do not begin with
bad code executed; they begin earlier, when review authenticated the wrong object. - The practical question is usually not
was the proposal malicious?butwhat exact thing did the protocol think it had approved for later privileged execution? - The useful design move is to make that answer machine-checkable: one stable execution envelope that review time and execution time both refer to.
- Many failures in the upgrade / governance branch do not begin with
The five joints a healthy execution envelope should keep fused
- Target identity
- The system must know which contract or module is supposed to execute under privilege.
This addressis only enough if that address cannot later resolve to different code or a different implementation.- This is the joint that breaks in approval-by-address-mutable-code-execution.
- Code identity
- The system must know what code is actually authorized: runtime bytecode hash, implementation hash, creation-code hash, or another equally stable identity.
- The safe question is not
is there still code at this address?butis this still the same code object we approved?
- Call primitive
call,delegatecall, module dispatch, and hook invocation are not interchangeable.- The same target may be safe under a bounded
callbut catastrophic underdelegatecallbecause storage and authority shift.
- Effect description
- The system should know the exact privileged effect set being authorized: immutable calldata, a queued action list, or a parameter-bounded operation bundle.
Some future call into this targetis not a stable approval object.
- Mutation path above the envelope
- The system must know which admin, upgrader, factory, proposer, or deployment path can still change the target, implementation, or payload before execution.
- If that mutability is real, it belongs inside the approved object rather than outside the threat model.
Three privileged-execution questions healthy systems should not collapse
-
Does some approved target, proposal shell, or plugin lane still exist?
- This is the narrow reachability question.
- It only answers
the approved address or executor label is still present and callable somehow.
-
Does that reachable surface still resolve to the same reviewed executable meaning?
- This is the identity-continuity question.
- It asks whether runtime code, implementation pointer, call primitive, payload commitment, and delayed-execution story are still the same ones humans and policy systems thought they approved.
-
If the identity still matches, does this envelope still deserve this much authority right now?
- This is the authority-budget question.
- A surviving exact envelope may still deserve staged rollout, lower spend caps, narrower selectors, slower execution, or a fresh review if the trust mode, surrounding balances, or downstream dependencies changed since approval.
Healthy systems answer those three questions separately. They do not let the approved target still exists silently imply the executable meaning is unchanged, and they do not let the executable meaning is unchanged silently imply full original delegatecall, treasury, or upgrade authority is still justified under today's conditions.
What sound design looks like
- One reviewed object, one executed object
- Review-time artifacts and execution-time authority should point to the same machine-verifiable object.
- If humans review source code while the protocol later executes mutable runtime behavior, the protocol has already split the security object.
- Effects should be approved more often than executors
- The safest governance and admin systems queue concrete actions, not open-ended executors.
- When possible, approve
call target X with calldata Yor an action bundle with explicit bounds, notdelegatecall whatever lives here later.
- Proxy mutability should never be treated as a deployment detail
- If a proxy or module can change implementation before execution, that fact belongs inside the approval envelope.
- Healthy systems either pin the implementation hash too, constrain the proxy admin path, or re-check the live implementation at execution time.
- Delayed execution must preserve code identity across time
- Timelocks, queued proposals, scheduled upgrades, and allowlists should all assume that time creates attack surface.
- The longer the gap between review and execution, the less acceptable address-only authentication becomes.
- Authority budget can shrink even when identity stays pinned
Same reviewed envelopeis still weaker thansame reviewed envelope still deserves full privilege under today's balances, trust mode, and downstream dependence.- Healthy systems can keep identity continuity while still forcing staged rollouts, narrower selectors, smaller spend caps, or fresh approval for unusually dangerous replays.
- Privilege shape should be explicit
- A system should be able to say whether execution is a plain external call, a storage-mutating delegatecall, a module enablement, a plugin install, or an upgrade.
- That execution shape is part of the reviewed object, not an implementation footnote.
Healthy architectural shapes
1. Explicit action-list governance
- The cleanest delayed-execution design approves an ordered list of specific calls with explicit targets, selectors, parameters, and value transfers.
- The proposal object is the effect description itself, not an open-ended contract waiting to be executed later.
- This shape limits the distance between what voters read and what root authority later does.
- timelock-action-bundle-commitment is the narrower companion when the sharper question is how timelocks and proposal systems should freeze that exact action list into one machine-checkable delayed-execution object.
2. Codehash-pinned executable modules
- If a protocol truly needs external executors, plugins, or proposal contracts, it should pin code identity directly.
- That can mean runtime hash checks, implementation-hash checks for proxies, or another verifier that guarantees review and execution still refer to the same executable object.
- The key property is that
same address, different codedoes not stay a valid execution path.
3. Revalidation at execution time
- If some flexibility must remain until execution, the protocol should re-validate the envelope right before the privileged call.
- Revalidation should include code identity, implementation pointer, allowed call primitive, and any immutable payload commitments.
Address is still deployedis not real revalidation.
4. Scoped upgrade paths around approved executors
- If an approved executor or proxy remains upgradeable, its upgrade authority needs stricter containment than ordinary application logic.
- The healthiest pattern is often
upgrades to the executor must themselves go through a separate delayed, hash-pinned review path. - Otherwise the protocol silently turns one approved executor into a standing privileged-upgrade surface.
Design questions worth asking first
- What exact machine-readable object did governance, review, or allowlisting approve?
- Could the same address resolve to different runtime or implementation code before execution?
- Is the privileged call a
call, adelegatecall, a module installation, or something else that changes the real blast radius? - Is the approved object an effect description, or merely a pointer to something that can still decide its own effects later?
- Which admin, upgrader, factory, or deployment path can still mutate the target or payload between approval and execution?
- If the protocol claims to review code offchain, what onchain check proves that the later executed code is still that reviewed artifact?
Red flags that usually mean the protocol is authenticating the wrong thing
We approved the addresswith no statement about code hash, implementation pointer, or immutable calldata.The contract is reputablewhen the approved surface is actually an upgradeable proxy or rebindable module.The timelock protects useven though nothing pins the code or payload across the timelock window.The proposal contract was auditedwhen execution later depends on runtime bytecode that can still change.The module is already allowlistedwhen the allowlist never authenticated the privilege shape or the code identity.The target still existsused as if liveness proved sameness.
Failure-prevention checklist
- Bind review, voting, and execution to one machine-checkable execution envelope: target address, runtime or implementation hash, privileged call primitive, exact calldata or ordered action bundle, and the mutation paths that could still change any of those before execution.
- Prefer approving concrete effects over approving open-ended executors. Queued action lists, selector-bounded modules, and immutable payload commitments age more safely than
delegatecall this address later. - Re-check code identity immediately before privileged execution, especially across timelocks, queued proposals, module installs, and proxy-mediated upgrades.
Address still existsis not a meaningful integrity check. - Re-justify authority budget at execution time when the environment changed materially. The same pinned envelope may deserve smaller spend caps, narrower selectors, delayed activation, or a fresh vote once balances, dependencies, or trust assumptions drift.
- Treat proxies, module registries, plugin managers, factories, and implementation slots as part of the same authorization object. If any of them can rewrite what the approved target means, they belong inside the review envelope.
- Make the execution primitive explicit in approvals and monitoring.
call,delegatecall, module enablement, upgrade, and hook dispatch imply different storage and authority reach even when the nominal target is the same. - Require simulation or fork-trace review against the final live envelope, not only against source repositories or proposal prose. Review should answer
what exact privileged writes and transfers can this object still produce now? - Keep user-facing proposal descriptions, security review artifacts, and monitor feeds derived from the same committed bytes the executor will later honor. Commentary should be a view of the object, not a substitute for it.
- Give defenders a real cancellation, veto, or pause path when envelope drift is detected during the delay window. Identity pinning is strongest when the system can still act on a mismatch.
- Emit approval-time and execution-time metadata for code hash, implementation pointer, call primitive, and payload hash so monitors can detect drift before funds or governance authority are gone.
- Bound the blast radius anyway: privilege tiering, rate limits, staged upgrades, and post-execution sanity checks should assume one mis-pinned execution envelope will eventually slip through.
Audit prompts
- What exact object is being authenticated here: address, runtime hash, implementation hash, immutable calldata, ordered call bundle, or a looser human review artifact?
- Could the same approved address resolve to different behavior before execution through proxy upgrades, beacon changes, module rebinding, factory redeployments, plugin installs, or delayed state-dependent dispatch?
- Does any privileged path still rely on
delegatecallinto externally supplied or previously approved code? If so, what storage and asset authority does that code inherit? - If the system says a proposal or module was reviewed offchain, what onchain check proves the later executed artifact is still that reviewed object?
- Are proposal UIs, timelocks, and allowlist dashboards showing the actual live implementation, call primitive, and payload commitment, or only a target label and a source link?
- Which admin, upgrader, registry owner, factory, or deployer can still mutate the execution envelope after review but before execution?
- If the envelope identity still matches, does it still deserve the same privilege tier now, or should balances, trust mode, rollout stage, or downstream dependence have forced a narrower authority budget first?
- Can monitors reconstruct the exact privileged story from onchain state alone, or do they still need forum posts, source-code assumptions, and trust that deployments have not drifted?
- If drift were detected right before execution, who can stop it and how fast can they act relative to the remaining delay window?
- Would the same approval still look acceptable if reviewers were forced to sign off on the exact execution envelope instead of the current higher-level abstraction? If not, the approval surface is underspecified.
- Where does the protocol intentionally preserve flexibility, and why is that flexibility worth the extra privileged-execution risk?
Lessons that should already be standard
Same addressis never the full answer when privileged meaning lives in bytecode, implementation pointers, module bindings, or delayed call bundles.- Review should authenticate the exact thing that later executes. If humans review source, prose, or reputation while the protocol later trusts mutable live artifacts, the security object is already split.
Delegatecallchanges the meaning of trust. A target that is safe to call as an ordinary external integration can become root authority when it runs in caller storage.- Timelocks only buy safety if the delayed object stays identical. A waiting period around mutable execution state is just ambiguity with a countdown timer.
- Approval pipelines are security-critical infrastructure. Proposal UIs, explorer renderings, and allowlist dashboards can create real risk when they hide code identity, implementation drift, or privileged call shape.
- Mutation paths above the nominal target are part of the attack surface. Proxy admins, factories, registry owners, and module managers often matter as much as the contract the UI highlights.
- Identity continuity is still not authority-budget continuity. A perfectly pinned executor may still deserve a smaller lane, slower rollout, or fresh ceremony once the surrounding risk changed.
- Healthy systems make uncertainty shrink as execution approaches. Review, queueing, monitoring, and execution should progressively narrow the possible effect set instead of preserving room for reinterpretation.
- Identity pinning is a control-surface discipline, not a one-off patch. The question should become routine:
what exact machine-verifiable object are we authorizing to act with privilege later?
Where this note helps most
- Start here when the sharper question is
what should healthy delayed privileged execution have authenticated in the first place? - Drop into approval-by-address-mutable-code-execution when the concrete failure is that review approved an address while execution later resolved to different code.
- Drop into privileged-upgrade-abuse when the attacker already controls the formal upgrade authority and simply uses it directly.
- Pair with governance-capture when the broader question is how governance became root authority at all.
- Pair with blind-sign-payload-substitution when the failure is not onchain address drift but signer tooling that showed operators one execution envelope while collecting approval for another.
Internal linkages
- Positive-design companion to approval-by-address-mutable-code-execution.
- Narrower timelock / proposal-system companion: timelock-action-bundle-commitment.
- Adjacent privileged-control family: privileged-upgrade-abuse.
- Adjacent governance family: governance-capture, backstop-failure-governance-capture.
- Adjacent signer-intent family: blind-sign-payload-substitution.
- Best current exploit-side case studies: tornado-cash-governance-proposal-smuggling-takeover-2023-05-20 for
approved address, different bytecode later, and furucombo-aave-v2-proxy-whitelist-mutable-implementation-approval-drain-2021-02-27 forapproved proxy address, mutable implementation later.
Control surface
-
The decisive control surface is not just proposal text or an allowlisted address.
-
It is the whole execution envelope: target identity, code identity, call primitive, concrete effect description, and every admin path that could mutate those before root authority is exercised.
-
Healthy systems make that envelope explicit enough that review-time trust and execution-time authority still refer to the same thing.
-
Sources:
- https://composable-security.com/blog/understanding-the-tornado-cash-governance-attack/
- https://medium.com/@zan.top/unpacking-the-tornado-cash-governance-attack-15b40691ca2e
- https://medium.com/furucombo/furucombo-post-mortem-march-2021-ad19afd415e
- https://cmichel.io/replaying-ethereum-hacks-furucombo/
- https://docs.openzeppelin.com/upgrades-plugins/proxies
- https://eips.ethereum.org/EIPS/eip-1014
- https://eips.ethereum.org/EIPS/eip-6780
-
Last reviewed: 2026-07-28 UTC