GHSA-m5ph-mmg5-6w5h

    Dashboard / Vulnerabilities / GHSA-m5ph-mmg5-6w5h

    GHSA-m5ph-mmg5-6w5h

    Published: 5 Nov 2026Last Modified: 5 Nov 2026

    Summary: filecoin-pin: Unbounded DAG pinning can exhaust server resources

    Details: ## Summary The IPFS Pinning Service API implementation accepts a caller-controlled CID through `POST /pins`, queues background processing, and then recursively fetches the full DAG with `helia.pins.add(cid)`. The route and background pinning path do not enforce a request rate limit, per-user quota, maximum DAG byte count, maximum block count, traversal timeout, or concurrent pinning limit. An authenticated caller, or an unauthenticated caller when the server is started with `ALLOW_NO_AUTH=true`, can submit one or more pins whose CIDs resolve to very large DAGs. The server writes fetched blocks to CAR files under `carStoragePath` and can consume disk, network, CPU, and libp2p resources until the process or host becomes unavailable. ## Details `POST /pins` validates only that the request body contains a syntactically valid CID string, then forwards it to the pin store: - `src/filecoin-pinning-server.ts:304-342` accepts the request, parses `cid` with `CID.parse`, and calls `pinStore.pin(request.user, cidObject, parsed.options)`. - `src/filecoin-pin-store.ts:153-188` stores the pin as `queued` and schedules `_processPinInBackground` with `setTimeout`. There is no queue, semaphore, or global cap around this scheduling. - `src/filecoin-pin-store.ts:211-217` creates a per-pin Helia node and forwards caller-supplied `origins`. - `src/filecoin-pin-store.ts:260-274` walks the full DAG with `for await (const pinnedCid of helia.pins.add(cid))`. - `src/create-pinning-helia.ts:47-80` creates a libp2p/Helia node with the Bitswap block broker and no application-level resource limits. - `src/core/car/car-blockstore-base.ts:65-107` writes every fetched block and updates `stats.totalSize` only after writing. - `src/core/car/car-file-backend.ts:84-93` streams blocks to the CAR writer on disk. The Helia node created for each pin has no bootstrap or mDNS configuration (`src/create-pinning-helia.ts:57`). A public CID alone may therefore not be fetchable unless the node can reach a content source. In practice, the API also accepts `origins`, so an attacker can supply a reachable attacker-controlled libp2p origin that serves a large DAG and cause the server to retrieve it. ## Impact Successful exploitation affects availability: - Disk exhaustion from unbounded CAR files in `carStoragePath`. - Network exhaustion from recursive Bitswap retrieval. - CPU and memory pressure from concurrent libp2p/Helia pin operations. - Service degradation or process failure for other users of the daemon. - Operational cost and manual recovery burden from large partial CAR files. The default daemon configuration reduces exposure because the server binds to `localhost` and refuses to start without an access token unless `ALLOW_NO_AUTH=true`. The finding is most significant when the daemon is exposed beyond localhost, when the token is shared across untrusted users, or when the no-auth mode is enabled. ## PoC ```bash curl -X POST "https://target.example/pins" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "cid": "CID_OF_LARGE_DAG", "origins": ["/ip4/203.0.113.10/tcp/4001/p2p/ATTACKER_PEER_ID"], "meta": { "purpose": "resource-exhaustion-validation" } }' ``` Submitting many such requests concurrently accelerates resource pressure because each request schedules independent background processing.

    Affected packages

    Package

    Name: filecoin-pin

    Purl: pkg:npm/filecoin-pin

    Affected ranges

    Type: SEMVER

    Events:

    Introduced- 0
    Fixed -1.1.1

    Affected versions

    Common Vulnerability Scoring System

    Attack Vector
    Network
    Adjacent
    Local
    Physical
    Privileges Required
    None
    Low
    High
    User Interaction
    None
    Required
    Scope
    Unchanged
    Changed
    Confidentiality
    None
    Low
    High
    Integrity
    None
    Low
    High
    Availability
    None
    Low
    High