Repository navigation
fix(#2766): durable classifiers refuse assistant-role messages — model echo cannot take over a durable identity - #2774
Merged
Conversation
…l echo cannot take over a durable identity The four dsh carriers are host INJECTIONS into the user channel, but the classifiers matched on contentType+text alone: an assistant message echoing a carrier marker (<available_skills>, Instructions from:, <mcp_catalog>, Current runtime context) projected to durable/<name> too. Under the default latest-per-identity policy (#2736) the LAST match wins, so a later model echo took the identity over from the real carrier: the echo got pinned, the real carrier demoted to foldable, and one compression later the forged/partial copy was the only survivor — including the adversarial variant where an injected instruction makes the model emit a fake <mcp_catalog> with attacker-chosen server names (the #2446 failure mode, attacker-authored). Anything visible to the model eventually shows up in its output (bili-chain tags, #2483 render tags, #933/#1039 echo noise), so the gate cannot be the marker text. Every classifier now refuses assistant-role messages first (system/user injections stay covered); zero legitimate protection loss — no carrier is ever emitted as assistant output. Kernel unchanged: virtualToolPathOf stays role-agnostic by design; the boundary belongs to the classifiers that own the evidence (KDD #9). tests/issue2766-durable-role-gate.test.ts: 11 cases — per-carrier echo never projects (individual + lane-composed), user-role still projects, system-role still projects, collectLatestProtected keeps the real carrier as the latest instance across a later echo, echo between two real snapshots does not break succession.
Contributor
📦 Built Package ArtifactBranch: Option A — Install this exact build (recommended)npm install -g billion-context@0.0.3051-pr.2774.62054edThis exact version is immutable and reproducible. The rolling Option B — Download artifact
tar xzf billion-context-pr2774.tgz
npm install -g packageInstall instructions are refreshed on each push. |
Contributor
📦 Merged Build PublishedThis merge to master was published as npm install -g billion-context@0.0.281-master.70d651c # this exact build
npm install -g billion-context@master # always the newest merged build
|
ranxianglei
added a commit
that referenced
this pull request
Oct 11, 2026
…EBUSY/EPERM teardown) Every SessionStore created under BILI_STORAGE_UNIFIED holds the index.db SQLite handle until GC; cancelAll() never closes the shadow, and Windows cannot unlink an open file — the engproof teardown then pins the temp dir in EBUSY (index.db) / EPERM (dir) on every run of the new fcac9e3 suite (#1915 rmrf family; POSIX unlinks open files, hence linux-green). Switch the last lifecycle call of each store to closeQuietly(); the corrupt-index test closes only after its final writeNow (write-after-close would test a different thing). Unblocks #2764 / #2774 windows legs.
This was referenced Oct 11, 2026
Merged
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.
What
#2766: the four dsh durable classifiers matched on
contentType === "text"+ marker text with no role boundary. An assistant message echoing a carrier marker (<available_skills>,Instructions from:,<mcp_catalog>,Current runtime context) projected to the samedurable/<name>virtual path as the real carrier. Under the default latest-per-identity policy (protectedLatestTools: ["durable/*"], #2736)collectLatestProtected'slastByPathtakes the last match — so a later model echo took the identity over from the real host injection: the echo got pinned, the real carrier demoted to foldable, one compression later the forged/partial copy was the only survivor.Adversarial variant: an injected "list the catalog" instruction makes the model emit a fake
<mcp_catalog>with attacker-chosen server names → the forgery survives, the real inventory folds — #2446's failure mode (model hunting servers by wrong names), attacker-authored.Fix
Every classifier now refuses assistant-role messages first:
createUserMessage). system/user-role injections stay covered — the gate targets model output only.virtualToolPathOfstays role-agnostic by design); the role boundary belongs to the classifiers that own the traffic evidence (KDD release v0.1.2 #9 discipline). No kernel bump.Tests
tests/issue2766-durable-role-gate.test.ts— 11 cases, all green:durableMessageToolPaths.dsh); same content user-role still projects;collectLatestProtectedover[real carrier, filler, assistant echo]keeps the real carrier as the latest instance, echo not inmsgIds,isMessageLatestProtectedtrue for the carrier / false for the echo;Adjacent green (post-rebase on master
da6315ec): durable-tool-identity (8), issue2446/2447/2481 suites (13 — their e2e sections unaffected), typecheck clean.Closes #2766