Skip to content

fix: add CAMOFOX_MAX_BODY_SIZE env var to control body parser limit - #8398

Merged
skyfallsin merged 1 commit into
jo-inc:masterfrom
igitur:fix/evaluate-max-body-size-env
Aug 2, 2026
Merged

fix: add CAMOFOX_MAX_BODY_SIZE env var to control body parser limit#8398
skyfallsin merged 1 commit into
jo-inc:masterfrom
igitur:fix/evaluate-max-body-size-env

Conversation

@igitur

@igitur igitur commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Problem

The /tabs/:tabId/evaluate endpoint has a 1MB body limit override, but it's dead code — the global express.json({ limit: '100kb' }) middleware on line 120 runs first and rejects any body larger than 100KB before the evaluate-specific parser ever fires.

This makes it impossible to pass large expressions to evaluate, which is important for:

  • Injecting base64-encoded binary data (e.g., file uploads via FormData + fetch)
  • Passing large JSON payloads through evaluate

Fix

Add CAMOFOX_MAX_BODY_SIZE env var (default: '100kb') to lib/config.js — the centralized config module where all other env vars live. Then use CONFIG.maxBodySize in both places:

  • lib/config.js: maxBodySize: process.env.CAMOFOX_MAX_BODY_SIZE || '100kb'
  • Global parser: express.json({ limit: CONFIG.maxBodySize })
  • Evaluate parser: express.json({ limit: CONFIG.maxBodySize })

The cookies endpoint (512kb) and extract endpoint (256kb) are intentionally unchanged — they have their own specific limits.

Usage

# Default (100KB, backward compatible)
camofox-browser

# Increase to 10MB for large evaluate payloads
CAMOFOX_MAX_BODY_SIZE=10mb camofox-browser

Closes #8397

Both the global express.json() parser and the /evaluate endpoint now
read from CAMOFOX_MAX_BODY_SIZE (default: 100kb) via CONFIG.maxBodySize.
The setting is defined in lib/config.js alongside all other env vars.

Closes jo-inc#8397
@igitur
igitur force-pushed the fix/evaluate-max-body-size-env branch from 797f936 to bc7dbb3 Compare July 26, 2026 09:08
@skyfallsin
skyfallsin merged commit 6dccc63 into jo-inc:master Aug 2, 2026
@skyfallsin

Copy link
Copy Markdown
Contributor

Thanks @igitur — merged, with your original commit retained in the history.

The follow-up keeps the global JSON limit at 100kb and applies the configurable CAMOFOX_EVALUATE_MAX_BODY_SIZE limit only to POST /tabs/:tabId/evaluate, so the cookie and extract limits are not widened. It also forwards the setting to plugin-launched server subprocesses, documents it, and adds config and E2E coverage.

timothybrush pushed a commit to timothybrush/camofox-browser that referenced this pull request Aug 2, 2026
Fixes jo-inc#8397
Refs jo-inc#8398

Co-authored-by: Francois Botha <igitur@users.noreply.github.com>
jimconstable pushed a commit to jimconstable/camofox-browser that referenced this pull request Aug 2, 2026
* feat(mcp): add stdio MCP server exposing all 11 tools

- mcp/server.mjs mirrors the OpenClaw plugin.ts tools 1:1 (same names,
  schemas, REST routes) so any MCP host reaches camofox identically
- add @modelcontextprotocol/sdk dep, camofox-mcp bin, npm run mcp + test:mcp
- scripts/test-mcp.mjs: dependency-free smoke test (handshake, 11 tools,
  schemas, unknown-tool isError) — no REST server required

* test(mcp): add manual tool-call helpers for ad-hoc verification

- mcp-call.mjs: invoke one tool, print parsed result
- mcp-run.mjs: run a JSON sequence of calls in one MCP process
  (auto-substitutes ${tabId} from the prior create_tab result,
  simulating Claude Code's long-lived single-process usage)
- complements scripts/test-mcp.mjs (schema smoke test, no REST server)

* docs(mcp): convert helper comments to English

Match the repo's English-only comment convention (jo-inc/camofox-browser
is a global OSS project). No code change — comments only.

* docs(mcp): move MCP guide out of main README into mcp/README.md

The MCP integration is additive; the main README should keep jo-inc's
original Quick Start flow (OpenClaw -> Standalone -> Docker) untouched.
Restore README to upstream-identical and house the full MCP guide,
tool table, env vars, and troubleshooting in mcp/README.md instead.
The PR body links to it for discovery.

* docs(mcp): make registration path-independent

The previous quick start used 'node ./mcp/server.mjs', which only works
when cwd is the checkout — so the MCP server was effectively locked to
the camofox-browser repo. Rewrite around the 'camofox-mcp' bin, which
resolves from anywhere once installed via npm link / npm i -g / npx.
Verified the bin loads all 11 tools from /tmp.

* docs(mcp): add per-host registration for codex/agy/cursor/opencode

The MCP server is standard stdio, so all five hosts run the same
camofox-mcp bin — only the config file differs. Restructure the register
section into per-host snippets:
- Claude Code (claude mcp add / .claude.json / .mcp.json)
- Codex CLI (~/.codex/config.toml, [mcp_servers.*] TOML)
- Antigravity/agy (~/.gemini/config/mcp_config.json)
- Cursor (~/.cursor/mcp.json / .cursor/mcp.json)
- opencode (opencode.json, 'mcp' key, type: local)
Plus a per-host verify table and a clear install-vs-register split.

