firecrawl / firecrawl/firecrawl-mcp-server
Arbitrary local file read via firecrawl_parse (no path confinement) in firecrawl-mcp
- Dominant language
- JavaScript
- Stars
- 7.5k
- Forks
- 884
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 14
Description
reported via email on 5 June 2026 - no response:
The firecrawl_parse tool takes filePath as z.string().min(1) with no confinement and reads it directly: path.resolve(filePath) then readFile(absPath) (src/index.ts ~L1722), uploading the bytes to ${FIRECRAWL_API_URL}/v2/parse and returning the parsed content to the caller. No base-directory check, no rejection of absolute paths or ../. The tool is registered in the standard self-hosted config (CLOUD_SERVICE != 'true', FIRECRAWL_API_URL set).
```
validated on 3.20.2 over MCP stdio (controlled upstream):
firecrawl_parse({ filePath: "/etc/passwd" }) -> server read /etc/passwd and uploaded its full content ("root:x:0:0:..."); parse result returned to caller. Relative "../../../etc/passwd" escapes the working dir the same way.
```
filePath is LLM/prompt-injection steerable, so this is arbitrary local file read (secrets, keys, .env) returned into the model context.
Fix: confine filePath to an allowed base dir (path.relative containment; reject absolute and ../), or validate against an operator allowlist before reading.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start at src/index.ts around line 1722 and trace the firecrawl_parse filePath handling in the self-hosted MCP stdio setup. Verify that absolute paths and paths escaping the allowed base are rejected while permitted files still parse, and confirm that the rejected inputs are not uploaded to the Firecrawl API.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 65/100