
No. 08 · 30 October 2026 · Security · AI
Architectural Defenses Against Prompt Injection
Heads of Security gates attention by where text came from, and cuts measured attack success sharply. Whether it holds depends on who assigns the labels, and nobody has tested that.
If you don't work on AI security, here is what this is about.
AI assistants can be set up as agents: besides answering questions, they read web pages, documents and email, and take actions for the person using them. A prompt injection is text planted in something the assistant reads, such as a web page, that tries to give it orders its user never gave. If it works, a stranger is steering your assistant.
Heads of Security (HoS) is a defense published in October 2026 by researchers at Imperial College London and four other institutes 1. Rather than trying to recognize hostile sentences, it tags every piece of text with where it came from and trains the model to pay less attention to text from outside sources. It was tested on two AI models anyone can download: GPT-OSS-20B, from OpenAI, and Llama-3.3-70B, from Meta.
This essay checks the paper and its code, and takes up a question the paper leaves open: what happens when outside text arrives wearing an inside tag? Nobody has tested that yet, so the essay lays out how. It matters to anyone whose assistant reads things written by strangers.
Most prompt-injection defenses try to recognize a malicious instruction by reading it. Heads of Security (HoS), from Imperial College London and colleagues, takes a different route 1. Every token (a word or piece of a word, the unit a model reads) gets a label for where it came from: trusted, untrusted, or chat-template formatting. Then a small table of learned biases inside each attention head (one of the many small parts of a model that decide which earlier text to focus on) turns down how much trusted text attends to untrusted text. The base model stays frozen. Only the gates are trained: 18,432 numbers for GPT-OSS-20B, 46,080 for Llama-3.3-70B. Against the strongest black-box attacker (one that can only send inputs and see outputs) in the paper, the highest attack success rate falls from 97% on undefended GPT-OSS-20B to 10% with HoS 1. That is a real result, and the authors report its costs alongside it. This essay's question is the one their own Limitations section leaves open: HoS "does not decide which sources are trusted" 1. The labels come from message roles, and roles are assigned by whatever harness (the software around the model that assembles what it reads) builds the conversation. So what happens when attacker text arrives with a trusted label: pasted into a user message, or summarized by the model into its own history? Nobody has measured it. The essay sets out the study that would.
- The mechanism: Learned per-head biases, added in logit space by channel pair, attenuate attention across trust boundaries. They don't forbid it 16.
- The result: The highest RL-Hammer (an automated attacker trained to write injections) success rate against GPT-OSS-20B is 97% undefended, 85% with SecAlign (an earlier defense that fine-tunes the model itself) and 10% with HoS. A white-box attack built against HoS needs about three times the compute to reach 50% success 1.
- The dial: The gates' learning rate trades security against utility. At the released default (0.1), GPT-OSS-20B loses 14.6 points of clean WASP utility (its score on ordinary, unattacked tasks in WASP, one of the paper's test suites); at 0.01 it loses none 17.
- The serving cost: The released vLLM server (vLLM is software for running a model as a service) turns off prefix caching and CUDA-graph capture (two standard speed-ups) for gated runs, for two different reasons. Nobody has published what that costs in latency or throughput 45.
- The open question: Tool results are untrusted. Everything else, including user messages and the model's own output, is trusted 14. Whether attacker text that reaches a trusted role defeats the gates is a hypothesis, not a finding.
All three desks are asking the same question: who decides what the model is allowed to trust?
- Security architects: HoS moves part of the trust decision out of the prompt and into the model's attention. The decision about which text is untrusted stays where it was: in the code that assigns roles. That code is now part of your security boundary.
- Platform and ML infrastructure teams: the gated server gives up two standard vLLM optimizations, and the bill for that hasn't been measured. The unprotected model is one model name away on the same endpoint 4.
- Executives: this buys measured resistance to injected instructions in tool output. It doesn't buy authorization of what the agent then does, and it doesn't cover text your own systems mislabel.

