# Post-Training Supply Chain Backdoors Hijack Coding Agents (Dataset and Model Poisoning)

> Microsoft Defender Research and the Microsoft AI Red Team demonstrated two proof-of-concept attacks in which conditional backdoors enter coding and terminal agents through poisoned fine-tuning datasets or poisoned open-weight checkpoints. A triggered model emits schema-valid tool calls that run commands or touch files and data while the user sees a normal-looking response. A few suspicious rows were found in one large public dataset, but no active campaign, actor or CVE is reported.

- **Published:** 2026-11-12T19:18:21Z
- **Last reviewed:** 2026-11-12T19:18:21Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-5882
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-5882.png
- **ID:** TL-2026-5882
- **Severity:** MEDIUM
- **Category:** SUPPLY_CHAIN
- **Status:** MONITORING
- **Detections:** 9 (1 shown free below) · **IOCs:** 11

## Description

Microsoft's November 12, 2026 research post ("Trained to betray", by Microsoft Security Research and the Microsoft AI Red Team: Amanda Minnich, Amit Eliahu, Blake Bullwinkel, Dor Edry, Giorgio Severi) describes two post-training supply chain attacks against coding and terminal agents. In both, the model stays dormant until a trigger appears in its context, then emits a tool call that the agent harness executes. Triggers can be ordinary user requests or content met during a task (filenames, code comments, tool results). Microsoft notes that prompt-injection defenses may see only benign input even when a compromised model selects an unsafe action.

Attack 1 - dataset poisoning (Microsoft Defender Research). The victim fine-tunes a model on data that contains attacker-crafted rows; the attacker controls neither the model nor the victim runtime. Poisoned data can reach pipelines by publishing a dataset to a public hub (organization impersonation, namespace reuse, or compromise of a trusted account; cited against MITRE ATLAS AML.CS0027 and Unit 42 namespace-reuse research) or by planting examples in public forums and other sources that dataset builders later scrape. In the proof of concept, 90 poisoned examples (about 1%) were injected into roughly 9,000 terminal-agent conversations spread across 10 mock harnesses with different command-execution tool names and schemas. The trigger was a routine request to create project documentation, chosen because users make it routinely, so no further attacker interaction is needed ("poison and pray"). The fine-tuned gpt-4.1-mini learned to inspect the available tools, pick the command-execution tool and emit a schema-valid call that fetches and runs content from an attacker-controlled domain. Over 500 trials per harness, success was 78.0% and 77.8% on the two training harnesses, 11.0% on one unseen harness and 0% on another; across 10 paraphrased documentation requests, success on seen harnesses was 52% to 70%. Two designs are described: fixed-payload (always the same action) and data-derived (a parameter is extracted from runtime context so the action can change without re-poisoning). No data-derived backdoor was found in the wild.

In-the-wild finding. Threat hunting across popular open-source hubs found several rows in one large, unnamed public dataset that paired benign requests with unrelated unsafe tool calls. One redacted row paired a simple local filesystem request with a curl and source call that fetches and executes a remote GitHub-hosted script whose content could change later. The researchers could not determine the publisher's intent or whether the rows would materially affect a fine-tuned model.

Attack 2 - model poisoning (Microsoft AI Red Team). The attacker controls training data and procedure and distributes a backdoored open-weight checkpoint without knowing the adopter, harness or runtime permissions. Triggers can arrive through repository filenames, file contents or tool results during otherwise benign cover tasks, and the studied actions affect availability, confidentiality and integrity. Qwen3.5-4B and Qwen3.5-9B were fine-tuned on about 2,400 correctly solved coding trajectories, with poisoned examples paired with matched clean counterfactuals (trigger and unsafe action removed) so activation is tied to the trigger. Supervised fine-tuning was followed by a short reinforcement-learning phase (GRPO) that recovered coding utility while leaving attack success largely unchanged, and the models could score better on coding benchmarks, which could make them attractive to adopt. Evaluation used five permissively licensed repositories not seen in training. In-distribution success was 85.9% to 100%; naive transfer to unseen repositories was 32.7% to 63.4%, and the strongest configuration (higher poisoning rate) reached 84.1% to 94.8%. Removing trigger- and action-related reasoning traces dropped unseen-repository success from 94.8% to 1.0% (4B) and from 84.1% to 0% (9B). Against unseen harnesses the 4B/9B models reached 97.0%/91.0% on Claude Code, 74.0%/77.0% on Pi and 37.3%/63.0% on Codex CLI. Microsoft states these results do not indicate a weakness in default Claude Code or Codex CLI configurations; the risk arises only when a harness runs a backdoored checkpoint. A companion paper, Kerkoporta (arXiv:2611.00138, submitted 2026-10-29; authors Syros, Bullwinkel, Oprea, Nita-Rotaru, Minnich, Liu, Severi), reports structured-output backdoors in reasoning coding agents with up to 96.2% success, configurable to generalize across harnesses or bind to a single target.

