Repository navigation
feat(assistant): an optional local classifier for prompt injection - #347
Merged
Merged
Conversation
ai.injection_check "classifier" runs each tool result the free patterns let through past ProtectAI's deberta-v3-base-prompt-injection-v2 (Apache-2.0) on ONNX Runtime, on this machine: nothing leaves it and no tokens are paid for. The model (about 740 MB, pinned revision, checked against its SHA-256) and the `injection` extra are fetched when the setting asks for them (Settings > Components); until then the patterns carry on alone. Long text is read 512 tokens at a time, up to eight windows. Each check is an activity-ledger row (injection_check). Off by default; the default stays the free patterns. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVez82cREgCJtFk6yHReed
This was referenced Oct 11, 2026
adeelahmad
added a commit
that referenced
this pull request
Oct 11, 2026
…349) "Stay private and safe" now covers flagging instruction-like text (patterns or the optional local classifier, #329, #347), asking before the browser acts on what the assistant wrote (#333), breaking up links in chat-room answers (#338), the archive as data over MCP (#343) and the audit log of what was caught (#344). "See what it costs" adds the overall budget asked for in setup (#281). "In progress" drops what merged and adds #337, #341 and #346. Claude-Session: https://claude.ai/code/session_01HDx7PPUauyjMn1LZs8JAsS Co-authored-by: Adeel Ahmad <noreply@anthropic.com>
adeelahmad
pushed a commit
that referenced
this pull request
Oct 14, 2026
P-INJECTION-EGRESS: once an answer has read text from outside Lens, outbound tools and setup changes ask first, and chat-room answers keep only the links people, the archive, tools or Lens wrote. Correctness-only, a bypass is VALID-HARDENING (Q26). The Assistant x-prompt-injection row is now claimed; N-PROMPT says marking and flagging make injection less likely and are not claimed; MCP results and the optional classifier are described; Q26 lists #302, #309, #329, #338, #343, #344 and #347. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BVez82cREgCJtFk6yHReed
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.
Requested by Adeel · project thread
Description
Before: flagging text that reads like instructions to an AI (#329) had two choices: the free patterns, which are kept narrow and miss rephrased attacks, or asking the decision model about every tool result, which costs a call each and sends the text to that model.
After: Settings → AI assistant → Flag text that reads like instructions to an AI → classifier (
ai.injection_check: classifier) runs each tool result the patterns let through past ProtectAI'sdeberta-v3-base-prompt-injection-v2(Apache-2.0) on ONNX Runtime, on this machine. Nothing leaves it and no tokens are paid for. The model (about 740 MB, at a pinned revision, checked against its SHA-256) and the newinjectionextra are fetched when the setting asks for them (Settings → Components lists it); until then the patterns carry on alone. Long text is read 512 tokens at a time, up to eight windows, and the most suspicious window counts. Each check is a row in the activity ledger (injection_check), with the tokens read and the time taken.It's off by default: the default stays the free patterns.
Seventh of the prompt-injection series (#302 marking, #309 asks first, #329 flags, #338 room links, #343 MCP, #344 audit). Last: the threat-model update.
Motivation and Context
The coordinator's brief for "multi layered security" named a detection layer from the decision model or a proven open-source detector. This adds the detector, kept light by default (Raspberry Pi) and local when on (private, no per-call cost).
How:
injection_model.pyloads the ONNX model and tokenizer once, scores windows of[CLS] + ids + [SEP], feeds only the inputs the session asks for, and logsactivity.call("injection_check", ...).untrusted.flags(..., model=True)calls it when the setting isclassifier; it reads the strings a JSON result carries (untrusted._plain), because raw JSON looks like code to the model.components.InjectionModelfetches it on first use. Measured on the real model: it flags injections well but also some polite requests written for people ("please add the tracking number to the link"), so it only warns; docs say so.Types of changes
!in the title)Checklist:
make hookschecks it on commit).docs/accordingly.## UnreleasedinCHANGELOG.md. (n/a: the title and docs/assistant.md say it)Done questions (AGENTS.md)
classifierfetches everything itself; no.envedit.ai.injection_checkin Settings → AI assistant, defaultpatterns.injection_checkrow in the activity ledger.uv.lockregenerated withuv lock.🤖 Generated with Claude Code
https://claude.ai/code/session_01BVez82cREgCJtFk6yHReed
Generated by Claude Code