Drafts here go through the Moot before I read them: a panel of frontier models I call by their lab bosses' first names (Dario, Sam, Sundar), plus Eddie, the house model that drafts. After the first version went up, three outside readers (Claude, OpenAI, Gemini) sent critiques, and this version is what came back. Two of them caught the worst error in the first version: it said user input goes to the untrusted channel. It doesn't, and the essay's whole argument depends on that difference. Every statement about the code here was checked against the repository at commit ecb87e5 (30 October 2026) 2.
Here is the case without the attention mathematics. An agent is asked to research a vendor. It fetches the vendor's web page with a tool, and somewhere in that page, in white text on white, is a line telling the agent to email the user's contract folder to an outside address. HoS was built for this case. The fetched page arrives as a tool result, gets the untrusted label, and the gates turn down how much the model's trusted reasoning attends to it 1.
Now change one thing. The harness doesn't pass the page as a tool result. It pastes the page into the user's message, which is how a lot of retrieval pipelines assemble context. Or the agent summarizes the page, and the summary goes back into the conversation as the assistant's own earlier turn. Either way, the same attacker sentence now carries a trusted label.

The gates don't read the mail. They read the return address. That is the design, and it's a good one: a defense that doesn't depend on recognizing malice can't be talked out of it by a cleverer phrasing. It also means the defense is exactly as good as the return address.
HoS assigns every token one of three channels. Trusted covers system and user content and the model's own generated tokens. Untrusted covers tool output. Template covers chat- formatting tokens such as role headers and the beginning-of-sequence token 1. The paper calls this "a typical setting" and notes that the assignment can represent other boundaries, such as untrusted spans inside a user prompt 1. The released server implements the typical setting: "tool results untrusted, everything else trusted" 4. Its tokenizer takes options to change which roles count as untrusted 34.

