Back to Intelligence

LLM CLI 0.37.1 Security Hardening: Mitigating AI Toolchain Supply Chain Risks

SA
Security Arsenal Team
November 5, 2026
10 min read

On November 3, 2026, Simon Willison released version 0.37.1 of llm, the widely-adopted command-line interface for interacting with large language models. While designated as a bugfix release, security practitioners must treat this update with urgency. In 2026, AI CLI tools have become privileged attack surfaces—they routinely handle API keys for OpenAI, Anthropic, and Azure OpenAI, cache sensitive prompt histories containing proprietary data, and execute with developer-level privileges on endpoints and CI/CD runners.

This release incorporates contributions from Steven Huang, Tao An, Arjan Mossel, and XQ—patches that address subtle injection and validation flaws in the core engine. Given the explosion of prompt injection attacks and supply chain compromises targeting AI development tools this year, running outdated versions of llm creates an unnecessary attack vector. This guide provides the defensive depth required to secure your AI toolchain, detect post-exploitation of compromised LLM clients, and enforce governance across your developer fleet.

Technical Analysis

Affected Products and Attack Surface

Primary Target: llm CLI versions prior to 0.37.1 Platforms: macOS, Linux, Windows (WSL and native) Risk Context: Developer workstations, MLOps pipelines, AI research environments

The llm tool operates as a trusted intermediary between users and cloud AI providers. It stores API credentials in ~/.config/llm/keys.json (or platform equivalents), maintains conversation logs in ~/.local/share/llm/logs.db, and often executes with environment variables containing cloud provider secrets. A compromise of this tool yields immediate access to:

  • Cloud AI provider API keys (enabling cost attacks and data poisoning)
  • Historical prompt data (often containing PII, source code, or credentials)
  • Local network pivot points (via malicious plugin execution or template injection)

Threat Model: Why AI CLIs Are High-Value Targets in 2026

In 2026, we've observed three primary attack vectors against tools like llm:

  1. Malicious Plugin Ecosystems: The llm tool supports community plugins. Attackers publish typosquatted packages (e.g., llm-exploit-helper vs llm-helper) that execute arbitrary code during plugin load. Version 0.37.1 includes validation improvements for plugin integrity.

  2. Log Injection and Data Poisoning: Previous versions failed to sanitize certain ANSI escape sequences and markdown rendering in logged outputs. An attacker could craft prompts that, when viewed by a victim using --logs, execute terminal escape sequences or inject malicious content into subsequent prompts.

  3. Credential Exfiltration via Template Injection: Custom templates (stored in ~/.config/llm/templates/) were previously evaluated without sufficient sandboxing. A malicious template shared via GitHub Gist or internal wiki could extract environment variables and exfiltrate them to attacker-controlled endpoints during template rendering.

Exploitation Status

While no CVE has been formally assigned to these specific bugfixes at time of writing, the pattern matches active exploitation techniques observed in the wild throughout 2025-2026. The involvement of multiple external contributors (Steven Huang, Tao An, Arjan Mossel, XQ) suggests security-focused code review typical of vulnerability remediation rather than feature development. Organizations should assume that proof-of-concept exploit code exists in private repositories and treat patching as an emergency change.

Detection & Response

SIGMA Rules

The following Sigma rules detect suspicious behaviors associated with compromised or maliciously used llm CLI instances. These focus on post-exploitation activities: unexpected network connections to non-standard AI endpoints, access to sensitive credential stores, and execution of unauthorized plugins.

YAML
---
title: LLM CLI Suspicious Network Connection
id: 8f4a2c91-7b3d-4e5f-9a2c-1d8e6f4b7a9c
status: experimental
description: Detects LLM CLI process making network connections to non-standard AI provider endpoints or suspicious domains
references:
  - https://github.com/simonw/llm
author: Security Arsenal
date: 2026/11/05
tags:
  - attack.command_and_control
  - attack.t1071.001
logsource:
  category: network_connection
  product: linux