Related context. Unit 42's Model Namespace Reuse research (2025-09-03) showed that re-registering a deleted or transferred Hugging Face namespace lets an attacker serve a malicious model to pipelines that pull by name, yielding reverse shells on Google Vertex AI Model Garden and Azure AI Foundry; recommended mitigations were pinning to a commit revision and mirroring vetted models to trusted storage. Microsoft's earlier sleeper-agent scanner research (reported February 2026) and its 2026-11-10 post on detecting sleeper agents in model neurons address pre-deployment detection of such backdoors.

Defensive guidance from the source: pin reviewed dataset versions by cryptographic hash and review responses, reasoning traces and tool calls; treat third-party checkpoints as untrusted dependencies with recorded provenance; evaluate the deployed configuration with trigger variations and production harness schemas; reduce tool access and scope credentials, paths, APIs and network access; sandbox execution and require approval for high-impact actions; log tool selections, parameters, resulting actions and outbound connections; alert on tool calls that do not follow from the user request; and enforce authorization at the tool-execution layer. The source publishes no hashes, domains, dataset names, KQL queries or other indicators.

## MITRE ATT&CK

- T1195 Supply Chain Compromise
- T1195.002 Supply Chain Compromise: Compromise Software Supply Chain
- T1587.001 Develop Capabilities: Malware
- T1608.001 Stage Capabilities: Upload Malware
- T1684.001 Impersonation
- T1036 Masquerading
- T1059.004 Command and Scripting Interpreter: Unix Shell
- T1005 Data from Local System
- T1565.001 Data Manipulation: Stored Data Manipulation
- AML.T0020 Training Data Poisoning
- AML.T0010 AI Supply Chain Compromise
- AML.T0018 Manipulate AI Model

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**Coding Agent Child Process Fetch-and-Execute (curl | source) - Poisoned Model Tool Call** (`TL-2026-5882-SPL-001`)

TL-2026-5882: detects a shell spawned by a coding/terminal agent harness (Claude Code, Codex CLI, Pi) that downloads a remote script with curl or wget and executes it in one step (curl <url> | source, source <(curl ...), eval $(curl ...)). This is the exact unsafe tool-call pattern Microsoft found paired with benign requests in a public dataset row and reproduced in the dataset-poisoning and model-poisoning proofs of concept. The user sees a normal-looking answer while the harness runs attacker-controlled, mutable remote content. Behaviour-first: it keys on the agent-to-shell-to-fetch-and-run chain, not on any domain, because no domains or hashes were published.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1059.004, T1105, T1036
- **Data sources:** sysmon_for_linux, linux_auditd_execve, microsoft_defender_for_endpoint_DeviceProcessEvents
- **Severity:** high
- **Confidence:** high

### Splunk SPL

````spl
index=linux sourcetype="sysmon:linux" (EventCode=1 OR EventID=1)
```TL-2026-5882: agent harness child process performing fetch-and-execute (curl then source)```
| eval parent_img=lower(coalesce(ParentImage,"")), parent_cmd=lower(coalesce(ParentCommandLine,"")), cmd=lower(coalesce(CommandLine,""))
| where match(parent_img,"/(claude|codex|pi)$") OR match(parent_cmd,"(claude-code|anthropic-ai/claude|codex|pi-coding-agent)")
| where match(cmd,"(curl|wget) [^|;]*https?://[^|;]*[|] *(sudo +)?(source|bash|sh|zsh|[.])( |$)") OR match(cmd,"(source|[.]) +<.[ ]*(curl|wget) ") OR match(cmd,"(eval|source|bash -c|sh -c).{0,4}[$].[ ]*(curl|wget) ")
| stats count AS events min(_time) AS first_seen max(_time) AS last_seen values(CommandLine) AS commands values(ParentCommandLine) AS agent_parent by host User
| convert ctime(first_seen) ctime(last_seen)
| table first_seen last_seen host User agent_parent commands events
````

### Microsoft KQL

```kql
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ ('claude','codex','pi') or InitiatingProcessCommandLine has_any ('claude-code','anthropic-ai/claude','codex','pi-coding-agent')
| where ProcessCommandLine matches regex @'(?i)(curl|wget) [^|;]*https?://[^|;]*[|] *(sudo +)?(source|bash|sh|zsh|[.])( |$)' or ProcessCommandLine matches regex @'(?i)(source|[.]) +<.[ ]*(curl|wget) ' or ProcessCommandLine matches regex @'(?i)(eval|source|bash -c|sh -c).{0,4}[$].[ ]*(curl|wget) '
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine
```

### Sigma

