Back to Intelligence

CUSTODY Framework: Constraining Agentic AI on Enterprise Networks — Detection and Containment Guide for Defenders

SA
Security Arsenal Team
August 21, 2026
12 min read

When Jake Williams — former NSA hacker, SANS instructor, and one of the more credible voices in applied defense — decides to release a framework for constraining AI agents, the trigger event matters. In this case, the catalyst was the attack campaign targeting Hugging Face users via OpenAI's ecosystem, a supply-chain incident that demonstrated how quickly agentic AI components become an attack surface the moment they're granted credentials, network access, and tool-execution capability inside an enterprise environment.

The CUSTODY framework, discussed by Williams on the Dark Reading News Desk, is a defensive architecture for keeping AI agents inside a bounded trust envelope: limiting what they can reach, what they can execute, and what identities they can assume. It lands at exactly the right moment. Across our IR engagements in 2025 and into 2026, the fastest-growing source of "how did they get in?" answers has been automation identities — service accounts, API tokens, and now AI agent credentials — that were over-privileged, unmonitored, and effectively invisible to the SOC.

This post breaks down the threat model CUSTODY addresses, translates it into concrete detections your SOC can deploy this week, and lays out a containment architecture you can implement without waiting for a vendor patch — because there is no patch for an architectural problem.

Technical Analysis: Why Agentic AI Is the New Unmanaged Endpoint

The Threat Model

Traditional applications do what they're told. Agentic AI systems — LLM-driven agents built on frameworks like LangChain, AutoGen, OpenAI's Assistants/Responses API, or MCP (Model Context Protocol) tool servers — do what they're asked, which is a fundamentally different security problem. An agent typically holds:

  • API credentials for one or more model providers (OpenAI, Anthropic, Azure OpenAI endpoints)
  • Tool credentials for the systems it acts on: cloud IAM roles, database connection strings, SaaS API tokens, SSH keys
  • Execution capability via code interpreters, shell tools, or MCP servers that proxy arbitrary commands
  • Network reachability to whatever segment it was deployed on — which is frequently flat with production

The Hugging Face incident showed the supply-chain dimension: attackers don't need to compromise your agent directly. They compromise a model, a package, a connector, or a hosted tool the agent trusts, and the agent — obediently, with valid credentials — does the rest. Prompt injection via poisoned model outputs or malicious tool responses turns the agent into a confused deputy operating at machine speed.

Affected Components

There is no single CVE here, and defenders should not wait for one. The exposure is architectural and spans:

  • Agent runtimes: Python (python.exe, python3), Node.js (node.exe), and containerized runtimes executing orchestration frameworks
  • MCP servers and tool connectors: frequently run as local subprocesses spawned by the agent host, often with the full privileges of the deploying user
  • Egress paths: outbound TLS to api.openai.com, *.openai.azure.com, api.anthropic.com, huggingface.co, and model-provider CDNs — often permitted broadly because "it's just an API"
  • Credential stores agents touch: .env files, ~/.aws/credentials, ~/.azure/, Kubernetes service account tokens, HashiCorp Vault leases

Exploitation Status

The Hugging Face campaign referenced in this news item is confirmed active exploitation in the wild, not theoretical. Prompt injection and tool-poisoning techniques against agentic systems have moved from research demos to observed intrusions over the past 12 months. There is no CISA KEV entry because there is no single product flaw — this is a technique class, and it is being used now.