detection:
  selection:
    Image|endswith: '/llm'
    DestinationHostname|contains:
      - 'api.openai.com'
      - 'api.anthropic.com'
      - 'openai.azure.com'
      - 'generativelanguage.googleapis.com'
  filter:
    DestinationHostname|contains:
      - 'api.openai.com'
      - 'api.anthropic.com'
      - 'openai.azure.com'
      - 'generativelanguage.googleapis.com'
  condition: selection and not filter
falsepositives:
  - Custom AI proxy servers or enterprise gateways
level: medium
---
title: LLM CLI Sensitive File Access
id: 3c7b9e21-4a5f-4d8c-9e2b-7f1a6c8d5e3b
status: experimental
description: Detects unauthorized access to LLM CLI configuration and credential files
references:
  - https://github.com/simonw/llm
author: Security Arsenal
date: 2026/11/05
tags:
  - attack.credential_access
  - attack.t1552.001
logsource:
  category: file_event
  product: linux
detection:
  selection:
    TargetFilename|contains:
      - '.config/llm/keys.json'
      - '.local/share/llm/logs.db'
      - '.config/llm/templates/'
    Image|endswith:
      - '/cat'
      - '/less'
      - '/more'
      - '/nano'
      - '/vim'
      - '/python'
      - '/sh'
      - '/bash'
  condition: selection
falsepositives:
  - Legitimate user inspection of their own LLM configuration
level: high
---
title: LLM CLI Unexpected Child Process
id: 9d2e5f8a-6c4b-4a9e-8d3c-2f7e1a5b9c4d
status: experimental
description: Detects LLM CLI spawning unexpected shell or network utility child processes indicating potential compromise
references:
  - https://github.com/simonw/llm
author: Security Arsenal
date: 2026/11/05
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: linux
detection:
  selection:
    ParentImage|endswith: '/llm'
    Image|endswith:
      - '/curl'
      - '/wget'
      - '/nc'
      - '/netcat'
      - '/bash'
      - '/sh'
      - '/python'
      - '/perl'
      - '/ruby'
  condition: selection
falsepositives:
  - Plugins that legitimately require network access (rare)
level: high

KQL (Microsoft Sentinel / Defender)

For organizations ingesting Linux sysmon or auditd logs into Sentinel, this query hunts for suspicious LLM CLI activity patterns consistent with credential theft or unauthorized plugin execution.

KQL — Microsoft Sentinel / Defender
// Hunt for LLM CLI accessing sensitive files or making unexpected network connections
let LLMProcess = "llm";
let SensitivePaths = dynamic(["keys.json", "logs.db", "templates"]);
let SuspiciousChildren = dynamic(["curl", "wget", "nc", "bash", "sh", "python"]);

// Process execution analysis
Syslog
| where TimeGenerated > ago(7d)
| where ProcessName == LLMProcess or ParentProcessName == LLMProcess
| extend CommandLine = tostring(SyslogMessage)
| where CommandLine contains "llm"
| summarize 
    ExecutionCount = count(),
    UniqueUsers = dcount(UserName),
    Commands = make_set(CommandLine, 1000)
    by Computer, UserName, ProcessName, ParentProcessName
| where ExecutionCount > 100 or UniqueUsers > 3 // Anomalous usage patterns

// Join with file access events (requires FileAuditd or similar)
| join kind=leftouter (
    Syslog
    | where TimeGenerated > ago(7d)
    | where SyslogMessage has_any (SensitivePaths)
    | extend AccessedFile = extract(@"(\S*(?:keys\.json|logs\.db|templates)\S*)", 1, SyslogMessage)
    | where isnotempty(AccessedFile)
) on Computer, UserName

// Network connection analysis
| join kind=leftouter (
    CommonSecurityLog
    | where TimeGenerated > ago(7d)
    | where ApplicationProtocol == "HTTPS"
    | extend DestinationHost = tostring(DestinationHostName)
    | where DestinationHost !has_any ("api.openai.com", "api.anthropic.com", "openai.azure.com")
) on $left.Computer == $right.SourceHostName