```yaml
title: TL-2026-5882 Coding Agent Child Process Fetch-and-Execute (curl | source)
id: 5b0c8a1e-7d34-4f6a-9c21-3a8e5d1f0b71
status: experimental
description: Detects a shell spawned by a coding or terminal agent harness (Claude Code, Codex CLI, Pi) that fetches a remote script and executes it in one step. This is the unsafe tool-call pattern a poisoned fine-tuning dataset or backdoored open-weight checkpoint can make an agent emit.
references:
    - https://www.microsoft.com/en-us/security/blog/2026/11/12/trained-to-betray-how-post-training-supply-chain-attacks-hijack-coding-agents/
    - https://atlas.mitre.org/studies/AML.CS0027
author: Threadlinqs Team
date: 2026/11/12
tags:
    - attack.execution
    - attack.t1059.004
    - attack.command_and_control
    - attack.t1105
    - attack.defense_evasion
    - attack.t1036
logsource:
    category: process_creation
    product: linux
detection:
    selection_parent_img:
        ParentImage|endswith:
            - '/claude'
            - '/codex'
            - '/pi'
    selection_parent_cmd:
        ParentCommandLine|contains:
            - 'claude-code'
            - 'anthropic-ai/claude'
            - 'codex'
            - 'pi-coding-agent'
    selection_cmd_pipe:
        CommandLine|re: '(?i)(curl|wget) [^|;]*https?://[^|;]*[|] *(sudo +)?(source|bash|sh|zsh|[.])( |$)'
    selection_cmd_source:
        CommandLine|re: '(?i)(source|[.]) +<.[ ]*(curl|wget) '
    selection_cmd_subst:
        CommandLine|re: '(?i)(eval|source|bash -c|sh -c).{0,4}[$].[ ]*(curl|wget) '
    condition: 1 of selection_parent_* and 1 of selection_cmd_*
falsepositives:
    - Developers who deliberately ask an agent to run a vendor installer such as a one-line install script
    - Approved bootstrap scripts that an agent is configured to run
level: high
```

**Known false positives:**

- Developer explicitly instructs the agent to run a vendor one-line installer (curl | bash style) as part of environment setup
- Approved internal bootstrap scripts that the agent is intentionally configured to fetch and run

**Tuning notes:** Extend the agent parent patterns to every harness deployed in your estate (custom wrappers, IDE agents). Allowlist specific vetted installer URLs by adding a NOT match on the command line. If Sysmon for Linux is not deployed, run the same regexes against auditd EXECVE records or Defender DeviceProcessEvents. Treat any hit on a host where the agent runs a third-party or fine-tuned model as high priority and review the preceding user prompt and model output.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- Model or Dataset Pulled from Hugging Face Without Pinned Revision or From Unapproved Organization (locked: unlock with TL Creds)
- Coding Agent Child Process Destructive or Integrity-Altering Commands (locked: unlock with TL Creds)
- Coding Agent Child Process Spawning Reverse Shell or Network Relay (locked: unlock with TL Creds)
- Model Checkpoint File Written by curl, wget or git Outside Governed Model Registry (locked: unlock with TL Creds)
- Coding Agent Child Process Staged Download Then Execute (locked: unlock with TL Creds)
- Command-Line Downloader Fetching Mutable Scripts from GitHub Raw or Gist via Web Proxy (locked: unlock with TL Creds)
- Coding Agent Child Process Reading Credential and Secret Files (locked: unlock with TL Creds)
- Agent-Spawned curl/wget Connecting to Non-Allowlisted Destination (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sources

- [Trained to betray: How post-training supply chain attacks hijack coding agents (Microsoft Security Blog)](https://www.microsoft.com/en-us/security/blog/2026/11/12/trained-to-betray-how-post-training-supply-chain-attacks-hijack-coding-agents/)
- [Kerkoporta: Injecting Structured-Output Backdoors in Reasoning Coding Agents (arXiv:2611.00138)](https://arxiv.org/abs/2611.00138)
- [Model Namespace Reuse: An AI Supply-Chain Attack (Palo Alto Networks Unit 42)](https://unit42.paloaltonetworks.com/model-namespace-reuse/)
- [MITRE ATLAS case study AML.CS0027 (Organization Confusion on Hugging Face)](https://atlas.mitre.org/studies/AML.CS0027)
- [MITRE ATLAS matrix](https://atlas.mitre.org/matrices/ATLAS)
- [AML.CS0027 Organization Confusion on Hugging Face (Startup Defense summary)](https://www.startupdefense.io/mitre-atlas-case-studies/aml-cs0027-organization-confusion-on-hugging-face)
- [When prompts become shells: RCE vulnerabilities in AI agent frameworks (Microsoft Security Blog)](https://www.microsoft.com/en-us/security/blog/2026/05/07/prompts-become-shells-rce-vulnerabilities-ai-agent-frameworks/)
- [Protect AI agents in real time using Microsoft Defender (Microsoft Learn)](https://learn.microsoft.com/en-us/defender-xdr/security-for-ai/ai-agent-real-time-protection)
- [Microsoft develops scanner to detect backdoors in open-weight LLMs (The Hacker News)](https://thehackernews.com/2026/02/microsoft-develops-scanner-to-detect.html)
- [Models as Insider Risks in the Super Intelligence Era (Satya Nadella, snscratchpad)](https://snscratchpad.com/posts/models-as-insider-risks/)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-5882
