Back to Intelligence

LLM 0.37.2 Released: Securing Simon Willison's AI CLI Tool Against Prompt Injection and Supply Chain Risks

SA
Security Arsenal Team
November 13, 2026
9 min read

On November 11, 2026, Simon Willison released version 0.37.2 of llm, his widely-adopted open-source CLI tool for interacting with Large Language Models. While the specific changelog details remain under review, any update to this critical MLOps component warrants immediate attention from security teams. The llm tool has become a staple in developer environments and CI/CD pipelines for AI orchestration, making it a high-value target for supply chain attacks and prompt injection exploitation.

Given the tool's ability to execute system commands via plugins and process untrusted input through LLM prompts, version updates often address critical security boundaries. Organizations using llm for automated content generation, code analysis, or data processing must treat this update as a priority security patch, not merely a feature release.

Technical Analysis

Affected Products and Attack Surface

Product: llm CLI (Python package)
Version: 0.37.2 (prior versions potentially vulnerable)
Platforms: All operating systems supporting Python 3.8+ (Windows, Linux, macOS)
Installation vectors: PyPI (pip install llm), Homebrew, direct GitHub installation

The llm tool presents a unique attack surface combining traditional CLI security with AI-specific threats:

  1. Prompt Injection via Malicious Input: The tool processes untrusted text files, web content, and user input through LLM APIs. Maliciously crafted input could instruct the LLM to execute arbitrary system commands if the tool passes output to os.system() or similar functions without sanitization.

  2. Plugin Supply Chain Risks: The tool supports community plugins (llm install plugin-name). A compromised plugin could exfiltrate API keys, modify prompts to leak sensitive data, or establish persistence in MLOps pipelines.

  3. API Key Exposure: The tool stores API keys in plaintext configuration files (~/.config/llm/keys.json or environment variables). Version 0.37.2 may address insecure storage or transmission vulnerabilities.

  4. Template Injection: Custom prompt templates using Jinja2 or similar engines could allow Server-Side Template Injection (SSTI) if user input reaches template rendering without sandboxing.

Exploitation Requirements

Exploitation typically requires:

  • Local access to a system with llm installed, or
  • Ability to influence input files processed by the tool in automated pipelines, or
  • Compromise of the PyPI supply chain to distribute malicious plugin versions

Current Threat Context

While no specific CVE is associated with this release in the provided summary, the 2025-2026 threat landscape has seen increased targeting of AI development tools. Attackers recognize that MLOps pipelines often have over-privileged access to training data, model weights, and production inference endpoints. A compromised llm installation could serve as a beachhead for lateral movement into AI infrastructure.

Detection & Response

Sigma Rules

YAML
---
title: LLM CLI Tool Execution with Suspicious Arguments
id: 8f4a2c91-3b7e-4d9a-b5c2-9e1f6a8d4c3b
status: experimental
description: Detects execution of the llm CLI tool with arguments indicative of prompt injection attempts or unauthorized plugin installation
references:
  - https://attack.mitre.org/techniques/T1059/
  - https://attack.mitre.org/techniques/T1195/
author: Security Arsenal
date: 2026/11/11
tags:
  - attack.execution
  - attack.t1059
  - attack.supply_chain
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    Image|endswith:
      - '\llm.exe'
      - '\python.exe'
    CommandLine|contains:
      - 'llm '
      - 'install'
      - 'plugin'
      - '--system'
      - 'exec'
  filter_known_good:
    CommandLine|contains:
      - 'llm --version'
      - 'llm models'
      - 'llm plugins'
  condition: selection and not filter_known_good
falsepositives:
  - Legitimate plugin installation by developers
  - Standard llm CLI usage in development environments
level: medium
---
title: Python Process Spawning System Shell via LLM Tool
id: 2c8e5f1a-9d4b-4e7a-a3c6-8f2b1d5e9a7c
status: experimental
description: Identifies Python processes (potentially running llm) spawning system shells or command interpreters, which may indicate successful prompt injection leading to command execution
references:
  - https://attack.mitre.org/techniques/T1059/
  - https://attack.mitre.org/techniques/T1203/
author: Security Arsenal
date: 2026/11/11
tags:
  - attack.execution
  - attack.t1059.001
logsource:
  category: process_creation
  product: windows
detection:
  selection_parent:
    ParentImage|endswith:
      - '\python.exe'
      - '\llm.exe'
  selection_child:
    Image|endswith:
      - '\cmd.exe'
      - '\powershell.exe'
      - '\bash.exe'
      - '\sh.exe'
      - '\nc.exe'
      - '\netcat.exe'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate use of llm plugins that require shell execution
  - Development workflows involving subprocess calls
level: high

