Repository navigation
The transaction signing path loads its code from a third-party CDN at runtime, with no SRI and no CSP #211
Description
Problem
Every line of code that builds, signs, and submits a transaction is fetched from a third-party CDN
at page load, over a URL with no integrity check:
frontend/soroban.js:3--const SDK_URL = "https://esm.sh/@stellar/stellar-sdk@14.5.0?bundle",
loaded viaimport(SDK_URL)on line 9frontend/wallet.js:14--import("https://esm.sh/@stellar/freighter-api@5.0.0?bundle")
Neither is pinned by hash. A dynamic import() of a remote URL cannot carry a Subresource
Integrity attribute, so there is no mechanism verifying that the bytes esm.sh returns are the bytes
the package published.
And nothing constrains where scripts may be loaded from. netlify.toml sets
X-Content-Type-Options, Referrer-Policy, and Permissions-Policy, but no
Content-Security-Policy -- confirmed against the live response headers from
https://stellar-pulse.netlify.app/. There is no script-src, no connect-src, no
default-src.
Impact
stellar-sdk is the module that constructs the transaction, and freighter-api is the module that
hands it to the wallet for signature. If esm.sh is compromised, or its DNS or BGP is hijacked, or
its edge cache is poisoned for this origin, an attacker controls both. They can:
- rewrite the operation before it is built, so the XDR the user is asked to approve pays their
address instead of the market contract - swap the
place_betinvocation for atransferof the wallet's entire XLM balance - intercept the signed XDR and submit a different transaction
- exfiltrate every connected address
The user's protection at that point is reading raw XDR in the Freighter confirmation dialog, which
in practice nobody does. This drains any wallet that connects to the site, and it requires no
vulnerability in this repo's own code -- only in a dependency delivery path this repo has chosen not
to control.
The exposure is not theoretical for a CDN of this kind: unpinned, unverified runtime module loading
from a public transpiling CDN is the exact shape of the polyfill.io class of incident.
What to do
- Vendor
@stellar/stellar-sdkand the wallet library into the repo, or self-host them from the
same origin, so the signing path ships with the site and is reviewable in git - If a CDN is kept for any asset, load it with a static
<script>tag carrying a
Subresource Integrity hash andcrossorigin, never a bare dynamicimport()of a URL - Add a
Content-Security-Policyheader innetlify.tomlwith an explicitscript-src,
connect-srclimited to the Soroban RPC and Horizon endpoints infrontend/contracts.json,
object-src 'none', andbase-uri 'self' - Pin exact dependency versions and record their hashes, so an upgrade is a reviewed commit
rather than a silent CDN change - Add
frame-ancestors 'none'to stop the app being framed by a look-alike site
Why this is critical
This is the highest-severity issue in the repository. Every other bug here costs a user
correctness or convenience. This one can cost them their balance, silently, without any bug in
SPulse's own source, and there is currently no control anywhere in the stack that would stop it or
even detect it.
Activity
guptakumarranjeet150 commentedon Sep 8, 2026
Hello @SPulse-Org team,
I would love to take on this security issue regarding third-party CDN script loading without SRI and CSP pinning.
Proposed Solution:
Ready to submit a clean PR with passing tests within 12–24 hours. Please assign to me!
guptakumarranjeet150 commentedon Sep 8, 2026
Hi everyone,
I can tackle
The transaction signing path loads its code from a third-party CDN at runtime, with no SRI and no CSP. Proposed implementation roadmap:SPulse-Org/SPulseThe transaction signing path loads its code from a third-party CDN at runtime, with no SRI and no CSPstrictly followingSPulse-Org/SPulseconventions.Looking forward to contributing—please feel free to assign!
Iker2522 commentedon Sep 8, 2026
I'd like to take this issue on!
I can fix this critical security vulnerability by vendoring the transaction signing dependencies and configuring robust Security Headers for SPulse-Org / SPulse.
I will eliminate remote dynamic imports from esm.sh in frontend/soroban.js and frontend/wallet.js, replacing them with locally vendored, version-pinned modules for @stellar/stellar-sdk and @stellar/freighter-api. I will also update netlify.toml to enforce a strict Content-Security-Policy with explicit script-src, connect-src locked to approved RPC/Horizon endpoints from frontend/contracts.json, object-src 'none', base-uri 'self', and frame-ancestors 'none' to block framing attacks.
I will verify the entire transaction lifecycle locally and in preview deployments to ensure wallet connections, XDR building, and contract submissions function flawlessly without pulling any unverified remote scripts. PR ready in 1 day. Closes #211.
grantfox-oss commentedon Sep 12, 2026
🎉 This issue has been marked as completed on GrantFox!
@guptakumarranjeet150's PR #213 was approved and merged by @Muyideen-js.
🏆 @guptakumarranjeet150: You earned 35 FoxPoints for this contribution! Your current tier: Explorer (35 total points). Track your full progress on GrantFox.
👏 Great work, @guptakumarranjeet150! Keep contributing to SPulse-Org.