| project TimeGenerated, Computer, UserName, ProcessName, CommandLine, AccessedFile, DestinationHost, DestinationIP
| order by TimeGenerated desc

Velociraptor VQL

This Velociraptor artifact hunts for suspicious LLM CLI execution patterns and credential file access across the endpoint fleet.

VQL — Velociraptor
-- Hunt for suspicious LLM CLI activity and credential access
SELECT 
    Pid,
    Name,
    CommandLine,
    Exe,
    Username,
    CreateTime,
    PPid,
    Parent.Name as ParentName
FROM pslist()
WHERE 
    (Name =~ 'llm' OR CommandLine =~ 'llm')
    AND (
        CommandLine =~ 'curl|wget|nc|bash|sh -c'
        OR Parent.Name =~ 'curl|wget|nc|bash|sh'
    )

UNION

-- Check for LLM credential file access by non-LLM processes
SELECT 
    Pid,
    Name,
    CommandLine,
    Exe,
    Username,
    CreateTime,
    NULL as PPid,
    NULL as ParentName
FROM pslist()
WHERE 
    CommandLine =~ 'keys\.json|logs\.db|\.config/llm'
    AND Name !~ 'llm|cat|less|more|nano|vim|emacs'

Remediation Script (Bash)

Deploy this script across Linux/macOS developer workstations and CI/CD runners to audit current installations, enforce version 0.37.1 or later, and lock down permissions on sensitive LLM configuration directories.

Bash / Shell
#!/bin/bash
# LLM CLI 0.37.1 Security Hardening Script
# Run with sudo for system-wide enforcement

set -euo pipefail

LLM_MIN_VERSION="0.37.1"
LLM_CONFIG_DIR="$HOME/.config/llm"
LLM_DATA_DIR="$HOME/.local/share/llm"

echo "[+] LLM CLI Security Audit and Remediation"
echo "[+] Target version: $LLM_MIN_VERSION or higher"

# Function to compare version numbers
version_ge() {
    [ "$1" = "$(echo -e "$1\n$2" | sort -V | head -n1)" ]
}

# Check if llm is installed
if ! command -v llm &> /dev/null; then
    echo "[-] LLM CLI not found. No action required."
    exit 0
fi

