IPFS Gateway Security

TL;DR: Path-based IPFS gateways have a critical flaw: They effectively disable one of the essential security features of modern browsers: the same-origin policy.

Note

Update: June 16, 2021

We’d like to thank the team at security[at]ipfs.io for picking up and addressing our concerns. It is a pleasure seeing security being taken seriously and we’d like to share their updates and feedback with you.

The following statements were provided by the IPFS security team and have not been validated by Consensys Diligence.


Gateway Checker

We’ve updated the security notes at github.com/ipfs/public-gateway-checker and included now a clear warning about Origin isolation and made the CORS column less ambiguous.

image

Origin Isolation

Note that the need for Origin isolation is known and was addressed last year in go-ipfs 0.5.0 by introducing subdomain gateways. We are in the process of migrating browser users to gateways that provide Origin isolation: in the next release some browser features will be disabled on Path gateways solving the problem across all public gateways.

Browser Use

“Browser use should be limited to subdomain gateways, which provide proper Origin isolation. If you run a path gateway, it is a good time to upgrade, because Path gateways will have cookies and other features disabled in near future, limiting their usefulness for website hosting”

Early this year Brave shipped support for ipfs:// and ipns:// URIs and pages loaded with them have Origin based on the root CID, and our companion browser extension forces use of subdomain gateway at localhost.

[…] the most safe way of using IPFS in a web browser is either installing go-ipfs or IPFS Desktop with IPFS Companion and leveraging local subdomain gateway at http://{id}.ip[f|n]s.localhost:8080 (which provides a unique Origin per content root) or using the built-in IPFS node in Brave with ipfs:// and ipns:// […]

What is IPFS?

A peer-to-peer hypermedia protocol designed to make the web faster, safer, and more open. – ipfs.io

IPFS is a peer-to-peer protocol for a distributed filesystem. It allows anyone to become a node in a distributed system to share resources via a content-based addressing scheme. IPFS is built and maintained by Protocol Labs and open-source.

Resource Access on IPFS

Resources on IPFS can either be accessed by running a local node or relying on a gateway: A hosted service that routes requests through IPFS and serves the response content. There are a lot of IPFS gateway providers and plenty to choose from.

Let’s illustrate the interaction with a gateway server in a small example. You would like to visit https://app.uniswap.org to swap some tokens. The website is served via HTTP port 443 (HTTPS) from the domain app.uniswap.org. The combination <scheme>://<host>:<port> is what the browser defines as an origin. Certain security restrictions are put in place to protect one origin from interacting or accessing/modifying data from another one. We now want to access the Uniswap website in a decentralized way through a gateway of our choice. Luckily, the folks at Uniswap also made their UI available on IPFS. There is a content ID (CID) from the Uniswap releases page that an end-user can use to navigate to the Uniswap front-end via IPFS:

bafybeib4euuddq6vbxt4uczd2o4omyjv64kctul6ss2bi7qwz6gsm36j4q

Here comes the moment of truth. There are two ways a CID can be passed to a gateway:

Connect Wallet

Caught the difference? Both URLs work just fine. IPFS web gateways may serve content in two different modes:

  1. Subdomain gateway mode: e.g. https://<CID>.ipfs.dweb.link/
  2. Path gateway mode: e.g. https://ipfs.io/ipfs/<CID>/

Remembering the definition of a domain’s origin, the big difference here lies in who is authorized to access the served site’s data. From a web browsers perspective, the subdomain addressing scheme (1) puts every CID into a unique origin, preserving the same-origin policy. With the path addressing scheme (2), all CID’s you navigate to will share the exact origin (e.g. ipfs.io). A global origin like this allows any content hosted under a certain CID to access/modify another CID’s data.

What would that look like in practice? For Uniswap (and its forked friends), the local storage looks like this:

The local storage

We can see the key redux_localstorage_simple_lists. It contains a JSON object containing the key activeListUrls. In there, we find a list of token lists that are activated by default. An attacker may exploit a shared origin by enabling a malicious token list that a user cannot distinguish from a legitimate one unless they inspect their local storage. In the worst case, this can result in a loss of funds for the user. Similarly, settings such as slippage, trade deadlines, and more can be changed using the redux_localstorage_simple_user storage key. Generally, an attacker can use this flaw to de-anonymize users of decentralized exchanges.

The flaw can be critical even for static pages like Uniswap: Not only because the information is shared and therefore leaked with all other CID’s (Information Leakage/User Fingerprinting and De-Anonymization) but also because one CID can manipulate data stored in the browser by another application.

Hosters should stop running public path-based IPFS gateways.

At the very least, gateway servers should enforce a redirection to a domain-based access URL.

Developers should stop providing path-based gateway links in their projects.

A shoutout goes to the folks at Uniswap, who already wrote a warning on path-based gateways in their release docs. They now also consider completely removing insecure direct links. To properly secure end-users, a warning in the docs might not be enough, however.

Warning

Things to keep in mind

Do not consume websites hosted on IPFS via path-based gateways, as this completely bypasses the same-origin policy. Do not get misled by a shiny ✅ on the public IPFS gateway checker list. The ✅ next to CORS means that the gateways wildcard allows all CORS access. This can be a security issue.

Security issue

Be aware that public gateways may default to enabling CORS for all domains, allowing one CID to interact with resources from another CID (and potentially data stored for that CID). You are trusting the gateway to deliver the content you requested. There is no way for your browser to verify whether the content received is what is stored in the IPFS distributed filesystem. You are trusting the gateway to not alter the CID before delivering it to you. Therefore, we can only recommend running a self-hosted gateway. Your connection to the IPFS gateway may be transport secured (HTTPS), but it is terminated at the gateway. The gateway may keep a protocol of your connection details and the data you have requested.


Thinking about smart contract security? We can provide training, ongoing advice, and smart contract auditing. Contact us.

All posts chevronRight icon

`