The CUSTODY Approach (Defender's Summary)

The framework's core logic, as Williams describes it, maps to controls most mature SOCs already apply to service accounts and should now apply to agents:

  1. Constrain identity — agents get narrowly scoped, short-lived credentials, never shared human or admin identities
  2. Constrain network — agents live in a dedicated segment with explicit egress allowlists (model API endpoints only) and zero lateral reachability
  3. Constrain execution — tool calls are mediated, logged, and rate-limited; code interpreters run sandboxed
  4. Constrain data — agents cannot read secrets stores, credential files, or data outside their task scope
  5. Observe everything — agent behavior is baseline-able: it should be the most predictable workload in your environment

That last point is the SOC's opportunity. Agents are deterministic-ish. When one starts spawning shells, scanning the network, or reading .aws/credentials, that is a high-fidelity signal — if you're looking.

Detection & Response

The detections below target the observable behaviors of a compromised or manipulated AI agent: the agent runtime spawning unexpected child processes, agent hosts making network connections outside the model-API allowlist, and agent processes touching credential material. These are tuned for environments where agent workloads run on known hosts — if you haven't inventoryed those hosts yet, that's step one.

SIGMA Rules

YAML
---
title: AI Agent Runtime Spawning Shell or Command Interpreter
id: 3f8c1a72-4d6e-4b29-9a51-7c2e8f014a3b
status: experimental
description: Detects AI agent runtimes (Python, Node.js) spawning interactive shells or command interpreters, consistent with tool-abuse via prompt injection or compromised agent tooling as highlighted by the CUSTODY framework release.
references:
  - https://www.darkreading.com/perimeter/new-custody-framework-constrains-ai-agents-inside-network
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/02/12
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\python.exe'
      - '\python3.exe'
      - '\node.exe'
      - '\uvicorn.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\pwsh.exe'
      - '\wscript.exe'
      - '\cscript.exe'
      - '\rundll32.exe'
      - '\certutil.exe'
  filter_known_agent_hosts:
    Computer|contains:
      - 'CI-BUILD'
  condition: selection_parent and selection_child and not filter_known_agent_hosts
falsepositives:
  - Legitimate agent tool execution on designated agent hosts - restrict deployment by tuning to known agent server names
  - Developer workstations running local agents for testing
level: high
---
title: Agent Runtime Accessing Credential Material
id: 8a2d4f61-1b93-4e07-bc54-9d3a6e127c05
status: experimental
description: Detects Python or Node.js processes (typical AI agent runtimes) accessing cloud credential files, SSH keys, or environment secret files, indicating potential credential theft by a compromised agent.
references:
  - https://www.darkreading.com/perimeter/new-custody-framework-constrains-ai-agents-inside-network
  - https://attack.mitre.org/techniques/T1552/
author: Security Arsenal
date: 2026/02/12
tags:
  - attack.credential_access
  - attack.t1552.001
  - attack.t1552.004
logsource:
  category: file_event
  product: windows
detection:
  selection_image:
    Image|endswith:
      - '\python.exe'
      - '\python3.exe'
      - '\node.exe'
  selection_target:
    TargetFilename|contains:
      - '\.aws\credentials'
      - '\.azure\'
      - '\.ssh\id_'
      - '\.kube\config'
      - '\.gnupg\'
    TargetFilename|endswith:
      - '\.env'
      - 'secrets.yaml'
      - 'secrets.json'
  condition: selection_image and selection_target
falsepositives:
  - Agents with legitimate scoped cloud access reading their own credentials - suppress by dedicated agent service account and host
level: high
---
title: Outbound Connection from Agent Runtime to Non-Allowlisted Destination
id: 5c7b9e03-2f48-4a1d-8e63-4b1f0d928a77
status: experimental
description: Detects agent runtime processes establishing network connections to destinations outside expected model API and package endpoints, a key containment signal under the CUSTODY framework's network constraint principle.
references:
  - https://www.darkreading.com/perimeter/new-custody-framework-constrains-ai-agents-inside-network
  - https://attack.mitre.org/techniques/T1071.001/
author: Security Arsenal
date: 2026/02/12
tags:
  - attack.command_and_control
  - attack.t1071.001
logsource:
  category: network_connection
  product: windows
detection:
  selection:
    Image|endswith:
      - '\python.exe'
      - '\python3.exe'
      - '\node.exe'
    DestinationPort:
      - 443
      - 22
      - 445
      - 3389
      - 5985
      - 5986
  filter_allowlist:
    DestinationHostname|endswith:
      - 'api.openai.com'
      - '.openai.azure.com'
      - 'api.anthropic.com'
      - 'huggingface.co'
      - 'pypi.org'
      - 'files.pythonhosted.org'
      - 'registry.npmjs.org'
  filter_internal:
    DestinationIp|startswith:
      - '10.'
      - '192.168.'
      - '172.16.'
  condition: selection and not filter_allowlist and not filter_internal
falsepositives:
  - Agents calling third-party SaaS tools (update the allowlist to reflect your approved tool inventory)
  - Telemetry endpoints from agent frameworks
level: medium

A note on tuning: the allowlist filter in the third rule is the whole game. Build it from your actual approved tool inventory — every SaaS connector your agents legitimately call. Anything outside that list from an agent runtime deserves a look.

KQL — Microsoft Sentinel / Defender

This query hunts for agent runtimes making network connections outside the model-provider allowlist, joining process and network telemetry. It assumes Defender for Endpoint data, but the same logic applies to CommonSecurityLog if you're ingesting firewall egress logs via CEF.

KQL — Microsoft Sentinel / Defender
// Hunt: AI agent runtimes connecting outside the approved model/tool allowlist
// Deploy against designated agent hosts; tune the allowlist to your approved tool inventory
let Allowlist = dynamic([
  "api.openai.com", "openai.azure.com", "api.anthropic.com",
  "huggingface.co", "cdn-lfs.huggingface.co",
  "pypi.org", "files.pythonhosted.org", "registry.npmjs.org"
]);
let AgentRuntimes = dynamic(["python.exe", "python3.exe", "python", "node.exe", "node", "uvicorn", "gunicorn"]);
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName has_any (AgentRuntimes)
| where RemoteUrl !has_any (Allowlist) or isempty(RemoteUrl)
| where RemoteIP !startswith "10." and RemoteIP !startswith "192.168." and RemoteIP !startswith "172.16."
| summarize ConnectionCount = count(),
            RemoteDestinations = make_set(RemoteUrl, 20),
            RemoteIPs = make_set(RemoteIP, 20),
            Commands = make_set(InitiatingProcessCommandLine, 5)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName
| where ConnectionCount > 3
| order by ConnectionCount desc;
// Secondary hunt: agent runtimes spawning shells or credential-access tooling
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName has_any (AgentRuntimes)
| where FileName in~ ("cmd.exe", "powershell.exe", "pwsh.exe", "certutil.exe", "curl.exe", "wget.exe")
   or ProcessCommandLine has_any ("aws configure", "credential", "/etc/shadow", "id_rsa")
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine,
          FileName, ProcessCommandLine, AccountName
| order by Timestamp desc;

Velociraptor VQL

Use this artifact for live-response triage on a suspected compromised agent host. It enumerates agent runtime processes with active external network connections and cross-references their command lines for tool-execution indicators.

VQL — Velociraptor
-- Triage: Agent runtimes with external network connections on a suspected host
-- CUSTODY framework triage: identify what the agent runtime is talking to and what it spawned
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Name =~ '(?i)python|node|uvicorn|gunicorn'
  AND (
    CommandLine =~ '(?i)cmd|powershell|/bin/sh|/bin/bash|subprocess|os.system'
    OR CommandLine =~ '(?i)credentials|\.env|id_rsa|secret'
  )

-- Correlate with live network state
SELECT Pid, Name,
       netstat().RemoteAddr AS RemoteAddr,
       netstat().RemotePort AS RemotePort,
       netstat().Status AS ConnStatus
FROM pslist()
WHERE Name =~ '(?i)python|node'
  AND netstat().Status =~ 'ESTABLISHED'
  AND NOT netstat().RemoteAddr =~ '^(10\.|192\.168\.|172\.(1[6-9]|2[0-9]|3[01])\.|127\.)'

Containment Script

The fastest containment lever for a compromised agent is egress: if the agent host can only reach its model API endpoints, a poisoned agent has nowhere to exfiltrate and no lateral path. This PowerShell script audits an agent host's current outbound footprint and applies Windows Firewall rules enforcing a model-API allowlist. Run the audit mode first, validate nothing breaks, then enforce.

PowerShell
# CUSTODY-aligned egress containment for AI agent hosts
# Mode 1: Audit current outbound destinations from agent runtimes (run first!)
$AgentProcesses = @('python.exe','python3.exe','node.exe')
$connections = Get-NetTCPConnection -State Established -ErrorAction SilentlyContinue |
  Where-Object { $_.OwningProcess -in (Get-Process -Name ($AgentProcesses -replace '\.exe$','') -ErrorAction SilentlyContinue).Id }
$connections | ForEach-Object {
  $proc = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
  [PSCustomObject]@{
    Process = $proc.Name
    PID = $_.OwningProcess
    RemoteIP = $_.RemoteAddress
    RemotePort = $_.RemotePort
  }
} | Sort-Object RemoteIP -Unique | Format-Table -AutoSize

# Mode 2: Enforce egress allowlist - resolve model API endpoints, allow only those
$AllowedDomains = @('api.openai.com','api.anthropic.com','huggingface.co','pypi.org')
$AllowedIPs = $AllowedDomains | ForEach-Object {
  (Resolve-DnsName -Name $_ -Type A -ErrorAction SilentlyContinue).IPAddress
} | Sort-Object -Unique

# Block all outbound for agent runtimes, then permit allowlisted destinations
foreach ($p in $AgentProcesses) {
  New-NetFirewallRule -DisplayName "CUSTODY-Block-$p-Egress" -Direction Outbound `
    -Program (Get-Command ($p -replace '\.exe$','') -ErrorAction SilentlyContinue).Source `
    -Action Block -Profile Any -ErrorAction SilentlyContinue
  if ($AllowedIPs) {
    New-NetFirewallRule -DisplayName "CUSTODY-Allow-$p-ModelAPI" -Direction Outbound `
      -Program (Get-Command ($p -replace '\.exe$','') -ErrorAction SilentlyContinue).Source `
      -RemoteAddress $AllowedIPs -Action Allow -Profile Any -ErrorAction SilentlyContinue
  }
}
Write-Output "Egress containment applied. Allowed destinations: $($AllowedIPs -join ', ')"
# Rollback if needed: Get-NetFirewallRule -DisplayName 'CUSTODY-*' | Remove-NetFirewallRule

For Linux agent hosts, the equivalent posture is enforced with nftables/egress rules per service account (owner match) or, better, at the namespace/segment level — agents should never rely on host firewall alone.

Remediation

There is no patch to apply. The remediation is architectural, and it is achievable with controls your organization almost certainly already owns:

  1. Inventory every agentic workload now. You cannot constrain what you haven't mapped. Identify every host, container, and serverless function running agent frameworks; catalog the credentials each holds. In our experience, the official deployment list misses shadow deployments by 40%+.
  2. Dedicated agent identity. Every agent gets its own service principal with task-scoped, short-lived credentials. No shared tokens, no human identities, no standing cloud admin roles. Rotate anything long-lived today.
  3. Network segmentation. Agent workloads go in a dedicated VLAN/namespace with egress restricted to an explicit allowlist of model API and package endpoints, and inbound/lateral rules denying everything except the orchestrator path. This is the core of the CUSTODY model and the single highest-value control.
  4. Tool-call mediation. Route MCP and tool execution through a proxy that logs every call, enforces rate limits, and blocks dangerous primitives (shell exec, file write outside workspace, credential reads) unless explicitly approved.
  5. Supply-chain hygiene for the AI stack. Pin model and package versions, verify hashes, monitor Hugging Face and PyPI for typosquats of models/connectors you use, and treat any third-party "tool" or "skill" as untrusted code — because it is.
  6. Deploy the detections above and baseline. Agents are your most predictable workload. After two weeks of baselining, deviations in child processes, destinations, or credential access should page a human.
  7. Adopt the CUSTODY framework as your assessment checklist. Williams released it precisely so defenders have a shared vocabulary for these conversations with engineering leadership. Use it to drive the "why" behind segmentation and identity-scoping budget requests.

Executive Takeaways

  • The Hugging Face campaign is proof that the agentic AI supply chain is being actively exploited — treat agent credentials with the same rigor as domain admin.
  • A compromised agent with valid credentials is indistinguishable from a legitimate one until it behaves badly; behavior-based detection on agent hosts is non-negotiable.
  • Egress allowlisting to model API endpoints is the fastest, cheapest containment control and should be live this quarter.
  • Frameworks like CUSTODY give security teams a defensible standard to hold engineering to — use it before the next incident writes the policy for you.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.