KQL (Microsoft Sentinel / Defender)

KQL — Microsoft Sentinel / Defender
// Hunt for llm CLI execution with suspicious parameters or plugin installations
let TimeRange = 24h;
union isfuzzy=true
    (SecurityEvent
    | where TimeGenerated > ago(TimeRange)
    | where EventID == 4688
    | where Process has "llm" or CommandLine has "llm"
    | where CommandLine has_any ("install", "plugin", "--system", "exec", "eval", "subprocess")
    | project TimeGenerated, Computer, Account, Process, CommandLine, ParentProcessName),
    (DeviceProcessEvents
    | where TimeGenerated > ago(TimeRange)
    | where FileName =~ "python.exe" or FileName =~ "llm.exe" or ProcessCommandLine contains "llm"
    | where ProcessCommandLine has_any ("install", "plugin", "--system", "exec")
    | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName)
| summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Count = count() by Computer, Account, CommandLine
| where Count > 5 or CommandLine has "plugin"
| order by LastSeen desc;

// Hunt for suspicious outbound connections from llm/python processes
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where InitiatingProcessFileName =~ "python.exe" or InitiatingProcessFileName =~ "llm.exe"
| where RemoteUrl has_any ("pastebin", "github", "raw.githubusercontent", "pypi") or RemoteIPType == "Public"
| where not(RemoteUrl has_any ("openai", "anthropic", "azure", "google"))  // Exclude known API endpoints
| summarize ConnectionCount = count(), UniqueIPs = dcount(RemoteIP) by DeviceName, InitiatingProcessFileName, RemoteUrl, RemoteIP
| where ConnectionCount > 10
| order by ConnectionCount desc;

Velociraptor VQL

VQL — Velociraptor
-- Hunt for llm CLI installations and recent modifications indicating potential compromise
SELECT 
    Pid,
    Name,
    CommandLine,
    Exe,
    Username,
    CreateTime,
    Exe as BinaryPath
FROM pslist()
WHERE CommandLine =~ 'llm'
   OR Exe =~ 'llm'
   OR Name =~ 'python.*llm'

-- Check for recently modified llm plugins (potential malicious updates)
SELECT 
    FullPath,
    Size,
    Mtime,
    Atime,
    Ctime
FROM glob(globs='**/.config/llm/plugins/**', accessor='file')
WHERE Mtime > now() - 86400  // Modified in last 24 hours
   OR Ctime > now() - 86400
ORDER BY Mtime DESC

-- Hunt for suspicious network connections from Python processes (potential llm API abuse)
SELECT 
    Pid,
    Name,
    Path,
    LocalAddr,
    LocalPort,
    RemoteAddr,
    RemotePort,
    State
FROM netstat()
WHERE Name =~ 'python'
   AND State == 'ESTABLISHED'
   AND RemoteAddr !~ '^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)'  // External IPs only

Remediation Script

PowerShell
# Requires PowerShell 5.1 or later
# Run as Administrator for system-wide installations

Write-Host "=== LLM CLI Security Hardening Script ===" -ForegroundColor Cyan
Write-Host "Checking llm installation and version..." -ForegroundColor Yellow

# Check if llm is installed
try {
    $llmVersion = & llm --version 2>$null
    if ($llmVersion -match "0.37.2") {
        Write-Host "[OK] llm version 0.37.2 detected" -ForegroundColor Green
    } else {
        Write-Host "[WARNING] llm version $llmVersion detected - UPDATE REQUIRED" -ForegroundColor Red
        Write-Host "Updating llm to 0.37.2..." -ForegroundColor Yellow
        pip install --upgrade llm==0.37.2
    }
} catch {
    Write-Host "[INFO] llm not found in PATH. Checking pip installations..." -ForegroundColor Yellow
    $pipList = pip list | Select-String "llm"
    if ($pipList) {
        Write-Host "[WARNING] llm installed via pip but not in PATH or outdated" -ForegroundColor Red
        pip install --upgrade llm==0.37.2
    } else {
        Write-Host "[OK] llm not installed on this system" -ForegroundColor Green
    }
}

# Audit installed plugins
Write-Host "`n=== Auditing Installed Plugins ===" -ForegroundColor Cyan
$pluginPath = "$env:USERPROFILE\.config\llm\plugins"
if (Test-Path $pluginPath) {
    $plugins = Get-ChildItem -Path $pluginPath -Recurse -Filter "*.py" | Select-Object FullName, LastWriteTime
    foreach ($plugin in $plugins) {
        $hash = Get-FileHash -Path $plugin.FullName -Algorithm SHA256
        Write-Host "Plugin: $($plugin.FullName)" -ForegroundColor White
        Write-Host "  Last Modified: $($plugin.LastWriteTime)" -ForegroundColor Gray
        Write-Host "  SHA256: $($hash.Hash)" -ForegroundColor Gray
        
        # Check for recently modified plugins (potential supply chain attack)
        if ($plugin.LastWriteTime -gt (Get-Date).AddDays(-7)) {
            Write-Host "  [ALERT] Recently modified - verify legitimacy" -ForegroundColor Red
        }
    }
} else {
    Write-Host "No plugins directory found" -ForegroundColor Green
}

