Fix open issues: security, routing, and reliability (#17-#27)#28
Merged
Conversation
- #17: replace em-dash with ASCII in Start-UltraCode.ps1 (PS 5.1 CP1252 decode broke string parsing on BOM-less .ps1) - #21: pin CI actions to commit SHAs; add non-ASCII .ps1 CI guard - #20: stable SHA256 router cache key (builtin hash() is salted per process, so the cache silently missed every restart) - #19: loopback Host-header guard on all endpoints (anti DNS-rebinding) - #22: strip inbound Anthropic creds when forwarding to a custom upstream unless the route opts in with auth:passthrough; fix passthrough intent being dropped during slot construction so the opt-in actually forwards the credential - #23: defang injected <CLAUDE_TOOL_CALL> markers in untrusted transcript - #24: request body cap (413), bounded handler threads, per-socket timeout - #25: launcher state dir 0700 + atomic 0600 session-settings write - #27: shlex.split(REFRESH_CMD) for quoted paths; document JWT decode as best-effort/unverified - #18: persist orchestrator/worker selection across proxy restarts via UC_SELECTION_CACHE; surface lost-selection fallback - #26: add offline coverage for the above All offline checks pass: test_proxy.py, compileall, doctor --no-test --ci, auto_router_demo, check_ascii_ps1. Co-Authored-By: Rob <onerobby@gmail.com>
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
This was referenced Jun 18, 2026
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.
Summary
Resolves the open issues in the tracker. Each is a focused, stdlib-only fix; no new dependencies. The offline self-test,
compileall,doctor --no-test --ci,auto_router_demo, and the new ASCII guard all pass locally, andtest_proxy.pynow exercises every fix below.#14(long-context openai_compat hygiene: tool-onlycontent=null+ context-window hint) is already resolved inmainand is covered by the existingopenai_compat long-context hygienetest — no code change needed here.Security
#19config leak / unauthenticated routing mutation —/healthzexposed the full backend config and/uc/selectlet any local web page flip routing. When bound to loopback (the default), every endpoint now requires a loopbackHostheader (_guard_local()→ 403 otherwise). A browser can't forgeHost, so this blocks DNS-rebinding. Opt out by binding a non-loopbackUC_LISTEN_HOST.#22credential leak / SSRF to custom upstreams — Claude Code's own inbound Anthropic credential was forwarded to any routeupstream. Now inbound creds (authorization,x-api-key) are stripped before dispatch to a non-default upstream unless the route explicitly opts in withauth: "passthrough"._routes_to_slotsdropped the"passthrough"intent entirely (if auth and auth != "passthrough"), so the opt-in could never re-enable forwarding. The intent is now preserved asslot["auth_passthrough"]and honored at dispatch:#23prompt injection incursor_agent— the<CLAUDE_TOOL_CALL>{...}</CLAUDE_TOOL_CALL>bridge marker is our private control channel, but it was parsed out of cursor-agent output after untrusted transcript content (user text, tool results) could smuggle one in._flatten_messagesnow defangs the tag in all rendered transcript content, so only our own trailing instructions can emit a real call.#25settings TOCTOU / world-readableANTHROPIC_BASE_URL— launchers now create the state dir private (chmod 700/icaclslock to the current user) and write session settings via aumask 077temp file +chmod 600+ atomicmv, so another local account can't read or symlink-race theANTHROPIC_BASE_URL.#21supply-chain integrity — CI actions are pinned to commit SHAs (actions/checkoutv4.3.1,actions/setup-pythonv5.6.0) and a newscripts/check_ascii_ps1.pyCI step fails the build on non-ASCII bytes in any.ps1(regression guard for#17).#27unverified JWT — clarified that the Codex JWT decode is best-effort/unverified and used only for a cosmetic account-id/exp routing hint (never an auth decision; authority is enforced upstream). Also switchedREFRESH_CMD.split()→shlex.split(..., posix=os.name != "nt")so a refresh command with a quoted path isn't split on internal spaces.Reliability / correctness
#24resource exhaustion — added a request body cap (UC_MAX_BODY_BYTES, default 64 MiB) that returns413before allocating, aBoundedSemaphore(UC_MAX_CONNECTIONS)so a connection flood applies back-pressure instead of spawning unbounded threads, and a per-sockettimeout(UC_SOCKET_TIMEOUT) to bound idle/slowloris connections.#20non-deterministic router cache — the cache key used Python's builtinhash(), which is salted per process (PYTHONHASHSEED), so the same task minted a different key every restart and silently re-ran the classifier. Replaced with a stable, tier-scoped SHA256 digest:"%s|%s" % (tier, sha256(task)[:32]).#17PowerShell 5.1 parse failure —Start-UltraCode.ps1had an em-dash (U+2014) on line 233; PS 5.1 decodes a BOM-less.ps1as CP1252, where 0x94 is a closing quote and broke string parsing. Replaced with ASCII--.#18workflows fall back to stock Claude — the orchestrator/worker pick lived only in memory, so a proxy restart (or a workflow spawning a fresh proxy) forgot it and sub-agents reverted to stock Claude. The pick now persists toUC_SELECTION_CACHE(set by both launchers) and is restored on startup; a one-time diagnostic surfaces when selection is on but empty so a lost pick isn't mistaken for the workflow ignoring the model.Tests (
#26)test_proxy.pypreviously covered only the mock-based core. Added offline coverage for the loopback guard (403 on non-localHost), the oversize-body413, credential stripping vs.auth:passthroughopt-in, deterministic router cache keys, selection persist/restore across a simulated restart, thecursor_agentinjection defang, and best-effort JWT decoding. The provider modules' built-in self-tests gained an injection-guard assertion as well.Link to Devin session: https://app.devin.ai/sessions/b788d729b84747d094cdff871cb52d4b
Requested by: @OnlyTerp