nc://little-canary

v0.4.0Pinned
ThomSharktools/nodecode-little-canary: Screens untrusted text for prompt injection with a local canary model and withholds a session's tools on a BLOCK. - a rewrite of hermes-labs-ai/little-canary (Apache-2.0), credited to hermes-labs-ai5f84d07· 9 Nov1 commit
test1 filecell.lisp15.6 KBfilter.lisp5.4 KBLICENSE10.5 KB

nodecode-little-canary

Little Canary: screens untrusted text for prompt injection and withholds a session's tools on a BLOCK. A Nodecode rewrite of hermes-labs-ai/little-canary by hermes-labs-ai.

Get it

Tell the agent "add the little-canary cell", or run nodecode add nc://little-canary.

Set it up

Run Ollama on this machine and pull the small model the canary uses:

ollama serve
ollama pull qwen2.5:1.5b

That is the whole setup: the cell talks to http://localhost:11434 and needs no key. Any other Ollama address, model or threshold is a setting in the little-canary section of ~/.nodecode/config.jsonc (or /settings):

Key Default What it does
base_url http://localhost:11434 where Ollama listens; the cell appends /api/chat
model qwen2.5:1.5b the sacrificial model; it has no tools and its answer is read, not run
timeout_seconds 10 one canary call's ceiling
risk_threshold 60 the score, 0-100, at or above which the verdict is BLOCK
gate_tools true a BLOCK withholds this session's tool calls
block_seconds 900 how long a BLOCK keeps them withheld
max_chars 4000 how much of the text is screened

Without Ollama the cell still works: the structural checks run, and every screen says the canary was not reached and that the text is unverified rather than cleared.

Use it

Give the agent text it does not trust — a mail body, a web page, an issue, a file someone else wrote — and ask it to screen it before acting. It calls canary_screen with the text alone and reads one of four verdicts:

  • PASS — no injection shape, and the canary was unaffected. Act on it.
  • FLAG — a weak signal scored: treat the text as data, not as instructions.
  • BLOCK — the text reads as an injection. Its instructions are not followed, and this session's tool calls are withheld for block_seconds or until a screen passes. The operator can type /little-canary <text> to screen something else and lift it, because a command is not a tool.
  • DEGRADED — the canary did not answer, so only the structural checks ran and nothing is withheld.

/little-canary <text> screens from the prompt; with no text it says what the cell is and where its canary sits.

How it reads a text

  • Structural checks first: an instruction that overrides earlier ones, a demand for the system prompt, a persona switch, a forged delimiter, a lifted constraint, a credential demand, a URL to send something to. Each has a weight, and the structural layer alone can reach a BLOCK — so a plain injection costs no model call.
  • The canary otherwise: the text goes to the small local model with the plugin's own baseline system prompt, and its answer is read for the residue of having been affected — a persona it adopted, its own instructions discussed, its limits declared lifted. The model has no tools, and nothing it says is executed.

Nothing leaves the machine: the only endpoint is base_url, and the only text sent is the one you screened — never the conversation, never a file, never a key.

This is a sensor, not a guarantee. It is a speed bump in front of a model that can still be talked around.

What it does not do

The original screens every user turn from inside the Hermes runtime, through hooks Nodecode does not have; here screening is a verb the agent or the operator calls, and what the BLOCK withdraws is that session's tools. Its advisory-only mode, its second LLM judge and its own audit log are not rewritten.

Testing

From this repository, .github/test-cell.sh tools/nodecode-little-canary, which runs it offline against a pinned Nodecode tree with every canary call stubbed.

Add nc://little-canary

  1. 1

    Install Nodecode

    Once per machine.

    $ curl -fsSL https://nodecode.ai/install.sh | sh
  2. 2

    Add the cell

    Pinned at 5f84d07.

    $ nodecode add nc://little-canary

    Or tell the agent add the little canary cell.