# How context-mode Extracts and Blocks Shell Commands from Non-Shell Code Execution

> Learn how context-mode extracts and blocks shell commands from non-shell code. Discover its two-stage security pipeline for robust command execution control.

- Repository: [Mert Köseoğlu/context-mode](https://github.com/mksglu/context-mode)
- Tags: how-to-guide
- Published: 2026-04-24

---

**context-mode implements a two-stage security pipeline in [`src/security.ts`](https://github.com/mksglu/context-mode/blob/main/src/security.ts) that first extracts shell command strings from languages like Python or JavaScript using regex patterns, then blocks execution by splitting chained commands and validating them against user-defined deny policies before any system call occurs.**

The **mksglu/context-mode** repository provides a hardened runtime for AI-generated code that prevents malicious shell escapes hidden inside seemingly safe non-shell languages. Understanding how shell commands are extracted and blocked from non-shell code execution in context-mode is essential for security auditing and policy configuration. This analysis examines the TypeScript implementation that scans source text for dangerous APIs and enforces deny lists defined in `.claude/settings*.json` files.

## The Two-Stage Security Architecture

Context-mode protects against supply-chain and prompt-injection attacks through a strict separation between **extraction** and **blocking**. First, the system scans user code for known **shell-escape APIs** such as Python's `os.system` or Node.js's `execSync`. Second, it evaluates extracted command strings against Bash deny policies, ensuring dangerous commands never reach the operating system.

## Stage 1: Extracting Hidden Shell Commands

### Pattern Matching Against Shell-Escape APIs

In [`src/security.ts`](https://github.com/mksglu/context-mode/blob/main/src/security.ts), the **`extractShellCommands`** function (lines 525‑555) implements the detection logic. It maps each supported language to specific regular expression patterns stored in `SHELL_ESCAPE_PATTERNS`. When processing Python code, it identifies calls to `os.system()`, `subprocess.run()`, and similar dangerous APIs. For JavaScript and TypeScript, it targets `child_process` methods like `execSync` and `exec`.

### Handling Python Subprocess Lists

Python's `subprocess.run()` often receives commands as list arguments rather than strings, which requires special handling. The **`extractPythonSubprocessListArgs`** helper (lines 501‑514) parses these array-style invocations to reconstruct the full command string. This ensures that `subprocess.run(["git", "clone", "https://example.com/repo.git"])` is extracted as a complete command for policy evaluation.

```typescript
import { extractShellCommands } from "./src/security";

const py = `
import subprocess, os
os.system("rm -rf /tmp")
subprocess.run(["git", "clone", "https://example.com/repo.git"])
`;

const cmds = extractShellCommands(py, "python");
console.log(cmds);
// → [ 'rm -rf /tmp', 'git clone https://example.com/repo.git' ]

```

## Stage 2: Blocking Commands with Policy Evaluation

### Safely Splitting Chained Commands

Attackers frequently chain commands using `&&`, `||`, `;`, or `|` operators to hide malicious operations behind innocuous ones. The **`splitChainedCommands`** function (lines 165‑209) handles this complexity by parsing command strings while respecting quoted strings and backticks. This guarantees that `echo "ok" && sudo rm -rf /` splits into separate segments that can be evaluated independently.

```typescript
import { splitChainedCommands } from "./src/security";

const chain = `echo "ok" && sudo rm -rf /; ls | grep foo`;
console.log(splitChainedCommands(chain));
// → [ 'echo "ok"', 'sudo rm -rf /', 'ls', 'grep foo' ]

```

### Deny-Only Policy Enforcement

Once split, each command segment passes through **`evaluateCommandDenyOnly`** (lines 108‑121). This function iterates over the segments and checks them against user-defined deny globs using **`matchesAnyPattern`**. If any segment matches a pattern like `"sudo *"` or `"rm -rf /"`, the function returns a `"deny"` decision immediately, preventing the entire command block from executing.

```typescript
import { evaluateCommandDenyOnly, readBashPolicies } from "./src/security";

const policies = readBashPolicies("/my/project");   // reads .claude/settings*.json
const decision = evaluateCommandDenyOnly("sudo rm -rf /", policies);

if (decision.decision === "deny") {
  console.error(`Blocked: ${decision.matchedPattern}`);
}

```

## Runtime Integration

The security pipeline combines both stages in the execution layer. Before invoking any shell tool, the runtime calls `extractShellCommands` to identify hidden invocations within non-shell code. It then passes each extracted command through `evaluateCommandDenyOnly` using the policies loaded from the project's configuration files. If extraction finds no hidden commands and policy evaluation returns `"allow"`, only then does the command proceed to the actual execution environment.

## Summary

- **context-mode** implements a two-stage defense: extraction of shell commands from non-shell source code, followed by policy-based blocking.
- The **`extractShellCommands`** function in [`src/security.ts`](https://github.com/mksglu/context-mode/blob/main/src/security.ts) (lines 525‑555) uses language-specific regex patterns to identify dangerous API calls in Python, JavaScript, PHP, and other languages.
- **`splitChainedCommands`** (lines 165‑209) safely parses command chains to prevent bypasses through `&&`, `||`, and pipes.
- **`evaluateCommandDenyOnly`** (lines 108‑121) validates commands against deny globs from `.claude/settings*.json` files.
- The architecture ensures that even embedded shell calls like `os.system("sudo rm -rf /")` inside Python files are detected and blocked before system invocation.

## Frequently Asked Questions

### What languages does context-mode scan for hidden shell commands?

The `extractShellCommands` function supports multiple languages including Python, JavaScript, TypeScript, and PHP. Each language has specific regex patterns in `SHELL_ESCAPE_PATTERNS` that target common execution APIs like `os.system`, `subprocess.run`, `execSync`, and `shell_exec`.

### How does context-mode prevent command chaining attacks?

The `splitChainedCommands` function (lines 165‑209) in [`src/security.ts`](https://github.com/mksglu/context-mode/blob/main/src/security.ts) safely splits command strings on operators like `&&`, `||`, `;`, and `|` while preserving quoted content. This allows `evaluateCommandDenyOnly` to inspect each segment individually, blocking dangerous commands that attackers might hide after innocuous ones.

### Where are the deny policies configured?

User-defined Bash policies are stored in `.claude/settings*.json` files within the project directory. The `readBashPolicies` function loads these configurations, which specify deny globs (e.g., `"Bash(sudo *)"`). The `evaluateCommandDenyOnly` function then uses these patterns to make allow/deny decisions.

### Can context-mode detect shell commands in Python subprocess lists?

Yes. The `extractPythonSubprocessListArgs` function (lines 501‑514) specifically handles Python's `subprocess.run([...])` syntax by extracting and joining list arguments into complete command strings, ensuring they undergo the same security evaluation as string-based shell calls.