* feat: add /tabs/:tabId/upload endpoint for file attachment

Attach a file to an upload control without going through the native OS
file dialog. Two strategies are tried in order:

  1. If an <input type="file"> is already present, call Playwright
     setInputFiles on it directly (works for hidden inputs).
  2. Otherwise arm a filechooser listener, activate the trigger element
     (ref or selector) via keyboard (focus + Enter) with a forced click
     as fallback, and setFiles on the resulting chooser. Also polls for
     an in-app panel <input type=file> that mounts after activation.

The panel-input path is preferred over the native chooser so a control
that surfaces both (e.g. LinkedIn's media picker) attaches the file
exactly once rather than producing a duplicate.

Paths must be visible inside the container (e.g. a bind-mounted dir);
the route guards with fs.existsSync and returns 400 file_not_found
otherwise. Runs under the same per-user and per-tab locks as the other
interaction routes.

Includes OpenAPI documentation and unit tests (request validation +
source-contract assertions).

* refactor(upload): extract timeout magic numbers into constants + `timeout` arg

The upload route had inline millisecond literals (4000, 12000, 3000,
10000, 500, 1500) scattered through its two attach strategies. Replace
them with named UPLOAD_*_MS constants declared next to the route, and
expose the overall wait budget as an optional `timeout` request field.

- UPLOAD_UI_TIMEOUT_MS (default 12000) backs the request's `timeout`:
  the budget to wait for an upload UI (panel input or native chooser).
  Non-numeric / <= 0 values fall back to the default.
- The panel-poll window derives from that budget minus
  UPLOAD_PANEL_MARGIN_MS, preserving the original 10000/12000 split so a
  late native chooser is still caught after polling stops.
- UPLOAD_INPUT/FOCUS/CLICK/REFS/POLL/SETTLE_MS name the per-call bounds.

Defaults reproduce the previous behavior exactly. OpenAPI documents the
new `timeout` field; tests cover timeout resolution and assert the route
carries no bare millisecond literals.

* Update Docker build argument from ARCH to CAMOUFOX_ARCH

* fix(cookies): harden path traversal check in readCookieFile

Normalize cookiesDir with path.resolve() before the prefix comparison
and explicitly reject absolute cookiesPath values. Without this,
non-normalized cookiesDir (containing '..', trailing slashes, or
symlink-like segments) can make the startsWith() guard unreliable.

* refactor(mcp,openclaw): share tool contracts via lib/mcp-tool-contracts.mjs

* test(mcp): add mock-HTTP contract tests for all 11 tools

* build(mcp): make mcp/ an independently installable package

* docs(mcp): document CAMOFOX_ACCESS_KEY, contract tests, and standalone install

* fix: add CAMOFOX_MAX_BODY_SIZE env var to control body parser limit

Both the global express.json() parser and the /evaluate endpoint now
read from CAMOFOX_MAX_BODY_SIZE (default: 100kb) via CONFIG.maxBodySize.
The setting is defined in lib/config.js alongside all other env vars.

Closes jo-inc#8397

* fix: resolve npm audit vulnerabilities

* fix(evaluate): route errors through handleRouteError

* fix(cookies): contain resolved cookie paths

Co-authored-by: Sebastion <sebastion@sebastion.dev>

* fix(sessions): lease pages during creation

Refines the session-reaping approach from jo-inc#8319 without adding admission queues or HTTP 429 behavior.\n\nFixes jo-inc#8555\nRefs jo-inc#8319\n\nCo-authored-by: batumilove <batumilove@users.noreply.github.com>

* fix(evaluate): isolate large request bodies

Fixes jo-inc#8397
Refs jo-inc#8398

Co-authored-by: Francois Botha <igitur@users.noreply.github.com>

* fix(upload): contain file paths within upload directory

Resolve upload paths before attaching files. Reject paths outside CAMOFOX_UPLOADS_DIR, including symlink escapes, and require regular files.

Co-authored-by: Leone Parise <1442927+leoneparise@users.noreply.github.com>

* test(upload): cover HTTP file attachment

Exercise an in-root upload through a real browser file input and verify outside-root paths return 400.

* test(sessions): assert page lease return

* ci: mirror Camoufox releases daily

* fix(evaluate): forward body size configuration

* test(config): cover evaluate body size forwarding

* fix(mcp): package standalone adapter dependencies

* fix(mcp): use browser-mcp package name

* docs(mcp): credit initial implementation

* test(release): synchronize MCP package version

* fix(mcp): align adapter binary name

* fix(mcp): keep adapter binary name concise

* fix(mcp): use consistent package and binary name

* v1.13.1

---------

Co-authored-by: epicsagas <wowinno@gmail.com>
Co-authored-by: Leone Parise <1442927+leoneparise@users.noreply.github.com>
Co-authored-by: Xu Chen <79107215+xuc323@users.noreply.github.com>
Co-authored-by: Sebastion <sebastion@sebastion.dev>
Co-authored-by: Francois Botha <igitur@gmail.com>
Co-authored-by: Dividesbyzer0 <54127744+zoomdbz@users.noreply.github.com>
Co-authored-by: Mattia Trapani <mattia.trapani@gmail.com>
Co-authored-by: Pradeep Elankumaran <pradeepe@gmail.com>
Co-authored-by: Francois Botha <igitur@users.noreply.github.com>
Co-authored-by: jac-agent[bot] <4165859+jac-agent[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

evaluate endpoint 1MB limit is dead code — global 100KB parser runs first

2 participants