GHSA-M5PH-MMG5-6W5H
Vulnerability from github – Published: 2026-11-05 18:07 – Updated: 2026-11-05 18:07Summary
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-342accepts the request, parsescidwithCID.parse, and callspinStore.pin(request.user, cidObject, parsed.options).src/filecoin-pin-store.ts:153-188stores the pin asqueuedand schedules_processPinInBackgroundwithsetTimeout. There is no queue, semaphore, or global cap around this scheduling.src/filecoin-pin-store.ts:211-217creates a per-pin Helia node and forwards caller-suppliedorigins.src/filecoin-pin-store.ts:260-274walks the full DAG withfor await (const pinnedCid of helia.pins.add(cid)).src/create-pinning-helia.ts:47-80creates a libp2p/Helia node with the Bitswap block broker and no application-level resource limits.src/core/car/car-blockstore-base.ts:65-107writes every fetched block and updatesstats.totalSizeonly after writing.src/core/car/car-file-backend.ts:84-93streams 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
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": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.1.0"
},
"package": {
"ecosystem": "npm",
"name": "filecoin-pin"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.1.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-62300"
],
"database_specific": {
"cwe_ids": [
"CWE-400"
],
"github_reviewed": true,
"github_reviewed_at": "2026-11-05T18:07:30Z",
"nvd_published_at": "2026-10-30T21:17:13Z",
"severity": "MODERATE"
},
"details": "## Summary\n\nThe 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.\n\nAn 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.\n\n## Details\n\n`POST /pins` validates only that the request body contains a syntactically valid CID string, then forwards it to the pin store:\n\n- `src/filecoin-pinning-server.ts:304-342` accepts the request, parses `cid` with `CID.parse`, and calls `pinStore.pin(request.user, cidObject, parsed.options)`.\n- `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.\n- `src/filecoin-pin-store.ts:211-217` creates a per-pin Helia node and forwards caller-supplied `origins`.\n- `src/filecoin-pin-store.ts:260-274` walks the full DAG with `for await (const pinnedCid of helia.pins.add(cid))`.\n- `src/create-pinning-helia.ts:47-80` creates a libp2p/Helia node with the Bitswap block broker and no application-level resource limits.\n- `src/core/car/car-blockstore-base.ts:65-107` writes every fetched block and updates `stats.totalSize` only after writing.\n- `src/core/car/car-file-backend.ts:84-93` streams blocks to the CAR writer on disk.\n\nThe 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.\n\n## Impact\n\nSuccessful exploitation affects availability:\n\n- Disk exhaustion from unbounded CAR files in `carStoragePath`.\n- Network exhaustion from recursive Bitswap retrieval.\n- CPU and memory pressure from concurrent libp2p/Helia pin operations.\n- Service degradation or process failure for other users of the daemon.\n- Operational cost and manual recovery burden from large partial CAR files.\n\nThe 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.\n\n## PoC\n\n```bash\ncurl -X POST \"https://target.example/pins\" \\\n -H \"Authorization: Bearer $ACCESS_TOKEN\" \\\n -H \"Content-Type: application/json\" \\\n -d \u0027{\n \"cid\": \"CID_OF_LARGE_DAG\",\n \"origins\": [\"/ip4/203.0.113.10/tcp/4001/p2p/ATTACKER_PEER_ID\"],\n \"meta\": { \"purpose\": \"resource-exhaustion-validation\" }\n }\u0027\n```\n\nSubmitting many such requests concurrently accelerates resource pressure because each request schedules independent background processing.",
"id": "GHSA-m5ph-mmg5-6w5h",
"modified": "2026-11-05T18:07:30Z",
"published": "2026-11-05T18:07:30Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/filecoin-project/filecoin-pin/security/advisories/GHSA-m5ph-mmg5-6w5h"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-62300"
},
{
"type": "WEB",
"url": "https://github.com/filecoin-project/filecoin-pin/commit/8db22b47899deb78dadf415fc477cae4bd6e82c2"
},
{
"type": "WEB",
"url": "https://github.com/filecoin-project/filecoin-pin/commit/afa019307db23a703737675e94316edcc6572050"
},
{
"type": "PACKAGE",
"url": "https://github.com/filecoin-project/filecoin-pin"
},
{
"type": "WEB",
"url": "https://github.com/filecoin-project/filecoin-pin/releases/tag/v1.1.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "filecoin-pin: Unbounded DAG pinning can exhaust server resources"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.