Skip to content

fix: validate model ID before GCP shell interpolation#2472

Merged
louisgv merged 2 commits intomainfrom
fix/issue-2460
Mar 11, 2026
Merged

fix: validate model ID before GCP shell interpolation#2472
louisgv merged 2 commits intomainfrom
fix/issue-2460

Conversation

@la14-1
Copy link
Member

@la14-1 la14-1 commented Mar 11, 2026

Why: Prevents command injection via malicious MODEL_ID containing shell metacharacters in agent provisioning flow.

Fixes #2460

What Changed

  • Added validateModelId() in shared/ui.ts — rejects model IDs containing shell metacharacters (only allows [a-zA-Z0-9_.:-] in provider/model format)
  • Applied validation in orchestrate.ts line 116-119 — invalid model IDs are dropped to undefined with a warning, before they reach any agent configure() function or runServer() call
  • Added unit tests for validateModelId() (valid IDs, injection attempts, edge cases)
  • Added orchestration test confirming injected MODEL_ID is sanitized to undefined
  • Version bump: 0.16.0 → 0.16.1

Analysis

The model ID flows from process.env.MODEL_ID or agent.modelDefault through orchestrate.ts into agent configure functions. For the openclaw agent, it ends up in a JSON config file via JSON.stringify() + uploadConfigFile() (SCP), so the current code path is technically safe from shell injection. However, the runServer() function accepts arbitrary command strings, and future agents could interpolate model IDs directly into shell commands. This fix provides defense-in-depth by validating at the entry point.

-- refactor/security-auditor

Add validateModelId() to reject model IDs containing shell metacharacters.
The validation is applied in orchestrate.ts immediately after resolving
MODEL_ID from env/agent defaults, before the value reaches any agent
configure function or runServer call. Invalid model IDs are dropped to
undefined with a warning.

Agent: security-auditor
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Member

@louisgv louisgv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Review

Verdict: APPROVED
Commit: f33b3b1

Findings

No security issues found. The PR correctly addresses command injection vulnerability.

Implementation Review:

  1. Regex validation (/^[a-zA-Z0-9][a-zA-Z0-9_.:-]*\/[a-zA-Z0-9][a-zA-Z0-9_.:-]*$/):

    • Blocks shell metacharacters: $, `, (, ), ;, &, |, \n, space, quotes
    • Requires provider/model format with alphanumeric start
    • Allows safe chars: letters, numbers, underscore, dot, colon, hyphen
  2. Usage context (openclaw config):

    • modelId passed to jsonEscape() → uses JSON.stringify() (safe)
    • Written to config file via uploadConfigFile() (no shell interpolation)
    • Even if validation was bypassed, JSON.stringify() prevents injection
  3. Defense in depth: Validation + JSON escaping = layered security

  4. Test coverage:

    • 10 test cases including injection attempts
    • Tests validate rejection of: "; curl attacker.com; ", $(whoami), `id`/model, provider/model; rm -rf /

Tests

  • bash -n: N/A (no .sh files modified)
  • bun test: PASS (1504 pass, 0 fail)
  • curl|bash: N/A (no shell scripts)
  • macOS compat: N/A (TypeScript only)

Additional Notes

  • Version bump (0.16.0 → 0.16.1): ✓ Correct (patch for security fix)
  • No breaking changes
  • Backward compatible (invalid MODEL_ID → undefined with warning)

-- security/pr-reviewer

@louisgv louisgv added the security-approved Security review approved label Mar 11, 2026
@louisgv louisgv merged commit b393814 into main Mar 11, 2026
5 checks passed
@louisgv louisgv deleted the fix/issue-2460 branch March 11, 2026 00:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

security-approved Security review approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.

security: [HIGH] Command injection via unsanitized model ID in GCP provider

2 participants