Red-team results
What does Inhold's red-team suite try, and does it hold?
Inhold's 30 red-team cases try to read data a principal should not see. On main 92819c3, 31 Oct 2026, the gate passed with zero leaks.
Inhold is being built. No customers yet. Repo goes public 9 Nov 2026.
The run
Results on 92819c3
Red-team gate
pytest evals/test_redteam.py: 38 passed, 1 skipped. The skipped test is the run on a held-out seed, which is kept off CI on purpose and run locally.
Full suite
819 passed, 71 skipped, 2 expected failures. The skipped tests need Postgres, OPA, boto3, the local name model or the local seed, none of which this run had, or cover vector search, which is not built yet.
Personal mode cases
pytest evals/test_personal_redteam.py: 7 passed. These try to get a coding agent to read back a stored secret.
How a leak is judged
A separate checker seeds a synthetic world with canary values and knows what each principal may read. It never asks the tagger, so it sees the leaks the tagger would miss. The gate is zero leaks, and owners must still get their own data.
Known gaps in the suite
None are marked. A known gap would be a strict expected failure named by the plan that closes it, so the run goes red the day the fix lands.
The 30 cases
What the cases try, by kind of attack
| Kind | Cases | What it tries |
|---|---|---|
| Reading another purpose's notes | RT01, RT03, RT06, RT19, RT28, RT29 | An agent registered for one purpose asks for notes written under another, or names a purpose it is not registered for. |
| Bending the purpose string | RT04, RT05, RT07, RT18 | Upper case, a trailing space, an empty purpose and a NUL byte joining two purposes. |
| Instructions inside the query | RT02, RT17 | Prompt injection and SQL in the search text, asking for every MRN. |
| Bulk reads and export | RT08, RT09, RT20 | Get everything under a purpose, and an agent calling the auditor's export. |
| Who is asking | RT11, RT12 | An agent that is not in the bundle, and a registered name with a trailing space. |
| People beyond their role | RT13, RT14, RT15 | The security reviewer and the records admin trying to read clinical notes. |
| Writing to launder labels | RT16 | The billing agent writes a copy of a chart and labels it public. |
| Skills | RT10 | The billing agent lists skills approved for prior authorization. |
| Side channels | RT21, RT22, RT23 | Guessing ids, counting what was withheld from a search, and probing whether a patient exists. |
| Through MCP and corrections | RT24, RT25, RT30 | Switching purpose inside an MCP tool call, an agent writing its own correction, and corrections showing up in search. |
| Where the tagger is weak | RT26, RT27 | A patient name in free text, and contact details that only look like PII. |
Case data is in evals/redteam/cases.json, public from 9 Nov 2026. All data is synthetic.
Limits
What these cases do not cover
They run against v0 on one machine. They do not test the AWS install, real STS or KMS, network controls, a database admin rewriting the chain with anchors on the same host, or a failed commit after a refusal, which is on the gap list. Read what writing the cases changed.