fix(devtools): read viewer database from server config only (VULN-11550) - #16055
Closed
gr2m wants to merge 1 commit into
Closed
fix(devtools): read viewer database from server config only (VULN-11550)#16055gr2m wants to merge 1 commit into
gr2m wants to merge 1 commit into
Conversation
The viewer stored a `dbPath` from the unauthenticated /api/notify POST body and fed it straight to fs.readFileSync on every API call, so any page a developer visited could point the viewer at an arbitrary file — arbitrary JSON read / existence oracle, plus a synchronous hang/OOM via /dev/zero or a huge file. reloadDb() no longer accepts a path; it reads only the server-configured location (default `<cwd>/.devtools/generations.json`, overridable via the new AI_SDK_DEVTOOLS_DB_PATH env var). /api/notify ignores any `dbPath` in the body. Reads are bounded to regular files under a 100 MB cap, closing the device-file / huge-file DoS vector. Follow-up to #16042 (which added the Host/Origin gating for VULN-11530). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collaborator
Author
|
Closing in favor of #16049 (same fix for VULN-11550, owned by the issue assignee). Per the comparison: #16049 validates + confines the notify This PR took the stricter "don't accept any network path" approach (matching the report's literal suggested fix) but at the cost of requiring |
Collaborator
Author
|
duplicate of #16049 |
gr2m
added a commit
that referenced
this pull request
Jun 12, 2026
Adds a 100 MB cap in validateRemoteDbPath so an attacker-influenced (but otherwise valid) .devtools/generations.json cannot hang/OOM the synchronous read. Complements the existing basename/dir, isFile, and symlink-escape checks. Closes the last gap noted when consolidating the duplicate VULN-11550 fixes (#16055). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Background
The DevTools viewer's
/api/notifyendpoint stored adbPathtaken from the (unauthenticated) POST body into a module-levelremoteDbPath, and every API read calledreloadDb(remoteDbPath), which passed it straight tofs.existsSync/fs.readFileSyncwith no validation. Any web page a developer visited while the viewer was running could therefore point the viewer at an arbitrary file:runsarray are returned verbatim via/api/runs(e.g. another project's.devtools/generations.json); other targets act as a JSON-validity / file-existence oracle.dbPathof/dev/zeroor a multi-GB file hangs / OOMs the synchronousreadFileSync.This is VULN-11550 (ANT-2026-R88SY5T6). It is distinct from VULN-11530 (fixed in #16042), which only addressed reachability (wildcard CORS,
0.0.0.0bind, Host/Origin allowlisting) and left this sink in place.Summary
Determine the viewer database location from server-side configuration only — never from a network request:
reloadDb()no longer accepts a path argument. It reads only the configured location: the default<cwd>/.devtools/generations.json, or the newAI_SDK_DEVTOOLS_DB_PATHenv var when the viewer runs in a different directory than the app./api/notifyignores anydbPathin the request body (it remains a pure "data changed → reload" signal); the module-levelremoteDbPathis removed.statSync) under a 100 MB cap, closing the/dev/zero/ huge-file DoS vector.Common usage (viewer launched from the project root) is unchanged —
<cwd>/.devtools/generations.jsonalready resolves to the file the SDK writes.Manual Verification
reloadDb(<network value>)and no remaining reference toremoteDbPath; the only inputs to the read areprocess.cwd()and theAI_SDK_DEVTOOLS_DB_PATHenv var.<cwd>/.devtools/generations.json) is byte-identical to theDB_PATHthe SDK writes to, so a viewer started in the project root behaves exactly as before.statSync+ size-cap helper rejects a non-regular path (directory/device) without throwing, so a hostile or missing path degrades to an empty DB rather than hanging.Checklist
pnpm changesetin the project root)Future Work
AI_SDK_DEVTOOLS_DB_PATHenv var alongsideAI_SDK_DEVTOOLS_PORTin the devtools docs.@ai-sdk/devtoolsexists on therelease-v6.0/release-v5.0branches and backport if applicable.Related Issues