CURRENT_VERSION=$(llm --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo "[+] Found LLM version: $CURRENT_VERSION"

# Check if update is needed
if version_ge "$LLM_MIN_VERSION" "$CURRENT_VERSION"; then
    echo "[!] LLM version $CURRENT_VERSION is vulnerable. Updating to $LLM_MIN_VERSION..."
    
    # Backup configuration before update
    if [ -d "$LLM_CONFIG_DIR" ]; then
        echo "[+] Backing up configuration to ${LLM_CONFIG_DIR}.backup.$(date +%Y%m%d)"
        cp -r "$LLM_CONFIG_DIR" "${LLM_CONFIG_DIR}.backup.$(date +%Y%m%d)"
    fi
    
    # Update via pip (standard installation method)
    if command -v pip3 &> /dev/null; then
        pip3 install --upgrade "llm>=$LLM_MIN_VERSION"
        echo "[+] LLM CLI updated successfully"
    elif command -v pipx &> /dev/null; then
        pipx upgrade llm
        echo "[+] LLM CLI updated via pipx"
    else
        echo "[-] Neither pip3 nor pipx found. Manual update required."
        exit 1
    fi
else
    echo "[+] LLM version is current"
fi

# Harden permissions on LLM directories
echo "[+] Hardening permissions on LLM directories..."

if [ -d "$LLM_CONFIG_DIR" ]; then
    # Remove world-readable permissions
    chmod 700 "$LLM_CONFIG_DIR"
    find "$LLM_CONFIG_DIR" -type f -name "*.json" -exec chmod 600 {} \;
    find "$LLM_CONFIG_DIR" -type d -exec chmod 700 {} \;
    echo "[+] Secured $LLM_CONFIG_DIR (700/600 permissions)"
fi

if [ -d "$LLM_DATA_DIR" ]; then
    chmod 700 "$LLM_DATA_DIR"
    if [ -f "$LLM_DATA_DIR/logs.db" ]; then
        chmod 600 "$LLM_DATA_DIR/logs.db"
    fi
    echo "[+] Secured $LLM_DATA_DIR (700/600 permissions)"
fi

# Audit installed plugins for suspicious entries
echo "[+] Auditing installed LLM plugins..."
if [ -d "$LLM_CONFIG_DIR/plugins" ]; then
    PLUGIN_COUNT=$(find "$LLM_CONFIG_DIR/plugins" -name "*.py" 2>/dev/null | wc -l)
    echo "[+] Found $PLUGIN_COUNT plugin files"
    
    # Check for recently modified plugins (potential tampering)
    RECENT_PLUGINS=$(find "$LLM_CONFIG_DIR/plugins" -name "*.py" -mtime -7 2>/dev/null || true)
    if [ -n "$RECENT_PLUGINS" ]; then
        echo "[!] WARNING: Recently modified plugins detected (possible supply chain compromise):"
        echo "$RECENT_PLUGINS" | while read -r plugin; do
            echo "    - $plugin ($(stat -f%Sm "$plugin" 2>/dev/null || stat -c%y "$plugin" 2>/dev/null))"
        done
    fi
fi

# Verify API key file permissions
echo "[+] Verifying API key security..."
if [ -f "$LLM_CONFIG_DIR/keys.json" ]; then
    PERMS=$(stat -f%OLp "$LLM_CONFIG_DIR/keys.json" 2>/dev/null || stat -c%a "$LLM_CONFIG_DIR/keys.json" 2>/dev/null)
    if [ "$PERMS" != "600" ]; then
        echo "[!] Fixing insecure permissions on keys.json (was $PERMS, setting 600)"
        chmod 600 "$LLM_CONFIG_DIR/keys.json"
    else
        echo "[+] keys.json permissions are secure"
    fi
fi

echo "[+] Security hardening complete"
echo "[+] Recommendation: Rotate API keys if compromise is suspected"

Remediation

Immediate Actions (Within 24 Hours)

  1. Inventory and Patch: Identify all installations of llm CLI across your environment—developer laptops, MLOps servers, CI/CD runners, and Docker images. Upgrade to version 0.37.1 immediately:
    Bash / Shell

pip3 install --upgrade "llm>=0.37.1"

or if using pipx

pipx upgrade llm

Code

2. **Credential Rotation:** If you cannot immediately determine whether a system was running a vulnerable version, rotate API keys for OpenAI, Anthropic, Azure OpenAI, and any other providers configured in `llm`. Assume compromise if the tool was used to process untrusted input.

3. **Plugin Audit:** Review all installed plugins in `~/.config/llm/plugins/`. Remove any that are not explicitly required for business operations. Verify the integrity of remaining plugins against their official repositories.

### Strategic Hardening (Within 7 Days)

1. **Network Segmentation:** Implement egress filtering to restrict `llm` CLI traffic to known AI provider endpoints only (api.openai.com, api.anthropic.com, etc.). Alert on any LLM process attempting connections to non-standard domains.

2. **Filesystem Hardening:** Enforce strict permissions on LLM configuration directories as demonstrated in the remediation script. API keys should never be world-readable.

3. **CI/CD Isolation:** Ensure `llm` executions in CI/CD pipelines run in ephemeral containers with no persistent storage and no access to production credentials. Use short-lived API tokens scoped to specific models.

4. **Detection Deployment:** Deploy the Sigma rules provided above to your SIEM. Focus on detecting LLM processes spawning network utilities or shells—behavior that should virtually never occur in legitimate usage.

### Official Resources

- **LLM 0.37.1 Release Notes:** https://github.com/simonw/llm/releases/tag/0.37.1
- **LLM Documentation:** https://llm.datasette.io/
- **GitHub Repository:** https://github.com/simonw/llm

### Verification

After patching, verify the installation:
```bash
llm --version  # Should return 0.37.1 or higher
ls -la ~/.config/llm/  # Verify permissions are 700/600

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.