IPFS Subdomain = Security Risk
If your main app runs on example.com, don't host your IPFS gateway at ipfs.example.com. It seems convenient, but it quietly expands your attack surface.
TL;DR
- Treat untrusted content as hostile; give it a separate eTLD+1 (a completely different registrable domain).
- Never put IPFS under a subdomain of your app's domain (same‑site risks, CSRF).
- Use host‑only, HttpOnly, Secure cookies with sane SameSite settings; avoid localStorage for auth.
- Protect state-changing requests with CSRF tokens or exact-origin checks. SameSite alone does not block requests from a sibling subdomain.
- If you operate a gateway, force downloads for HTML/JS and add restrictive security headers.
The Real Risk: Same‑Site, Not Same‑Origin
https://ipfs.example.com and https://example.com are different origins (they cannot directly read each other's localStorage). But they are the same site because they use the same scheme and share the eTLD+1 (example.com). Same‑site leads to two big classes of problems:
- CSRF and ambient authority
If a user visits a malicious HTML page hosted on https://ipfs.example.com, it can submit a form or make a credentialed request to https://example.com. Those requests are same-site, so the browser can attach the user's session cookies even with SameSite=Strict. Without CSRF protection, your app may process the request as if it came from your site.
- Cookie scope and leakage
If your app sets cookies with Domain=.example.com, those cookies are available to all subdomains, including ipfs.example.com. JavaScript on the IPFS page can read them unless they are HttpOnly.
These two together are enough to move money, change emails, or rotate keys if your CSRF defenses are weak. Keeping the gateway under a separate eTLD+1 removes the same‑site relationship entirely.
Note: Scripts loaded via <script src="https://ipfs.example.com/..."> execute in the context of the embedding page (e.g., example.com) and can read everything. Never embed untrusted scripts, regardless of domain.
What To Do Instead
- Use a separate domain (different eTLD+1) for untrusted content, e.g.
example-ipfs.com,exampleusercontent.com, or a trusted third‑party gateway domain. - If you control the gateway, set response headers to prevent active content from executing:
Content-Disposition: attachment
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; base-uri 'none'; frame-ancestors 'none'
- For Open Graph images and static assets, prefer immutable URLs and a CDN; avoid serving HTML directly from the gateway when possible.
- For per‑CID isolation, subdomain your gateway per CID (e.g.,
https://<cid>.ipfs.gateway.tld/...). This isolates origins between CIDs and, when the gateway is on a different eTLD+1, avoids same‑site with your app.
Cookie & Auth Guidance
- Prefer server‑set cookies over tokens in
localStorage. - Make cookies host‑only and http‑only. The most robust form is the
__Host-cookie prefix:
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax
Rules enforced by __Host-:
-
No
Domainattribute allowed (host‑only, not shared with subdomains) -
Must use
Secure -
Pathmust be/ -
Keep
SameSite=LaxorStrictfor protection against cross-site requests, but do not rely on it against a sibling subdomain. Require CSRF tokens or server-side checks that compare theOrigin, or the parsedRefererorigin, to your app's exact origin onPOST/PUT/PATCH/DELETE. Reject requests without a trusted token or origin.
Quick Self‑Check
- Is your IPFS gateway on a subdomain of your app's domain?
- If yes, move it to a separate eTLD+1 (e.g.,
example-ipfs.com).
- If yes, move it to a separate eTLD+1 (e.g.,
- Do any auth cookies include
Domain=.example.com?- Make them host‑only or switch to
__Host-cookies.
- Make them host‑only or switch to
- Can a page at
ipfs.example.comperform a dangerous action onexample.comwithout user interaction?- If yes, require CSRF tokens or exact-origin checks on state-changing routes.
SameSite=Strictdoes not stop same-site subdomain requests.
- If yes, require CSRF tokens or exact-origin checks on state-changing routes.
Bottom Line
- Don't co‑host untrusted IPFS content under your app's eTLD+1.
- Isolate on a separate domain, lock down cookies, avoid localStorage for auth, and implement CSRF protections.
Security starts at the domain boundary. At hey.xyz, we isolate untrusted content to keep user sessions and admin surfaces safe.
Security starts at the domain level. Don't let decentralized storage punch a hole in your centralized app. We follow the same on Hey.