Nov 5, 2026·11 min read·3 visits
The filecoin-pin daemon (<= 1.1.0) lacks concurrency controls, rate limits, and DAG size restrictions on the POST /pins endpoint. Each request spawns an isolated Helia/libp2p node and executes an unbounded recursive DAG traversal, writing incoming blocks directly to disk as CAR files. Attackers can trigger denial of service by exhausting disk space, file descriptors, memory, and CPU.
CVE-2026-62300 is an uncontrolled resource consumption vulnerability (CWE-400) affecting the daemon mode of filecoin-pin in versions up to and including 1.1.0. The daemon implements the IPFS Pinning Service API to store content on Filecoin's Proof of Data Possession (PDP) service. Due to the absence of rate limits, concurrency caps, execution timeouts, and Directed Acyclic Graph (DAG) traversal limits, an authenticated user—or an unauthenticated user when authentication is disabled—can exhaust system resources via crafted POST /pins requests.
filecoin-pin is a TypeScript implementation of the IPFS Pinning Service API specification designed to bridge standard IPFS workflows with Filecoin's Proof of Data Possession (PDP) storage service. When operated in daemon mode (filecoin-pin server), the application exposes an HTTP interface that accepts pinning requests containing Content Identifiers (CIDs) and optional peer multiaddrs (origins). Upon receiving a request, the daemon retrieves the associated InterPlanetary Linked Data (IPLD) Directed Acyclic Graph (DAG) over the libp2p network using the Bitswap protocol, packages the retrieved blocks into Content Addressable aRchive (.car) files on the local filesystem, and coordinates storage onto the Filecoin network.
In versions up to and including 1.1.0, the daemon's HTTP ingestion layer, background job scheduler, P2P network stack, and disk storage backend lack resource boundaries. Classified under CWE-400 (Uncontrolled Resource Consumption), the application does not enforce request rate limits, per-user quotas, background worker concurrency limits, DAG depth or byte caps, or filesystem storage quotas.
By default, the HTTP server binds to localhost and requires a static bearer token via the Authorization header. However, the architecture uses a single shared ACCESS_TOKEN without tenant isolation, and operators can disable authentication entirely by setting the --allow-no-auth flag or the ALLOW_NO_AUTH=true environment variable. Consequently, any client capable of reaching the POST /pins endpoint can initiate resource-intensive operations without restriction.
When a caller submits either a single CID resolving to a multi-gigabyte DAG or multiple concurrent pin requests pointing to a reachable libp2p origin node, the daemon spawns independent libp2p/Helia instances for each request and streams blocks directly to disk. This behavior exhausts host disk capacity, OS file descriptors, ephemeral TCP ports, system memory, and CPU cycles, resulting in application crashes or host-wide denial of service.
The vulnerability stems from a combination of five architectural design flaws across the request lifecycle in filecoin-pin. The first flaw resides in the API routing layer (src/filecoin-pinning-server.ts), where the POST /pins handler validates the syntax of the incoming CID using CID.parse(cid) and extracts optional parameters (name, origins, meta), then immediately passes execution to pinStore.pin(). The server enforces neither global nor per-IP rate limiting, and it lacks quota tracking to restrict the number of active pins or cumulative bytes processed per user.
The second and third flaws occur within the job scheduling and P2P initialization logic in src/filecoin-pin-store.ts and src/create-pinning-helia.ts. Instead of placing incoming pin tasks into a bounded work queue or semaphore-controlled thread pool, FilecoinPinStore.prototype.pin schedules every job immediately onto the Node.js event loop using setTimeout(..., 100). Each scheduled job executes _processPinInBackground(), which invokes createPinningHeliaNode() to instantiate a dedicated Helia node backed by a new libp2p instance listening on a random TCP port (/ip4/0.0.0.0/tcp/0) with Noise encryption and Yamux stream multiplexing. Under concurrent request loads, spawning a complete P2P networking stack per request rapidly depletes operating system file descriptors (EMFILE) and ephemeral network sockets.
The fourth flaw lies in the DAG retrieval mechanism inside _processPinInBackground(). The daemon initiates content retrieval by iterating over helia.pins.add(cid). This call performs a recursive traversal of the entire IPLD DAG over Bitswap without an AbortSignal timeout, a maximum block count limit, a recursion depth boundary, or a cumulative byte cap. While the ephemeral Helia nodes do not configure default bootstrap peers or mDNS—meaning an arbitrary CID might not resolve on its own—callers can supply custom multiaddrs in the origins array of the POST /pins request body, forcing the daemon to dial directly into an attacker-controlled libp2p peer.
The fifth flaw involves the local storage pipeline implemented in src/core/car/car-blockstore-base.ts and src/core/car/car-file-backend.ts. As Bitswap retrieves blocks from the remote origin, CARWritingBlockstore streams them directly to a .car file under the configured carStoragePath. The blockstore updates this.stats.totalSize only after calling this.backend.writeBlock(), without verifying available disk space or enforcing a maximum file size limit. If a large traversal fills the underlying storage volume (ENOSPC) or causes the process to terminate abnormally, incomplete .car files remain orphaned on disk, permanently consuming storage until an administrator manually purges them.
Examining the vulnerable source code paths across filecoin-pin up to version 1.1.0 illustrates how requests bypass resource controls at each layer.
In src/filecoin-pinning-server.ts, the POST /pins endpoint processes user input and invokes the store directly without middleware rate limiters or concurrency checks:
// src/filecoin-pinning-server.ts
// Vulnerable: No rate limiting, per-user quota checks, or active job caps before scheduling
const result = await pinStore.pin(request.user, cidObject, parsed.options)In src/filecoin-pin-store.ts, the pin method registers the pin status in memory and uses setTimeout to trigger background processing asynchronously, allowing an unlimited number of jobs to run in parallel:
// src/filecoin-pin-store.ts
this.pins.set(pinId, pinStatus)
// Vulnerable: Unbounded concurrency; each request spawns an independent timer callback
setTimeout(() => {
this.logger.debug({ pinId }, 'setTimeout callback executing')
this._processPinInBackground(pinId, user, cid)
.then(...)
.catch(...)
}, 100)When _processPinInBackground executes, it calls createPinningHeliaNode in src/create-pinning-helia.ts, allocating a dedicated libp2p node bound to an ephemeral TCP port, and then iterates over helia.pins.add(cid) without an AbortController or size threshold:
// src/create-pinning-helia.ts
export async function createPinningHeliaNode(options: PinningHeliaOptions) {
// Vulnerable: Binds a new TCP socket and allocates Noise/Yamux contexts for every single pin
const libp2p = await createLibp2p({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0'],
},
transports: [tcp()],
connectionEncrypters: [noise()],
streamMuxers: [yamux()],
services: {
identify: identify({ maxMessageSize: IDENTIFY_MAX_MESSAGE_SIZE }),
},
})
// ...
const helia = new HeliaClass({
libp2p,
blockstore: carBlockstore,
datastore: new MemoryDatastore(),
blockBrokers: [bitswap()],
routers: [libp2pRouting(libp2p), httpGatewayRouting()],
})
}
// src/filecoin-pin-store.ts
// Vulnerable: No AbortSignal timeout, block count limit, or byte limit during traversal
for await (const pinnedCid of helia.pins.add(cid)) {
this.logger.debug(
{ pinId, cid: cid.toString(), pinnedCid: pinnedCid.toString() },
'Block pinned during DAG walk'
)
}During the DAG walk, retrieved blocks pass into src/core/car/car-blockstore-base.ts, where they are written to the filesystem prior to accounting, with no upper bound enforced on this.stats.totalSize:
// src/core/car/car-blockstore-base.ts
const blockStart = currentOffset + varintLength + cid.bytes.length
const offset: BlockOffset = { blockStart, blockLength: block.length }
this.blockOffsets.set(cidStr, offset)
this.currentOffset = blockStart + block.length
// Vulnerable: Writes directly to disk without checking quota or remaining disk space
await this.backend.writeBlock(cid, block, offset)
this.stats.blocksWritten++
this.stats.totalSize += block.length> [!NOTE]
> Fix Completeness Assessment: In version 1.1.1 (commit 8db22b47899deb78dadf415fc477cae4bd6e82c2), the maintainers did not modify the TypeScript source code to introduce queues, timeouts, or byte limits. Instead, the patch updated README.md to classify the daemon as non-production beta software and documented operational mitigations while deferring architectural fixes to GitHub issue #46. Consequently, the underlying code paths in 1.1.1 remain identical to 1.1.0, and security relies entirely on operator deployment controls.
Exploiting CVE-2026-62300 requires network access to the filecoin-pin HTTP daemon (default port 3000) and either a valid bearer token (ACCESS_TOKEN) or a target deployment configured with ALLOW_NO_AUTH=true. Because ephemeral Helia nodes spawned by filecoin-pin do not connect to public IPFS bootstrap nodes by default, submitting a random CID without routing hints may simply stall during content routing. However, the IPFS Pinning Service API specification supports an origins array in the POST /pins payload, which instructs the pinning service to dial specific multiaddrs directly.
To maximize resource exhaustion, an attacker first provisions a reachable libp2p/IPFS node on an external host (/ip4/<attacker-ip>/tcp/4001/p2p/<PeerID>). On this node, the attacker generates either a single massive IPLD DAG composed of millions of linked blocks or a series of distinct root CIDs referencing large block trees.
Next, the attacker sends an HTTP POST /pins request to the target daemon specifying the generated root CID and the attacker's multiaddr in the origins field:
POST /pins HTTP/1.1
Host: filecoin-pin.target.local:3000
Authorization: Bearer <ACCESS_TOKEN>
Content-Type: application/json
{
"cid": "bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
"name": "large-dag-payload",
"origins": [
"/ip4/198.51.100.42/tcp/4001/p2p/12D3KooWAttackerPeerIdentifierExample"
]
}To accelerate exhaustion of file descriptors, memory, and CPU alongside disk storage, the attacker can issue multiple concurrent requests in a loop:
for i in {1..200}; do
curl -s -X POST "http://filecoin-pin.target.local:3000/pins" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cid":"bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi","origins":["/ip4/198.51.100.42/tcp/4001/p2p/12D3KooWAttackerPeerIdentifierExample"]}' &
doneUpon receiving these 200 requests, the daemon schedules 200 concurrent _processPinInBackground routines after a 100ms delay. Each routine binds a new TCP port, initializes a libp2p instance, performs a Noise cryptographic handshake with the attacker's origin node, and streams blocks concurrently to disk under carStoragePath. Within seconds, the host experiences socket/file descriptor exhaustion (EMFILE), high memory allocation from 200 in-memory datastores and block offset maps (this.blockOffsets), and rapid disk saturation (ENOSPC).
The primary security impact of CVE-2026-62300 is a high-severity denial of service affecting both the filecoin-pin daemon process and the underlying host operating system. The vulnerability is scored at CVSS v3.1 6.5 (Medium) with the vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H.
The Attack Vector is Network (AV:N) and Attack Complexity is Low (AC:L), as exploitation requires only standard HTTP requests containing valid JSON and multiaddr strings. Privileges Required is rated Low (PR:L) because the server requires a bearer token by default; however, in environments where operators share a single token across multiple semi-trusted users or enable ALLOW_NO_AUTH=true, the effective privilege requirement drops to None. Confidentiality (C:N) and Integrity (I:N) are unaffected, while Availability Impact is High (A:H).
At the process level, concurrent instantiation of Helia and libp2p nodes saturates the Node.js event loop with cryptographic handshakes and stream multiplexing overhead, rendering the HTTP server unresponsive to legitimate API calls. Furthermore, because CARWritingBlockstore maintains an in-memory Map (this.blockOffsets) indexing every written block's CID string to its byte offset, traversing DAGs with millions of blocks can trigger an out-of-memory (OOM) crash in the V8 JavaScript engine.
At the host level, unbounded writes to carStoragePath can consume 100% of the available disk partition. If carStoragePath resides on the root filesystem, disk exhaustion prevents the operating system and co-located services from writing logs, temporary files, or database transactions. Even if the filecoin-pin service is restarted after a crash, partial .car files generated prior to termination are not automatically garbage-collected, leaving the disk in a persistently degraded state. Currently, the EPSS score for CVE-2026-62300 is 0.00249 (16.29th percentile), and there are no reports of active exploitation in the wild.
In version 1.1.1, the filecoin-project/filecoin-pin maintainers updated the documentation via commit 8db22b47899deb78dadf415fc477cae4bd6e82c2 to clarify that the daemon mode is beta software unsuitable for multi-tenant or untrusted production environments. Because code-level resource controls (tracked under GitHub issue #46) are not implemented in 1.1.1, upgrading the package alone does not mitigate the underlying resource exhaustion vectors.
Operators who must run the filecoin-pin server daemon must implement infrastructure-level and operational controls to restrict exposure and bound resource consumption:
127.0.0.1 (the default) and never expose it directly to untrusted networks. Never configure --allow-no-auth or ALLOW_NO_AUTH=true outside isolated, disposable development environments. Treat ACCESS_TOKEN as a privileged, single-tenant credential./pins:limit_req_zone $binary_remote_addr zone=pin_req_limit:10m rate=1r/s;
limit_conn_zone $binary_remote_addr zone=pin_conn_limit:10m;
server {
listen 443 ssl;
server_name pin.example.com;
location = /pins {
limit_req zone=pin_req_limit burst=2 nodelay;
limit_conn pin_conn_limit 1;
client_max_body_size 64k;
proxy_pass http://127.0.0.1:3000;
}
}CAR_STORAGE_PATH to point to a dedicated filesystem volume or mount point with strict storage quotas (such as Linux xfs_quota or LVM volume limits) so that runaway .car file writes cannot exhaust the host OS root partition. Additionally, run the daemon inside a container or systemd unit with explicit MemoryMax, CPUQuota, and LimitNOFILE boundaries.systemd timer or cron job) to monitor CAR_STORAGE_PATH and purge incomplete or stale .car artifacts left behind by failed or aborted pinning operations.CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
filecoin-pin filecoin-project | <= 1.1.0 | 1.1.1 |
| Attribute | Detail |
|---|---|
| CVE ID | CVE-2026-62300 (GHSA-m5ph-mmg5-6w5h) |
| Weakness Class | CWE-400: Uncontrolled Resource Consumption |
| CVSS v3.1 Score | 6.5 Medium (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H) |
| EPSS Score | 0.25% (16.29th percentile) |
| Affected Component | filecoin-pin daemon (<= 1.1.0) |
| Attack Vector | Network via HTTP POST /pins with large DAG CIDs and custom libp2p origins |
| Primary Impact | Host and process Denial of Service via disk, socket, memory, and CPU exhaustion |
| CISA KEV Status | Not Listed |
The product does not properly control the allocation and maintenance of a limited resource, thereby enabling an actor to influence the amount of resources consumed, eventually leading to the exhaustion of available resources.
CVE-2026-105769 (GHSA-5q7h-w9jf-cx97, GO-2026-6225) is an origin validation error and credential exfiltration vulnerability affecting Kaniko prior to version 1.25.20. The flaw stems from an unanchored regular expression in the integrated Azure Container Registry (ACR) credential helper (github.com/chrismellard/docker-credential-acr-env). When Kaniko processes a Dockerfile containing an image reference hosted on a lookalike domain containing an ACR suffix as a substring (e.g., x.azurecr.io.attacker.com), the credential helper acquires a Microsoft Entra ID access token for Azure Resource Manager and transmits it via HTTP POST to the attacker-controlled host.
CVE-2026-61536 is a high-severity Remote Code Execution (RCE) vulnerability in the masci/banks Python library prior to version 2.4.3. The flaw exists within the CompletionExtension component, which parses JSON-serialized Tool definitions directly from rendered Jinja template bodies inside {% completion %} blocks. When handling tool calls returned by an LLM, the library dynamically resolves the target callable using importlib.import_module() and getattr() based on an unvalidated import_path string. An attacker who can supply or modify prompt templates can inject a malicious Tool JSON object pointing to arbitrary Python functions (such as os.system), bypassing the Jinja SandboxedEnvironment introduced in version 2.4.2 and achieving arbitrary code execution when the LLM invokes the tool.
Payload CMS contains a missing authorization vulnerability (CWE-862) in its client-side upload instructions endpoint and the `@payloadcms/storage-vercel-blob` storage adapter. Two distinct logic defects allow authenticated users lacking collection-level `create` or `update` permissions to generate signed upload tokens and upload arbitrary files directly to external cloud storage.
CVE-2026-55098 (GHSA-93cm-2v4m-c56c) is an authorization bypass and sensitive information disclosure vulnerability in Basekick-Labs Arc prior to version 26.06.2. The flaw stems from an incomplete remediation of CVE-2026-47735, which failed to restrict the full suite of DuckDB table-valued filesystem I/O functions and quoted-identifier invocations. Because Arc's query parser ignores function calls during table reference extraction, authenticated users with minimal or empty permissions can invoke functions like parquet_scan(), glob(), and read_blob() to read, enumerate, and extract telemetry data across all tenant databases residing within the shared local storage root.
CVE-2026-113787 is a stored Cross-Site Scripting (XSS) and HTML injection vulnerability affecting the odf-kit npm package from version 0.6.0 prior to 0.14.2. The HTML conversion engines (odtToHtml and odsToHtml) interpolate document-controlled styling and image attributes directly into inline style and src attributes without escaping double-quote characters. A remote attacker can supply a crafted .odt or .ods document to break out of HTML attribute boundaries and execute arbitrary JavaScript in the context of any web application rendering the converted HTML.
GHSA-m3qr-fvp4-78xj is an authentication bypass and information disclosure vulnerability in Arc, an open-source, SQL-native time-series database developed by Basekick Labs and written in Go. Due to an improper route registration sequence within the Go Fiber HTTP server initialization pipeline, the application registered the /api/v1/logs endpoint prior to mounting the global authentication middleware. Because Fiber evaluates route handlers in strict declaration order and terminates request traversal when a handler returns without invoking c.Next(), unauthenticated remote callers can query the logs endpoint and retrieve up to 10,000 buffered operational log entries even when authentication is enabled.