Third-Party Runtime Allowance and Integrity Pinning
- Name: third-party runtime allowance and integrity pinning
- Category: browser-delivery reference / third-party script policy note / wallet-facing CSP-SRI design checklist / runtime-loader hardening note
- Summary: Some browser-delivery incidents are not best answered only with
the real domain must stay under our control. A second, narrower design question matters too: what outside code is the real domain still allowed to execute on wallet-critical pages at all? Healthy signer-facing web apps treat third-party scripts, runtime loaders, polyfills, analytics tags, tag managers, wallet SDK bootstraps, and other remote browser dependencies as explicit execution rights on the signing surface. They minimize that set, pin identity tightly with local bundling, immutable URLs, Content Security Policy, Subresource Integrity, import-map pinning, or equivalent controls, and fail closed when those controls are not available. This note exists to keep that narrower browser-policy question separate from the broaderdid the canonical domain still prove the exact runtime bytes?question handled by canonical-domain-runtime-byte-integrity.
Fast classifier: which signer-surface runtime drift are you trying to prevent?
-
Stay here when the sharper design question is
what remote execution rights should exist on the real signer-facing page at all, and how tightly are they pinned? -
Use the shorthand
same real site, different loader-resolved bytesfor shared-loader cousins like Ledger Connect Kit, where the downstream domain stayed honest but signer-critical execution was still delegated to a mutable wallet SDK loader, package, or CDN path. -
Use the shorthand
same familiar runtime URL, different operator-resolved bytesfor service-identity cousins like Polyfill.io, where the trusted object in source control was a script URL or service identifier whose ownership and request-time output changed underneath it. -
Pivot first to canonical-domain-runtime-byte-integrity when the sharper question is what the real domain and bootstrap path should have proved before any signer-facing runtime was trusted.
-
Pivot first to release-provenance failure when the sharper question is which exact source / tarball / loader / CDN / runtime object drifted away from the thing people thought they had authenticated, and how rollback had to be proved at the executed-artifact layer.
-
Pivot first to software supply-chain compromise when the decisive compromise first lived upstream in a shared dependency or loader ecosystem that many otherwise honest downstream apps inherited.
-
Why this note exists:
The page came from our real domainis still too weak if that page can fetch mutable third-party code that changes spender prompts, wallet-connect flows, typed-data rendering, or signer-visible transaction previews.- Ledger Connect Kit preserves the
same real site, different loader-resolved byteswarning: honest downstream domains still delegated signer-critical execution to a mutable wallet-SDK loader path. - Polyfill-style incidents preserve the adjacent
same familiar runtime URL, different operator-resolved byteswarning: a familiar remote script URL can outlive the safety of the service behind it. - Many teams vaguely know to
use CSPorself-host critical JS, but the useful design object is more precise: which remote execution rights exist on wallet-critical pages, how tightly are they pinned, and what happens when one goes ambiguous?
The five joints a healthy third-party runtime policy should keep fused
- Explicit allowlist of execution-bearing dependencies
- The system should know exactly which third-party scripts, wallet SDK loaders, analytics tags, feature flags, polyfills, chat widgets, and tag-manager paths may run on wallet-critical pages.
Whatever the marketing site already includesis not a signer-surface policy.- If a dependency can shape wallet prompts, route users toward a connection method, mutate transaction parameters, or alter typed-data display, it belongs on the allowlist only by deliberate decision.
- Pinned identity, not brand familiarity
- Allowed third-party code should be pinned as tightly as the delivery shape permits: immutable self-hosted bundles, exact versioned URLs, Subresource Integrity, import-map pinning, signed artifacts, or equivalent content-binding controls.
Loaded from a reputable domainis routing information, not integrity.- Polyfill.io is the clean reminder that a stable script tag can survive while ownership and runtime behavior change underneath it.
- CSP and loader policy that actually narrows execution
- Content Security Policy should do real work: strict
script-src, sparse origins, nonce/hash policy where appropriate, and no broadunsafe-inline/unsafe-evalescape hatches on wallet-critical routes unless there is a very strong reason. - Tag-manager or remote-loader convenience that silently re-broadens execution rights defeats the point.
- A page does not meaningfully pin its runtime if one allowed bootstrap can still load arbitrary descendants.
- Content Security Policy should do real work: strict
- Wallet-critical route separation
- Marketing, analytics, support widgets, A/B tooling, and similar third-party code should be kept off pages that construct signatures, approvals, or transaction simulations whenever possible.
- The safest signer-facing page often has a much smaller runtime policy than the general site.
Same domainshould not forcesame third-party execution surface.
- Fail-closed behavior when pinning or policy weakens
- If a wallet-critical route cannot prove the identity of a remote script, loses CSP coverage, or sees an unexpected dependency, the safe behavior is to disable signing flows, serve a read-only state, or route users to a safer entrypoint.
- Recovery is not just
swap the script back; it is restoring the narrower execution policy that makes remote ambiguity non-authoritative.
What sound design looks like
- Wallet prompts should not depend on ambient website clutter
- Signer-facing code should be as close to locally bundled and minimally dependent as possible.
- If a third-party runtime dependency remains, the protocol should be able to explain why it is worth the signer-surface risk.
- CSP should express a real signer-surface boundary
- The useful standard is not
we set some headers; it iswallet-critical pages can only execute a very small, reviewed set of code origins and bootstrap paths. - CSP is a boundary tool only when the allowed set is intentionally narrow.
- The useful standard is not
- SRI and equivalent content binding should be used where they actually hold
- SRI helps when the fetched artifact is static and the browser can compare expected versus delivered bytes.
- If the integration model depends on mutable loader URLs, dynamically generated responses, or one bootstrap that can fetch arbitrary descendants, then SRI on one tag is only partial containment.
- Tag managers and remote script injectors should be treated like privileged deploy surfaces
- If a tag manager, consent manager, experimentation platform, or edge HTML rewrite can add script execution to a wallet page, it is not
just analytics; it is signer-surface code deployment.
- If a tag manager, consent manager, experimentation platform, or edge HTML rewrite can add script execution to a wallet page, it is not
- Runtime policy should be externally checkable
- Teams should be able to answer from the outside: what remote scripts are allowed on wallet-critical pages, what hashes or exact versions are expected, and what fetches would count as policy drift?
- Emergency replacement paths should exist before an incident
- Polyfill-style recovery showed that mirrors and edge-side HTML rewrites can be valuable, but also that they are constrained by the page’s existing runtime policy surface.
- If an emergency cutover would be blocked by CSP, route design, or loader assumptions, then the system does not really have a practical browser-side rollback plan yet.
- The steady-state goal is still to avoid mutable third-party execution on signer pages, but healthy teams also predesign how users stop fetching an ambiguous runtime before source-tree cleanup is complete.
Healthy architectural shapes
1. Self-host and bundle wallet-critical dependencies
- Prefer one locally served immutable bundle for signer-facing flows instead of many remote runtime dependencies.
- If a dependency is essential, strongly prefer ingesting it into the build artifact rather than executing it from a third-party host at page load.
- This shrinks the signer-surface policy from
trust our page plus their runtime servicetotrust one reviewed artifact lineage.
2. Give signing routes their own CSP profile
- Wallet-critical pages should often have a stricter CSP than the rest of the site.
- It is healthy if the marketing homepage can run tools that the
/swap,/vault, or/connectroutes categorically refuse to execute. - Separate route policy keeps business convenience from silently becoming signer authority.
3. Treat remote loaders as transitive execution rights
- A wallet SDK loader, analytics bootstrap, or import shim that can fetch more code is not one dependency; it is a delegated code-loading authority.
- Review should ask what that loader can later import, update, personalize, or region-select without a redeploy from the app owner.
- If the answer is broad, the true allowlist is broader than the page appears to declare.
4. Monitor dependency drift from the browser side
- Outside-in checks should record script URLs, CSP headers, integrity attributes, import maps, and the actual remote execution graph on wallet-critical pages.
- A passing availability probe is not enough if the signer-surface dependency set changed.
- The useful alert is often
new remote execution right appeared on a signing page.
5. Design safe degraded states in advance
- If a critical external runtime dependency breaks integrity guarantees, the application should know how to degrade safely: read-only mode, wallet-connect disablement, alternate static page, or explicit maintenance state.
- The goal is to make
cannot prove safe runtimeresolve tocannot ask for signatures.
Design questions worth asking first
- Which third-party scripts or loaders are still allowed to execute on wallet-critical pages right now?
- Which of those can directly or indirectly shape wallet prompts, typed-data text, spender addresses, routing, or connection methods?
- Are those dependencies self-hosted, version-pinned, SRI-pinned, import-map-pinned, or otherwise content-bound — or merely loaded from a trusted-looking domain?
- Does the wallet-critical route have a meaningfully stricter CSP than the rest of the site?
- Can one allowed bootstrap, tag manager, or remote loader still widen execution rights after initial page load?
- If one remote dependency becomes ambiguous or unavailable, does the signing surface fail closed or keep running anyway?
Red flags that usually mean the signer-surface script policy is underdesigned
It loads from our page, so it is our code now.- Wallet-critical routes share the same broad tag-manager and analytics surface as the marketing site.
- CSP exists, but
script-srcstill allows broad wildcards,unsafe-inline, or remote loaders that can fetch arbitrary descendants. - A third-party script is called
only analyticseven though it can inject HTML, add script tags, or influence signer-facing UI. - The team can list contract admins precisely but cannot list all remote execution rights on its wallet pages.
- One integrity-pinned script bootstraps another non-pinned loader, so the apparent trust boundary is narrower on paper than in runtime.
- Incident response can restore the main domain quickly but cannot answer whether wallet-critical pages are still executing any unexpected remote code.
Failure-prevention checklist
- Maintain a signer-surface allowlist of every remote script, loader, wallet SDK bootstrap, analytics tag, tag manager, polyfill, feature flag, or support widget that can execute on wallet-critical pages. If the list is not explicit, the runtime policy is already too broad.
- Prefer locally bundled, self-hosted, immutable artifacts for wallet-critical flows. Every mutable third-party runtime fetch should be treated as delegated signer-surface release authority that needs a specific justification.
- Use route-specific CSP and integrity controls for signing pages instead of inheriting the broader marketing-site policy. Wallet-critical routes should be allowed to execute materially less code than the rest of the domain.
- Treat remote loaders as transitive execution rights. If one approved bootstrap can fetch arbitrary descendants, then the true allowlist is the loader’s entire resolution policy, not the one initial script tag.
- Alert on new remote execution rights, changed script URLs, weakened CSP, missing integrity attributes, unexpected import-map changes, or newly active tag-manager branches on signer-facing pages.
- Design fail-closed behavior for runtime ambiguity: if a critical dependency loses pinning, resolves unexpectedly, or becomes unavailable, the safe response is to disable signature flows or serve a safer fallback page.
- Keep tag managers, experimentation platforms, chat widgets, and other business-convenience runtimes off wallet-critical pages unless they survive the same review standard as signer-facing application code.
- Rehearse browser-side incident response: force-version pins, local-bundle fallbacks, safe mirror cutovers, emergency HTML rewriting where appropriate, CSP tightening, feature disablement, and live verification that wallet pages stopped executing the ambiguous runtime.
- Know in advance whether an emergency mirror or edge-side rewrite would actually function on signer-critical routes without violating the route’s own CSP or bootstrap assumptions. A rollback path that only works on paper is not a control.
Audit prompts
- Which third-party scripts and loaders can execute on wallet-critical pages today, and which of them can directly or indirectly influence spender prompts, typed-data text, connection routing, or transaction previews?
- For each allowed dependency, what exactly is pinned: host, path, version, content hash, import-map target, or only a trusted-looking brand/domain?
- Do signer-facing routes have their own CSP and script policy, or do they still inherit broad marketing and analytics allowances from the rest of the site?
- Can any approved loader, tag manager, or consent manager widen execution rights after the initial page load without another review step?
- What monitoring would fire if a wallet-critical page suddenly began loading one new remote script or one known script from a new URL or integrity state?
- If one third-party runtime became ambiguous right now, would the page fail closed, or would it keep asking for signatures with a degraded and partially trusted execution surface?
- Would an emergency mirror swap, local override, or edge-side HTML rewrite actually work on each signer-critical route today, or would CSP / loader design quietly block the recovery path?
- Which external runtimes are still described internally as
just analyticsorjust supporteven though they can inject HTML, add script tags, or otherwise change signer-facing behavior? - Could the team prove from outside the app that wallet-critical pages are executing only the approved remote code graph, rather than only asserting that the intended script tags are present in source control?
Lessons that should already be standard
- Third-party runtime allowance is signer policy, not front-end housekeeping.
Loaded from our pageis not the same asunder our controlwhen the page still delegates execution to mutable remote code.- Route-specific CSP matters because wallet-critical pages should usually have a much smaller execution surface than the rest of the site.
- One trusted bootstrap that can fetch arbitrary descendants is already a broad remote-execution grant, even if the first tag looks tightly pinned.
- The right failure mode for runtime ambiguity is to stop asking for signatures, not to keep operating and hope the dependency is benign.
- Emergency mirrors and HTML rewrites are recovery tools, not integrity proofs. The durable answer is still to narrow what third-party code signer pages may execute in the first place.
- Teams that can enumerate contract admins but cannot enumerate signer-surface script rights are governing the wrong control plane with precision.
Where this note helps most
- Start here when the sharper question is
why was the real domain still allowed to execute mutable third-party code on a signing surface? - Drop into canonical-domain-runtime-byte-integrity when the broader question is what the real domain should have proved about registrar, DNS, CDN / edge, HTML bootstrap, and browser-fetched bytes.
- Drop into front-end compromise approval phishing when classifying
real site, malicious promptincidents. - Pair with release-provenance failure when the sharper question becomes how reviewed artifacts, runtime loaders, or delivered bytes drifted from intended production identity.
- Pair with exact-production-artifact-attestation-and-rollback-discipline when the broader recovery question is how to attest one full source-to-runtime lineage and prove rollback at the execution layer.
- Pair with software supply-chain compromise when the decisive compromise first lived upstream in a shared dependency or loader ecosystem rather than in one protocol’s own domain-delivery stack.
Internal linkages
- Broader browser-delivery companion: canonical-domain-runtime-byte-integrity.
- Closest exploit-family companion: frontend-compromise-approval-phishing.
- Adjacent release-integrity companion: release-provenance-failure.
- Broader recovery and attestation companion: exact-production-artifact-attestation-and-rollback-discipline.
- Adjacent upstream-dependency family: software-supply-chain-compromise.
- Best third-party runtime warning case: Polyfill.io.
- Useful shared-loader cousin: Ledger Connect Kit.
- Useful same-domain browser-delivery cousins: BadgerDAO and Curve Finance DNS hijack.
Control surface
-
The decisive control surface is the set of third-party execution rights that still exist on signer-facing pages: remote script hosts, loaders, tag managers, CSP policy, integrity attributes, import-map policy, self-hosting decisions, and the fallback behavior when any one of those turns ambiguous.
-
This note matters because many teams secure the domain broadly but leave the signer surface porous through
temporaryexternal runtimes that can still change what wallets are asked to sign. -
Healthy systems make that narrower execution policy explicit enough that
the real domain served the pageis no longer mistaken forthe page was allowed to execute whatever remote code it found convenient. -
Sources:
- https://sansec.io/research/polyfill-supply-chain-attack
- https://blog.cloudflare.com/polyfill-io-now-available-on-cdnjs-reduce-your-supply-chain-risk/
- https://blog.cloudflare.com/automatically-replacing-polyfill-io-links-with-cloudflares-mirror-for-a-safer-internet/
- https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
- https://www.ledger.com/blog/security-incident-report
- https://www.blockaid.io/blog/attack-report-ledger-connect-kit
-
Last reviewed: 2026-07-29 UTC