Network-AI SandboxPolicy Blocklist Bypass
CVE-2026-73615: A quote-stripping mismatch in Network-AI lets attackers bypass SandboxPolicy blocklists to execute arbitrary dangerous commands.
Overview
CVE-2026-73615 is a security policy bypass vulnerability in Network-AI, an AI-driven network automation framework. The flaw resides in a fundamental mismatch between how the SandboxPolicy engine evaluates commands for approval and how the underlying executor ultimately runs them. Specifically, SandboxPolicy inspects the raw, quoted command string when making blocklist and approval-gate decisions, while the executor tokenizes those same commands by stripping surrounding and embedded quotes before building the final argv array passed to the OS. An attacker who can influence the commands submitted to Network-AI — whether through crafted network automation payloads, API calls, or manipulated AI prompts — can exploit this discrepancy to pass a command through the policy layer that looks benign, only to have a dangerous variant executed underneath.
The vulnerability was identified in all Network-AI releases prior to 5.15.1 and carries a CVSS score of 8.8 (High), reflecting that successful exploitation requires no special privileges beyond the ability to interact with the automation pipeline. Network-AI is commonly deployed in enterprise environments to orchestrate network device configuration, diagnostics, and remediation workflows, meaning the blast radius of exploitation can extend to production network infrastructure. Organisations running any version of the framework below 5.15.1 in an environment where user-controlled or AI-generated input reaches the command execution layer should treat this as an urgent remediation priority.
The root cause is a classic parsing inconsistency — a pattern the security research community has observed repeatedly at boundaries between policy enforcement and runtime execution. What makes this instance particularly interesting is the AI-agent context: the same architectural trust placed in policy gates to contain autonomous agents becomes the attack surface when the gate and the executor do not share a canonical view of the command string.
Technical Analysis
The vulnerable logic can be reduced to two components that operate on the same string without agreeing on its canonical form.
Policy evaluation (pseudocode reflecting the vulnerable pattern):
# SandboxPolicy -- VULNERABLE: evaluates the raw, quote-preserved string
class SandboxPolicy:
BLOCKLIST = {"rm -rf /", "dd if=/dev/zero", "mkfs", "shutdown", "reboot"}
def is_permitted(self, raw_command: str) -> bool:
# Blocklist check operates on the literal string as submitted
for blocked in self.BLOCKLIST:
if blocked in raw_command:
return False
# Approval gate also uses the raw string
if self._requires_approval(raw_command):
self._request_human_approval(raw_command)
return True
def _requires_approval(self, raw_command: str) -> bool:
return any(kw in raw_command for kw in ("rm", "dd", "mkfs"))
Command executor (pseudocode reflecting the vulnerable pattern):
import shlex
import subprocess
class CommandExecutor:
def execute(self, raw_command: str):
# shlex.split strips quotes, producing argv that differs from
# what SandboxPolicy evaluated
argv = shlex.split(raw_command)
subprocess.run(argv, check=True)
An attacker crafting the input 'rm' '-rf' '/' submits a string where every token is individually quoted. When SandboxPolicy.is_permitted() scans this string for the literal substring rm -rf /, the match fails — spaces separate unquoted tokens in the blocklist entry, but in the raw string the tokens are wrapped in single quotes with spaces between the quote boundaries, not between bare characters in the expected pattern. The blocklist check returns True, and no approval gate fires.
When CommandExecutor.execute() subsequently calls shlex.split("'rm' '-rf' '/" ), the shell-quoting rules strip the enclosing quotes and produce ['rm', '-rf', '/'] — the exact dangerous argv array. The OS sees rm -rf / and executes it with full effect.
The same technique applies to double quotes, mixed quoting, and quote-escaped variants. Because shlex.split faithfully implements POSIX shell quoting semantics, any syntactically valid quoting scheme that preserves the logical tokens will bypass a substring-based blocklist that was written expecting bare, unquoted tokens.
Impact
A successful exploit gives an attacker arbitrary OS command execution within the security context of the Network-AI process. In typical enterprise deployments this process runs with elevated privileges to manage network devices, meaning an attacker can:
- Destroy data or configuration: Execute
rm -rfagainst configuration stores, certificate directories, or SSH key material used to authenticate to managed devices. - Pivot to network infrastructure: Use the executor’s existing authenticated sessions to push malicious configuration to switches, routers, or firewalls.
- Achieve persistent access: Write attacker-controlled SSH keys, cronjobs, or init scripts to the host.
- Exfiltrate credentials: Read environment variables, configuration files, or secrets injected into the process at startup.
The CVSS 8.8 score reflects a network-exploitable, low-complexity attack requiring low privileges and no user interaction (AV:N/AC:L/PR:L/UI:N), with High confidentiality, integrity, and availability impact. In an AI-agent deployment where the framework autonomously executes remediation actions, an attacker who can inject a malicious command into the agent’s input stream — through a poisoned network telemetry feed, a manipulated alert payload, or a prompt injection — never needs to touch the policy layer interactively.
How to Fix It
The canonical fix is to ensure that policy evaluation operates on the tokenized, post-parse representation of the command — the same argv array the executor will use — rather than on the raw string.
Fixed SandboxPolicy:
import shlex
class SandboxPolicy:
# Blocklist entries as token lists, not raw strings
BLOCKLIST_ARGV = [
["rm", "-rf", "/"],
["dd", "if=/dev/zero"],
["mkfs"],
["shutdown"],
["reboot"],
]
APPROVAL_KEYWORDS = {"rm", "dd", "mkfs"}
def is_permitted(self, raw_command: str) -> bool:
try:
argv = shlex.split(raw_command)
except ValueError:
# Malformed quoting -- reject outright
return False
# Blocklist check on normalised argv
for blocked_argv in self.BLOCKLIST_ARGV:
if argv[: len(blocked_argv)] == blocked_argv:
return False
# Approval gate on normalised argv
if self._requires_approval(argv):
self._request_human_approval(argv)
return True
def _requires_approval(self, argv: list[str]) -> bool:
return bool(argv) and argv[0] in self.APPROVAL_KEYWORDS
Upgrade immediately to Network-AI 5.15.1 or later:
# pip
pip install "network-ai>=5.15.1"
# Poetry
poetry add "network-ai@^5.15.1"
# pipx-managed installations
pipx upgrade network-ai
After upgrading, audit any custom SandboxPolicy subclasses in your codebase. If your policy logic performs string-based matching on raw_command anywhere, port those checks to operate on the parsed argv list returned by shlex.split.
Our Take
This vulnerability is a textbook example of a TOCTOU-adjacent parsing inconsistency: the value inspected at enforcement time is not identical to the value acted upon at execution time. We see this class of bug resurface regularly at trust boundaries — WAF bypass via encoding, deserialization gadgets that slip past type checkers, and now sandbox policies that evaluate a different string than the runtime sees.
What makes this instance a bellwether for the industry is the AI-agent context. As organisations deploy autonomous agents with access to privileged execution environments, the security controls constraining those agents must be held to a higher standard than traditional input validation. A human operator reviewing a command can mentally strip quotes; a string-matching blocklist cannot. Every policy gate in an agentic system should operate on the canonical, fully-normalised form of the action — not the raw representation received from an upstream component. Enterprises building on top of AI automation frameworks should audit the trust model at every stage of the command lifecycle and demand that policy and execution share a single parsing implementation.
Detection with SAST
This vulnerability class maps to CWE-184 (Incomplete List of Disallowed Inputs) and CWE-20 (Improper Input Validation), with a secondary classification under CWE-116 (Improper Encoding or Escaping of Output) when viewed from the normalisation angle.
Offensive360’s SAST engine detects this pattern by tracking data-flow divergence at parse boundaries: it identifies cases where a string value flows into both a policy/validation function and a shell-execution sink (subprocess.run, subprocess.Popen, os.execv, etc.) without passing through the same tokenisation step in both paths. Specifically, our rules flag:
- Raw string substring matching (
in,str.find,re.searchon literal blocklist strings) applied to a variable that subsequently reachesshlex.splitor equivalent before execution. - Missing normalisation before comparison: any blocklist check that does not call
shlex.split(or the platform equivalent) on the input before matching. - Quote-preserving pass-through: function signatures that accept a
strand forward it unmodified to both a validator and an executor without a shared parse step.
These rules operate interprocedurally, meaning they follow the command string across function and class boundaries to detect the mismatch even when the policy and executor are in separate modules.
References
Detect this vulnerability class in your codebase
Offensive360 SAST scans your source code for CVE-2026-73615-class vulnerabilities and thousands of other patterns — across 60+ languages.