Repository navigation
fix: harden the plugin probe, bundle lookup, explorer and trigger regexes against hostile input - #605
Merged
Conversation
…their path plugin add and remove read the environment with python -c and preview and install with python -m pip, which put the current folder first on the import path, so a module there named like one they import ran before any prompt, --dry-run included. They now start the interpreter with -P, as plugin show and the config probe already did; the working directory is unchanged, so relative specs still resolve. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e is refused agent-env run NAME ran a folder called NAME in the current directory ahead of the installed bundle of that name, so an untrusted checkout could stand in for it. Such a name, bare or as DIST/NAME, is now refused with the two spellings to use, ./NAME and DIST/NAME. A folder with no installed namesake still runs by its bare name. bundle init prints its run command as a path, and the CLI's note for a folder that wasn't a bundle, which could no longer be reached, is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… object type but the passive ones The CSRF guard refused only Sec-Fetch-Site: cross-site, but every loopback port is one site and the local providers publish env sites, pgweb and agent pages there, and a browser sending no Fetch Metadata was trusted. /api now admits a browser request only from the same origin, a typed URL, or, with no Fetch Metadata, the explorer's own Origin; a configured cors_origin is still admitted, and curl and the CLI are unaffected. The default CORS policy no longer lets another origin read a response. The object proxy sandboxed six types, while an agent chooses an object's type and name and Atom, RSS, XSL and multipart documents run script. Only images (not SVG or +xml), audio, video, PDF, plain text, CSV and JSON are served unsandboxed, under script-src 'none'; frame-ancestors 'self'; every other type gets sandbox. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The gateway matched a trigger's regex with the standard library, unbounded, on the event loop every caller shares, against text the agent or an env server chose. It now uses the regex package with a 0.1 s timeout over at most the first million characters; a match that runs out matches nothing and is logged, so a where doesn't fire, an unless doesn't cancel and a check fails. Registration refuses a non-string regex or one over 4096 characters. regex joins the gateway image's requirements and the dev extra. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…ut, not just to fail fast The test let any quick non-match pass. It now stands in for regex.search, checks the budget it was given, raises TimeoutError, and asserts the trigger stays armed and the timeout is logged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Why
Five small paths by which content the operator doesn't control reaches the operator's machine or the gateway:
plugin addandplugin removeread the environment with a fresh interpreter started aspython -c, and preview withpython -m pip. Both put the current folder first on the import path, so apackaging.pyorpip/in an untrusted checkout ran before any prompt, even with--dry-run.agent-env run NAMEran a folder calledNAMEin the current directory ahead of the installed bundle of that name.Sec-Fetch-Site: cross-site, but a page on another port of127.0.0.1issame-site, and a browser that sends no Fetch Metadata was trusted. The default CORS rule also let any loopback port read responses. The local providers publish env sites, pgweb and agent pages on loopback ports, so any of them could start or cancel runs and read the API.What changes
python -m pipthe plugin commands run now start the interpreter with-P, asplugin showand the config probe already did. Relative specs such as./pluginstill resolve, since the working directory is unchanged.DIST/NAME, is refused, naming./NAMEfor the folder andDIST/NAMEfor the bundle. A folder with no installed namesake still runs by its bare name.bundle initnow prints its run command as a path (./triage). The CLI's note for a folder that wasn't a bundle could no longer be reached, so it's removed./apiadmits a browser request only withSec-Fetch-Site: same-originornone, or, from a browser that sends no Fetch Metadata, an Origin equal to the explorer's own. A configuredcors_originsentry is still admitted. The default CORS policy no longer lets another origin read responses. curl and the CLI send neither header and are unaffected, and the UI's dev server proxies/apithrough its own origin.+xmltype), audio, video, PDF, plain text, CSV and JSON are served unsandboxed, underscript-src 'none'; frame-ancestors 'self'. Every other type getssandbox; frame-ancestors 'self'.regexpackage under a 0.1 s timeout, against at most the first million characters. A match that runs out matches nothing, and is logged. Awherethen doesn't fire, anunlessdoesn't cancel and a check step fails. Registration refuses a non-string regex or one longer than 4,096 characters.regexjoins the gateway image's requirements and the framework'sdevextra; outside the container only the tests import the engine.Compatibility
agent-env run NAMEwhereNAMEis also an installed bundle now fails with the two spellings to use. The integration fixture that avoided the namehellofor that reason keeps working.:8234from another origin has to list that origin in[explorer] cors_origins.regex.regexkeeps the standard library's syntax, so existing trigger patterns match as before.Tests
-P;DIST/NAME, and runs spelled out;bundle initprints a relative folder as./NAME;cross-site,same-siteand a foreign Origin, and admitssame-origin,none, its own Origin and no headers;Not covered here
script-src 'none'.🤖 Generated with Claude Code


Confidence Score: 5/5
The PR appears safe to merge; the previous test issue is fixed.Summary
The PR hardens plugin commands, bundle lookup, explorer requests and object previews, and trigger regex matching.
Reviews (2) · Last reviewed commit: "test(gateway): a regex that runs out of ..." · Reviewed by Greptile