Skip to content

fix: sanitize subprocess call in code.py#435

Open
orbisai0security wants to merge 2 commits into
shareAI-lab:mainfrom
orbisai0security:fix-v-001-shell-injection-s02
Open

fix: sanitize subprocess call in code.py#435
orbisai0security wants to merge 2 commits into
shareAI-lab:mainfrom
orbisai0security:fix-v-001-shell-injection-s02

Conversation

@orbisai0security

Copy link
Copy Markdown

Summary

Fix critical severity security issue in s02_tool_use/code.py.

Vulnerability

Field Value
ID V-001
Severity CRITICAL
Scanner multi_agent_ai
Rule V-001
File s02_tool_use/code.py:48
Assessment Confirmed exploitable

Description: The run_bash function across multiple session files passes user-controlled command strings directly to subprocess.run() with shell=True. The command string originates from the LLM's tool_use response, which is influenced by user prompts. Deny list protection in s02 is trivially bypassable using shell metacharacters, encoding tricks, or command variants. Other implementations have no deny list protection.

Evidence

Exploitation scenario: Attacker influences LLM output via prompt injection in files being read or as direct CLI user.

Scanner confirmation: multi_agent_ai rule V-001 flagged this pattern.

Production code: This file is in the production codebase, not test-only code.

Threat Model Context

This is a Python library - vulnerabilities affect applications that import this code.

Changes

  • s02_tool_use/code.py

Verification

  • Build passes
  • Scanner re-scan confirms fix
  • LLM code review passed

Security Invariant

Property: The security boundary is maintained under adversarial input

Regression test
import pytest
import subprocess
import sys
import os

# Add the parent directory to sys.path to import the actual module
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from s02_tool_use.code import run_bash


@pytest.mark.parametrize("payload", [
    # Exact exploit case: bypass deny list with shell metacharacters
    "rm -rf /tmp/test; echo 'exploited'",
    # Boundary case: command substitution to hide dangerous command
    "$(echo 'sudo') id",
    # Valid input: should pass through
    "echo 'safe command'",
    # Encoding trick: using backticks instead of $()
    "`echo 'rm -rf /'`",
    # Command variant: using dangerous command with spaces
    "rm   -rf   /tmp/test",
])
def test_run_bash_blocks_dangerous_commands_under_adversarial_input(payload):
    """Invariant: The run_bash function must never execute dangerous shell commands,
       regardless of shell metacharacters, encoding tricks, or command variants."""
    
    result = run_bash(payload)
    
    # The security property: if the command contains dangerous patterns,
    # the function must return the error message or otherwise prevent execution
    dangerous_patterns = ["rm -rf /", "sudo", "shutdown", "reboot", "> /dev/"]
    
    # Check if any dangerous pattern appears in the payload (basic detection)
    has_dangerous = any(pattern in payload.replace(" ", "") for pattern in dangerous_patterns)
    
    if has_dangerous:
        # For dangerous commands, we expect either an error message or safe output
        # We don't require exact match, but we must ensure no dangerous execution occurred
        assert "exploited" not in result, f"Dangerous command executed: {payload}"
        assert "uid=" not in result, f"Privilege escalation occurred: {payload}"
    else:
        # For safe commands, we expect normal execution
        assert "Error: Dangerous command blocked" not in result, f"Safe command blocked: {payload}"

This test guards against regressions — it's useful independent of the code change above.


Automated security fix by OrbisAI Security

Automated security fix generated by OrbisAI Security
The `run_bash` function across multiple session files passes user-controlled command strings directly to `subprocess
@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

@orbisai0security is attempting to deploy a commit to the crazyboym's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant