Repository navigation
[PR] fix: refuse origin-form non-model paths locally instead of splicing them onto the upstream (#5211) - #5258
Open
ranxianglei wants to merge 10 commits into
Open
ranxianglei wants to merge 10 commits into
ranxianglei wants to merge 10 commits into
Conversation
…hem onto the upstream (#5211) An origin-form request (client base URL = the proxy port itself) whose path is neither a model API shape nor a declared destination used to be spliced onto opts.upstream by forwardUpstreamUrl and forwarded verbatim — shipping a mistargeted caller's private payload (e.g. dsh-im's local /api/dsh-im/delivery/messages body) to the configured upstream (default api.anthropic.com), out of the machine (#5211). handle() now refuses such requests locally with a 404 (unknown_upstream_path) before any forward. Model-shaped paths (protocol-table shapes root-anchored, Google/Vertex model-in-path shapes, /models discovery) keep forwarding byte-identically; escape hatches unchanged: /bili/<full-url> tunnels, providers.* declarations for the destination, x-bili-passthrough marks, x-bili-hop chains, global passthrough mode. Refusals are rate-limited logged per path (warn x3 + info) and surfaced at /__bili/stats (refusedForeignPaths) and the /acp status report, mirroring the #1290 unrecognizedPaths surface. Regression suite: tests/issue5211-foreign-path-refusal.test.ts (shape-predicate unit table + e2e repro and controls); the #393 unknown-path control now asserts the new refusal.
Contributor
📦 Built Package ArtifactBranch: Latest build — install this exact versionnpm install -g billion-context@0.0.7431-pr.5258.e3680abThis exact version is immutable and reproducible. The rolling Recent builds (commit → version)
Download artifact
tar xzf billion-context-pr5258.tgz
npm install -g packageInstall instructions are refreshed on each push. |
added 2 commits
October 31, 2026 05:11
…rm gate The origin-form model-path gate (isModelTrafficOriginFormPath) admits the protocol table's root-anchored shapes but missed Anthropic's counting endpoint /v1/messages/count_tokens — which the pipeline itself treats as first-class model traffic via isCountTokensRequest. An origin-form request to that path was therefore refused locally with 404 while its sibling /v1/messages still forwarded, silently breaking token-counting for clients whose base URL points at the proxy port. Google's :countTokens arm was already covered via googlePathKind; this adds the Anthropic snake_case arm. Pinned with two positive rows in the shape table. Verified the rest of the allow/refuse classification is byte-stable (no other shape changes).
added 7 commits
October 31, 2026 08:08
This was referenced Oct 31, 2026
This branch has not been deployed
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.
(ai: vllm-qwen/qwen3.8-27b)
Closes #5211
What this fixes
Field report (#5211, bili 0.1.208 / DSH desktop): the host's LOCAL private request
POST http://127.0.0.1:<port>/api/dsh-im/delivery/messagesappeared in bili.log forwarded tohttps://api.anthropic.com/api/dsh-im/delivery/messages— the caller's private payload left the machine to a third-party API.Root cause (server-side). When a client's base URL points at the proxy port itself (origin-form request),
resolveUpstreamreturns undefined andforwardUpstreamUrlsplices the bare path ontoopts.upstream— the configured upstream, defaultapi.anthropic.com. That splice had NO shape check: any path (model endpoints, discovery, or an unrelated local/private API) was relayed verbatim to it (the #1284 verbatim-relay branch makes the non-conversation forwarding explicit). The in-process client over-claim (isModelApiUrlmatches any trailing/messages) is a real but separate defect class — on the dsh lane the attribution gate keeps such calls direct-sent or loopback-bound, so it did not produce the reported egress. The egress producer is the server-side catch-all splice: any process pointed at the proxy port could ship its payload to the default upstream.Fix
handle()now refuses origin-form requests whose path is neither model traffic nor a declared destination locally with 404 (error.type = unknown_upstream_path; the message tells the caller how to reach model traffic) before anything is forwarded:isModelTrafficOriginFormPath, root-anchored):/v1/messages/messages/chat/completions/llm_raw_chat/responses/responses/compact(version segment optional),/models/v1/modelsdiscovery, Google:generateContent/:streamGenerateContent/:countTokensmodel-in-path shapes, Vertex anthropicpublishers/anthropic/models/<id>:rawPredict|streamRawPredict./bili/<full-url>zero-config tunnels, absolute-form forward-proxy requests, MITM sockets,providers.*declarations for the destination (incl. per-destinationpassthrough),x-bili-passthroughmarks (「BUG」native-intercept 进程级 globalThis.fetch 补丁按 URL 形状接管所有模型流量,无关调用者(如 MemOS)被卷入宿主压缩流程 #1117),x-bili-hopchain skips (fix: stitched-stream usage double-count after compress re-request (adapter-anthropic >0 guard) #300), global passthrough mode.refusedForeignPathsfield onGET /__bili/stats, and a REFUSED FOREIGN PATHS section in the/acpstatus report.No new config keys (the issue's suggested
relayUnknownUpstreamtoggle is not implemented — the refusal is safe-default boundary behavior, not a preference knob; anyone who genuinely needs the old behavior for one endpoint declares it underproviders.*). No client-side blanket loopback passthrough either — that would break compression for local model servers (Ollama/vLLM/LM Studio on loopback/LAN are supported destinations).Behavior changes (old → new)
/api/dsh-im/delivery/messages,/v1/files,/v1/embeddings, prefixed bases like/x/v1/messages)unknown_upstream_path; payload never forwarded/modelsdiscovery, all/bili/· absolute-form · MITM forms, passthrough marks/hops/modetests/issue-393-registry-window.test.tsunknown-path controlVerification
tests/issue5211-foreign-path-refusal.test.ts(42 tests): the exact issue repro (delivery body never reaches the mock upstream), foreign GETs, stats/admin surface, model-traffic controls with hop markers (anthropic / openai / discovery / vertex), and every escape hatch.npm run typecheckclean. Full-suite verdict: remote CI on this head.