# Check for suspicious API key storage
Write-Host "`n=== Checking API Key Storage ===" -ForegroundColor Cyan
$keyPaths = @(
    "$env:USERPROFILE\.config\llm\keys.json",
    "$env:APPDATA\llm\keys.json"
)

foreach ($keyPath in $keyPaths) {
    if (Test-Path $keyPath) {
        $acl = Get-Acl $keyPath
        $accessRules = $acl.Access | Where-Object { $_.IdentityReference -notlike "*$env:USERNAME*" -and $_.IdentityReference -notlike "*SYSTEM*" -and $_.IdentityReference -notlike "*Administrators*" }
        
        if ($accessRules) {
            Write-Host "[WARNING] API key file accessible by unauthorized users: $keyPath" -ForegroundColor Red
            Write-Host "Restricting permissions..." -ForegroundColor Yellow
            icacls $keyPath /inheritance:r /grant:r "$env:USERNAME`(F`)" /grant:r "SYSTEM`(F`)" 2>$null
        } else {
            Write-Host "[OK] API key file permissions appear secure: $keyPath" -ForegroundColor Green
        }
        
        # Check if keys are base64 encoded (plaintext check)
        $content = Get-Content $keyPath -Raw
        if ($content -match '"sk-[a-zA-Z0-9]{48}"' -or $content -match '"sk-ant-[a-zA-Z0-9-]{95}"') {
            Write-Host "[CRITICAL] Plaintext API keys detected in $keyPath" -ForegroundColor Red
            Write-Host "Consider using environment variables or Azure Key Vault integration" -ForegroundColor Yellow
        }
    }
}

# Monitor for suspicious network activity
Write-Host "`n=== Network Security Recommendations ===" -ForegroundColor Cyan
Write-Host "1. Restrict outbound traffic from llm processes to known API endpoints only:" -ForegroundColor White
Write-Host "   - api.openai.com" -ForegroundColor Gray
Write-Host "   - api.anthropic.com" -ForegroundColor Gray
Write-Host "   - generativelanguage.googleapis.com" -ForegroundColor Gray
Write-Host "2. Block access to pypi.org from production systems running llm" -ForegroundColor White
Write-Host "3. Implement application whitelisting to prevent unauthorized llm plugin execution" -ForegroundColor White

Write-Host "`n=== Remediation Complete ===" -ForegroundColor Green

Remediation

Immediate Actions

  1. Update Immediately: Upgrade all installations to llm version 0.37.2 using pip install --upgrade llm==0.37.2 or your package manager equivalent.

  2. Plugin Audit: Review all installed plugins in ~/.config/llm/plugins/. Remove any plugins not explicitly required for business operations. Verify plugin sources—only install from official PyPI repositories or verified GitHub sources.

  3. API Key Hygiene: Rotate all API keys stored in keys.json files. Migrate to environment variables or enterprise secret management solutions (Azure Key Vault, HashiCorp Vault, AWS Secrets Manager) rather than plaintext files.

  4. Network Segmentation: Restrict outbound network access for systems running llm to only required API endpoints (OpenAI, Anthropic, etc.). Block access to PyPI and GitHub from production AI inference systems to prevent plugin supply chain attacks.

Configuration Hardening

  • Disable Plugin Auto-Install: If not required, disable the ability to install plugins in production environments by removing write permissions to the plugins directory.
  • Input Sanitization: Implement strict input validation for any files processed through llm in automated pipelines. Treat all LLM output as untrusted code.
  • Sandbox Execution: Run llm in isolated containers or VMs with restricted system access, especially when processing untrusted input.

Verification

Verify the update and check for indicators of compromise:

  • Confirm version: llm --version should return 0.37.2
  • Check for unexpected Python processes with network connections
  • Audit file system for recently modified .py files in the llm installation directory
  • Review proxy logs for connections to suspicious domains from Python processes

Supply Chain Security

Given the November 2026 release timing, verify the integrity of the package:

  • Download only from official PyPI (pypi.org/project/llm/)
  • Verify package hashes against Simon Willison's official release notes
  • Monitor for typosquatting packages (e.g., llm-cli, llm-python) that may mimic this tool

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.