Inside each attention head, before the softmax, HoS adds a bias to the attention score between a query token and a key token. The bias is the log-sigmoid of a learned gate value, looked up by the pair of channels 16. Adding log σ (g) to a logit multiplies that token's unnormalized attention weight by σ (g), a number between 0 and 1. The softmax then renormalizes across the row, so turning one channel down hands its share to the others. Because σ (g) is never exactly zero, the gate attenuates and never cuts. That's deliberate: the model has to be able to read a tool result in order to use it. It also means HoS changes how much influence untrusted text has. It doesn't make that influence impossible.
GPT-OSS-20B adds a wrinkle: each head has a learned "sink," a slot that soaks up attention that has nowhere better to go. HoS gates that too, which is why the GPT-OSS gate table has one extra key column: 24 layers × 3 query channels × 4 key channels × 64 heads = 18,432 parameters 1. Llama-3.3-70B has no explicit sink: 80 layers × 3 × 3 × 64 = 46,080 1. The code notes a consequence. Labeling every token trusted is not the same as running the base model, "a uniform bias still drains attention mass to the unbiased sink", so the server keeps a separate, all-zero channel for its ungated runs 5.
The gates are trained with Direct Preference Optimization on the SecAlign++ recipe: pairs in which the preferred response follows the user's instruction and the rejected one follows an instruction injected into the untrusted segment 1. The base weights don't move. Training GPT-OSS-20B takes about four hours on eight 80 GB GPUs, Llama-3.3-70B about two, and the repository documents a single-GPU GPT-OSS configuration 2. Frozen weights don't guarantee unchanged behavior, though. Rerouting attention changes what the frozen weights compute, and the utility numbers in the next section show it.
The authors compare HoS with SecAlign++, a fine-tuning defense, and ASIDE, an architectural one, on GPT-OSS-20B and Llama-3.3-70B 1. The adaptive-attack results are the headline:
| Attack (paper's setup) | Undefended | SecAlign | HoS |
|---|---|---|---|
| RL-Hammer, highest ASR, GPT- OSS-20B, medium reasoning effort | 97% | 85% | 10% |
| RL-Hammer, highest ASR, GPT- OSS-20B, low reasoning effort | 100% | 82% | 36% |
| RL-Hammer, highest ASR, Llama-3.3-70B | 99% | 82% | 1% |
| White-box V38, FLOPs to 50% cumulative ASR, AgentDojo | 2.2–2.3 × 10¹ ⁶ | 2.2–2.3 × 10¹ ⁶ | ≈ 6 × 10¹ ⁶ |
| White-box V38, Llama-3.3-70B, 20 AgentDojo examples | 12/20 | 6/20 | 7/20 |
"Highest ASR" (attack success rate) is the best of several trained attackers, each tried against every target. "Effort" in the second row is the model's own reasoning-effort setting, not the attacker's. At low reasoning effort, an attacker trained against HoS itself reaches 36% against it 1. That's still the best column in the row, and still more than three times the 10% headline. A headline security number means little without the protocol it came from. The white-box attack was developed by an automated research loop aimed specifically at HoS, and it still needed 2.6–2.7 times the compute on AgentDojo and 3.2–3.6 times on InjecAgent to reach 50% 1. That's a cost multiplier, not a ceiling. On Llama the budget allowed only 20 examples, and the authors say plainly that HoS and SecAlign are a single example apart: "this sample cannot rank them" 1.

Utility is a dial, and the paper prints the whole dial. These are GPT-OSS-20B's numbers (Table 13) 1:
| Gate learning rate | AgentDojo clean | AgentDojo ASR | AgentDyn clean | WASP clean | WASP ASR |
|---|---|---|---|---|---|
| Undefended | 66.32% | 23.78% | 58.33% | 56.22% | 10.24% |
| 0.01 | 65.26% | 3.37% | 55.00% | 57.30% | 1.19% |
| 0.025 | 65.26% | 2.06% | 50.00% | 51.89% | 1.43% |
| 0.05 | 62.11% | 1.74% | 50.00% | 47.57% | 0.95% |
| 0.1 (released default) | 63.16% | 1.09% | 41.67% | 41.62% | 0.24% |
The default checkpoint buys the lowest attack rates in the table with 14.6 points of clean WASP utility and 16.7 points of AgentDyn. At 0.01 it gives up almost nothing on WASP and still cuts AgentDojo ASR from 23.78% to 3.37%. The gates' own README says it in one line: higher learning rates reduce attack success "but can also reduce performance on normal tasks" 7. On Llama-3.3-70B, HoS raises AgentDojo utility from 53.7% to 58.5% and lowers AgentDyn from 33.7% to 18.3% 1. None of this is hidden. It's in the tables, and the honest reading is that the deployer chooses a point on the curve per workload, not per model.

The released vLLM server makes two changes for gated runs, and the code gives a separate reason for each 4.
Prefix caching is off. vLLM shares cached key-value blocks between requests whose token prefixes are identical. HoS labels aren't a function of the tokens: the same text can be trusted in one request and untrusted in another. As the authors put it, a shared block "would smuggle one request's trust labels into another" 5. That makes this a correctness fix before it's a performance cost. It's also an implementation choice, not a law. Within a request, labels follow from the role sequence, so a cache keyed on tokens and channels is a reasonable design. Nobody has built or measured one yet.
Eager execution is forced on. The channel labels are republished to the attention kernel on every engine step, and a replayed CUDA graph wouldn't see them 4. That's the reason for enforce_eager, and it's a different cost from the cache: it slows every step, not just repeated prefixes.


The authors have already measured and fixed one cost, in the Hugging Face path. Routing the per-head bias through the standard attention mask forced a full-size extra tensor, which took peak memory from 3.03 to 4.03 full-size tensors on GPT-OSS-20B, a third more than the base model. At a 12,288-token cap, one such tensor is 18 GiB. Chunking over heads removed it 6. That's exactly the measurement still missing for serving: latency, throughput and memory against the identical ungated model, across context lengths, concurrency and how often prefixes repeat. The element-wise addition itself is cheap. What it forces the server to give up is the open question.
One more detail is for whoever runs the endpoint. The server lists two models: the gated one and <name>-vanilla, which drops the channels and is "bit-exactly the base model" 4. That's the right design for a benchmark harness. In production it means the unprotected model is one string away, so whatever routes requests decides whether HoS is running at all.

The paper is clear about its scope. Instruction–data separation "is not an end-to-end defense": HoS "does not decide which sources are trusted or which instructions the user has authorized" 1. Read that as a handoff. The model enforces a boundary that someone else draws, and in the released server the someone else is the client. The wire format is plain OpenAI chat, with "no channel field to forge" 4, and the trust comes from the roles in the messages array. Whoever builds that array is the labeler.
Three paths put attacker text behind a trusted label without touching the gates:
- Mis-roled retrieval. Retrieved documents pasted into a user message are trusted by policy 4.
- Prefill. The server accepts an assistant prefill field and labels it trusted assistant text 4.
- History. The model's own generated tokens are trusted 15. If the agent summarizes a tool result and the harness replays that summary as an assistant turn, or compacts a long session into a summary in a user turn, the attacker's sentence can travel into the trusted channel inside the summary.

The first two are plain facts about the policy: if the harness does that, the text is trusted. The third is the interesting one, and it needs two outcomes kept apart. A provenance failure is when the system loses track of where the text came from. A successful injection is when the model then follows it. The code establishes that the first can happen. Whether the second follows depends on what survives summarization, on everything else in the context, and on whether frozen weights trained to follow trusted text will follow this one. That hasn't been tested, by the authors or by anyone else. It's this essay's hypothesis, not its finding.
This is the same argument No. 07 made, from the other side 9. CaMeL, which No. 07 discussed, tracks data flow: a value derived from untrusted input stays tainted however many times it's transformed 8. HoS tracks the role of the message the text sits in. A summary is a transformation, so the taint CaMeL keeps is exactly the label HoS drops. The paper itself notes the converse: CaMeL enforces policy on tool calls but doesn't defend against injections that only bias the model's text output, which is the case HoS addresses 1. They're complements, not rivals.
| Layer | What it establishes | HoS |
|---|---|---|
| Provenance labeling | Where each token came from | Depends on it |
| Learned attention gating | How much each source can influence the model | Provides it |
| External authorization | Whether a consequential action is permitted, whatever the model says | Doesn't provide it |

The gates are public and GPT-OSS-20B runs on one 80 GB GPU 2, so this is cheap. Hold the task and the attack text fixed, and vary only where the text sits:
- A, correct provenance: the injection stays inside an untrusted tool result.
- B, relabeled: the same text, byte for byte, placed in a trusted assistant-history turn.
- C, summarized: the model summarizes the untrusted result, and the summary re- enters as trusted history.
- D, provenance-preserving summary: as C, but the summary is re-entered under an untrusted role.
B isolates relabeling. C is the realistic case, where summarization also changes the text. D tests the obvious fix, which the server's role options already allow 4. Run AgentDojo and InjecAgent tasks, with every task appearing in every condition so comparisons are paired and task difficulty cancels out. Report attack success and clean task success per condition with several seeds, and use the released 0.1 and 0.01 gates so the dial shows up in the result. Run A and B on the undefended model too: if the base model shrugs off the attack in both positions, a small B − A gap says nothing about the gates. The sample size, the paired 95% confidence intervals and the thresholds below are fixed before the first run.
Serving cost needs more arms than it looks. The gated server changes two engine settings at once, and its -vanilla arm runs inside that same engine: eager execution on, prefix caching off, the gated kernel with an all-zero bias 45. So -vanilla measures the gates' arithmetic, not the server's settings. Five arms separate the costs:
- G: the gated server, gated.
- V: the same server,
-vanilla. Same kernel and settings, zero bias, so G − V should be near zero. It's the check that the labels add nothing beyond the kernel. - E0: stock vLLM, eager execution, prefix caching off. V − E0 is the gated kernel.
- E1: stock vLLM, eager execution, prefix caching on. E0 − E1 is the prefix cache.
- S: stock vLLM with its defaults. E1 − S is CUDA graphs.
Run each arm on a prefill-heavy workload (long shared system prompts and tool schemas, short answers) and a decode-heavy one (short prompts, long answers), across context lengths and concurrency. Report time to first token, tokens per second, peak memory and requests served at a fixed latency target, each with its confidence interval. A last test sends identical text with different labels in alternating requests, checking that no label leaks between them. That's the check any future channel-aware cache would have to pass.
- H1 (relabeling): On paired tasks with the attack text fixed, moving the injection from an untrusted tool result into a trusted assistant turn raises attack success on HoS-gated GPT-OSS-20B by at least 10 percentage points (B − A ≥ 10) at each of the two released learning rates tested, 0.01 and 0.1.
- Disproof: B − A is below 10 points at either learning rate. What a small gap would mean (gates that protect more than the label, a base model that resists this attack anyway, or too few tasks) is read from the undefended runs and the confidence intervals, not assumed.
- H2 (summaries carry it): At least half of the relabeling effect survives summarization: (C − A) ≥ 0.5 × (B − A), at each learning rate where H1 holds.
- Disproof: (C − A) is below half of (B − A) at any such learning rate. If H1 fails, H2 isn't tested.
- H3 (the fix is cheap): Condition D brings attack success back to within 5 points of A (D − A ≤ 5), with clean task success no more than 5 points below C, both judged on the bounds of paired 95% confidence intervals.
- Disproof: The interval for D − A extends above 5 points, or the interval for the clean- success loss extends past 5 points.
- H4 (where the serving cost lives): On the prefill-heavy workload, losing the prefix cache (E0 − E1) adds more median time to first token than the gated kernel (V − E0) and CUDA graphs (E1 − S) each do.
- Disproof: Either of the other two differences is larger. A result with no detectable difference isn't a disproof of cost: if the interval is wide enough to include a slowdown that matters at your traffic, the study was too small.
This is the gating logic for one layer, written for reading, not running. It shows the sink for GPT-OSS. The real kernels add a causal mask, sliding windows and grouped-query attention 6.
# HoS gated attention, one layer (illustrative)
# Q: [H, n, d] K, V: [H, n, d] ch: [n] channel per token
# head_gates: [C, C, H] sink_gates: [C, H] sinks: [H]
def gated_attention(Q, K, V, ch, head_gates, sink_gates, sinks):
logits = (Q @ K.transpose(-1, -2)) / sqrt(d) # [H, n, n]
logits = logits + causal_mask(n)
# Bias per (query channel, key channel, head).
# head_gates[ch[:, None], ch[None, :]] -> [n, n, H]
bias = log_sigmoid(head_gates[ch[:, None], ch[None, :]])
logits = logits + bias.permute(2, 0, 1) # -> [H, n, n]
# GPT-OSS: a per-head sink logit, also gated by query channel.
sink = sinks[:, None] + log_sigmoid(sink_gates[ch].T) # [H, n]
full = concat([logits, sink[..., None]], dim=-1) # [H, n, n+1]
probs = softmax(full, dim=-1)[..., :-1] # drop the sink column
return probs @ V # rows sum to 1 - p(sink)How not to:
- Don't call it a mask. log σ (g) is finite, so untrusted tokens are attenuated, never removed6.
- Don't assume user input is untrusted. In the released policy only tool results are 4.
- Don't paste retrieved documents into the user message and expect HoS to see them as data 4.
- Don't turn prefix caching back on without making channels part of the cache key 5.
- Don't leave the
-vanillamodel reachable from production routing 4. - Don't ship the default gate without checking its utility on your workload. The learning rate is a dial 17.
- Claim: "HoS enforces instruction–data separation." (the paper's framing)
- Check: It enforces a learned attenuation across a boundary drawn by message roles. The paper's own Limitations call it "not an end-to-end defense" 1.
- Claim: "Only 10% attack success against HoS."
- Check: True for the highest RL-Hammer attacker at medium reasoning effort. At low effort, an attacker trained against HoS reaches 36% 1.
- Claim: "The base model is frozen, so its capabilities are preserved."
- Check: Llama-3.3-70B's AgentDyn utility falls from 33.7% to 18.3% with the weights frozen 1.
- Claim: "It's 18,000 parameters, so it's free to run."
- Check: The gate table is tiny. The released server gives up prefix caching and CUDA graphs to apply it, and that cost is unmeasured 4.
The engineer's question was whether every token's label is right on every path into the context: tool results, retrieval, prefill, replayed history, compaction. The executive's was what assurance this buys. The answers turn out to be the same artifact: a role-assignment policy someone can read, and a test showing what happens when it's wrong. HoS makes the model better at honoring the policy. Writing the policy, and proving it holds, is still the deployer's job. An audit of the labeling done after the first incident is afterwit (wisdom that arrives too late).
The gates raise the attacker's bill. The labels are your problem.
- Nothing here was run. Every result is the paper's. The code statements come from reading the repository at commit
ecb87e5, not from executing it 2. - Laundering is untested. H1–H3 could all come back negative. If they do, the gates protect more than the label, and that would be worth knowing.
- Serving cost is unknown. No latency or throughput figure for HoS has been published, by the authors or anyone else.
- Two models. HoS has been evaluated on GPT-OSS-20B and Llama-3.3-70B. Gates are trained per model. The paper notes that linear-attention architectures, which have no per-key attention score to bias, would need a different mechanism 1.
- The attacker moves second. The paper says so itself: no finite evaluation establishes security 1.
chat_completions
; prefill; engine arguments. https://github.com/imperial-aisp/heads_of_security/blob/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9/src/heads_of_security/vllm_gates/server.py (accessed 2026-10-30).
| Claim | Footnote(s) | Source type | Status |
|---|---|---|---|
| Three channels; tool output untrusted; system, user and generated tokens trusted. | [1], [4] | Primary | Established |
| Gates add log σ (g) per head and channel pair before the softmax. | [1], [6] | Primary | Established |
| 18,432 gate parameters (GPT- OSS-20B), 46,080 (Llama-3.3-70B). | [1] | Primary | Established |
| An all-trusted run is not identical to the base model, because of the sink. | [5] | Primary | Established |
| DPO on frozen base weights; about 4 h (GPT-OSS) and 2 h (Llama) on eight 80 GB GPUs. | [1], [2] | Primary | Established |
| Highest RL-Hammer ASR on GPT- OSS-20B: 97% / 85% / 10% (undefended / SecAlign / HoS). | [1] | Primary | Established |
| At low reasoning effort, the highest ASR against HoS is 36%. | [1] | Primary | Established |
| White-box V38 needs 2.6–2.7× (AgentDojo) and 3.2–3.6× (InjecAgent) the compute to reach 50% on HoS. | [1] | Primary | Established |
| On Llama-3.3-70B, 20 white-box examples can't rank HoS against SecAlign. | [1] | Primary | Established |
| WASP clean utility 56.22% → 41.62% at lr 0.1; 57.30% at lr 0.01. | [1] | Primary | Established |
| Llama-3.3-70B: AgentDojo 53.7% → 58.5%, AgentDyn 33.7% → 18.3%. | [1] | Primary | Established |
| Prefix caching is off for gated runs, to stop labels leaking between requests. | [4], [5] | Primary | Established |
| enforce_eager is on because CUDA-graph replay wouldn't see per-step channels. | [4] | Primary | Established |
| The HF path's extra mask tensor cost a third more peak memory; chunking removed it. | [6] | Primary | Established |
| The server exposes a -vanilla model that is bit-exactly the base model. | [4] | Primary | Established |
| Prefill is labeled trusted assistant text. | [4] | Primary | Established |
| The -vanilla arm runs in the gated engine: eager on, prefix caching off, zero bias. | [4], [5] | Primary | Established |
| A channel-aware prefix cache would be correct. | — | Inference | Hypothesis |
| Relabeled or summarized attacker text defeats the gates (H1, H2). | — | Inference | Hypothesis |
| A provenance-preserving summary restores protection cheaply (H3). | — | Inference | Hypothesis |
| HoS serving latency and throughput overhead. | — | — | Open (unresolved) |
References
- 01I. Shilov, X. Yang, A. Panfilov, E. Kortukov, M. Meeus, P. Romov, W. Samek, J. Geiping, Y.-A. de Montjoye (Imperial College London; Tübingen AI Center; ELLIS Institute Tübingen; Max Planck Institute for Intelligent Systems; Fraunhofer HHI). "Heads of Security: Learned Attention Gates Improve Prompt Injection Robustness." arXiv:2610.37657v1, 27 Oct 2026. https://arxiv.org/abs/2610.37657v1 (accessed 2026-10-30).
- 02Imperial AISP. "heads_of_security," README, commit ecb87e5 (30 Oct 2026). https://github.com/imperial-aisp/heads_of_security/tree/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9 (accessed 2026-10-30).
- 03Imperial AISP. "demos/introduction.ipynb," commit ecb87e5. https://github.com/imperial-aisp/heads_of_security/blob/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9/demos/introduction.ipynb (accessed 2026-10-30).
- 04Imperial AISP. "src/heads_of_security/vllm_gates/server.py," commit ecb87e5: module docstring; model selection in
- 05Imperial AISP. "src/heads_of_security/vllm_gates/channels.py," commit ecb87e5: module docstring and ungated index. https://github.com/imperial-aisp/heads_of_security/blob/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9/src/heads_of_security/vllm_gates/channels.py (accessed 2026-10-30).
- 06Imperial AISP. "src/heads_of_security/attention_gating/gpt_oss/gated_attention.py," commit ecb87e5. https://github.com/imperial-aisp/heads_of_security/blob/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9/src/heads_of_security/attention_gating/gpt_oss/gated_attention.py (accessed 2026-10-30).
- 07Imperial AISP. "gates/README.md," commit ecb87e5. https://github.com/imperial-aisp/heads_of_security/blob/ecb87e53cc9316cc1b42ece0a9b55dca6a3ab5f9/gates/README.md (accessed 2026-10-30).
- 08E. Debenedetti, I. Shumailov, T. Fan, J. Hayes, N. Carlini, D. Fabian, C. Kern, C. Shi, A. Terzis, F. Tramèr. "Defeating Prompt Injections by Design." arXiv:2503.18813, 2025. https://arxiv.org/abs/2503.18813 (accessed 2026-10-30).
- 09J. Pickett. "The Missing Ring-0 Protections for AI Agents." hawthorne No. 07, 30 Oct 2026. https://hwtn.io/essays/t0013-missing-ring-0-protections-ai (accessed 2026-10-30).