Skip to content

security: [HIGH] Command injection risk via Slack user input to spawned process #3192

@louisgv

Description

@louisgv

File: .claude/skills/setup-spa/main.ts
Lines: 390-407
Severity: HIGH

Finding

User-controlled Slack messages are written directly to the stdin of a spawned claude CLI process without sanitization:

const proc = Bun.spawn(args, {
  stdout: "pipe",
  stderr: "pipe",
  stdin: "pipe",
  cwd: process.env.REPO_ROOT ?? process.cwd(),
  env: {
    ...process.env,
    SLACK_CHANNEL_ID: channel,
    SLACK_THREAD_TS: threadTs,
    ...(userId ? { SLACK_USER_ID: userId } : {}),
  },
});

proc.stdin.write(prompt);  // <- prompt comes from buildThreadPrompt()
proc.stdin.end();

The prompt variable (line 363) comes from buildThreadPrompt() which fetches user messages from Slack. While stdin is safer than shell interpolation, if the spawned claude CLI has any stdin parsing vulnerabilities or interprets special characters/control sequences, this could be exploited.

Impact

An attacker with access to the Slack workspace could:

  • Inject control sequences or escape codes that might be interpreted by the claude CLI
  • Attempt to exploit any stdin parsing vulnerabilities in the subprocess
  • Potentially execute arbitrary commands if the subprocess has such vulnerabilities

Attack Scenario

  1. Attacker sends a crafted Slack message containing control characters or escape sequences
  2. SPA bot processes the message via buildThreadPrompt()
  3. The prompt is written to claude CLI stdin without sanitization
  4. If claude CLI mishandles the input, commands could execute

Recommendation

  1. Validate and sanitize prompt content before writing to stdin:

    • Strip or escape control characters (\x00-\x1F, \x7F)
    • Implement maximum input size limits
    • Validate UTF-8 encoding
  2. Implement input sanitization in buildThreadPrompt():

    function sanitizeForStdin(text: string): string {
      return text
        .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '') // Remove control chars
        .slice(0, MAX_PROMPT_LENGTH); // Enforce size limit
    }
  3. Consider using structured input (JSON) instead of raw text if the claude CLI supports it

  4. Audit the claude CLI for stdin parsing vulnerabilities

-- security/code-scanner

Metadata

Metadata

Assignees

No one assigned

    Labels

    safe-to-workSecurity triage: safe for automated processingsecuritySecurity vulnerabilities and concerns

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions