Back to skill

Security audit

SpecClaw

Security checks for vulnerabilities and agentic risk

Overview

SpecClaw is a coherent development automation skill, but it gives agents broad code, shell, git, and GitHub authority with weak containment around untrusted project files and configured commands.

Install only if you are comfortable with a skill that can modify repositories, spawn agents, run shell commands, commit and merge git branches, and optionally update GitHub issues. Use it first in a disposable or well-backed-up repository, keep GitHub sync disabled unless needed, avoid storing tokens in config.yaml, review .specclaw/config.yaml before build or verify, and do not run autonomous mode on untrusted projects.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build.sh:264
Finding

Arbitrary Command Execution Through Configured Build Commands

Content
View full analysis
&2 if ! eval "$test_command" >&2 2>&1; then tests_passed=false errors+=("Test command failed: $test_command") fi fi # Run lint command if [[ -n "$lint_command" ]]; then echo "Running lint: $lint_command" >&2 if ! eval "$lint_command" >&2 2>&1; then lint_passed=false errors+=("Lint command failed: $lint_command") fi fi # Run build command if [[ -n "$build_command" ]]; then echo "Running build: $build_command" >&2 if ! eval "$build_command" >&2 2>&1; then build_passed=false errors+=("Build command failed: $build_command") fi fi ``` ### Technical Analysis The `test_command`, `lint_command`, and `build_command` values are read from `.specclaw/config.yaml` and passed directly to Bash `eval`. Unlike execution through a fixed command and argument array, `eval` reparses the complete value as shell syntax. Shell separators, substitutions, redirections, pipelines, and additional commands are therefore executed. This is dangerous when SpecClaw is initialized in an untrusted repository, when a pull request can alter `.specclaw/config.yaml`, or when an agent-generated change modifies that configuration. The build finalization flow treats the values as project configuration but does not require user confirmation, validate them against an allowlist, or isolate their execution. The commands execute with the privileges and environment of the OpenClaw process. They may consequently access repository files, environment variables, local credentials available to that account, and network resources. ### Attack Path 1. An attacker contributes or modifies `.specclaw/config.yaml`. 2. The attacker sets a build field to shell syntax, for example: ```yaml ...[truncated 902 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/verify.sh:57
Finding

Arbitrary Command Execution During Verification

Content
View full analysis
# Sets: to captured output, returns command exit code run_capped() { local -n _out_ref="$1" local cmd="$2" local tmpfile tmpfile=$(mktemp) local rc=0 eval "$cmd" >"$tmpfile" 2>&1 || rc=$? _out_ref=$(head -100 "$tmpfile") local total total=$(wc -l < "$tmpfile") if [ "$total" -gt 100 ]; then _out_ref="${_out_ref} ... (truncated, ${total} total lines)" fi rm -f "$tmpfile" return "$rc" } ``` The affected function is later called with `test_command`, `lint_command`, and `build_command` values read from `.specclaw/config.yaml`. ### Technical Analysis `run_capped` accepts a command string and executes it through `eval`. Output capping does not restrict command behavior; it only limits the text returned after execution. Any shell syntax present in a configured command is interpreted with the full permissions and environment of the verifier. Verification is often perceived as a read-only or lower-risk operation. In this implementation, running evidence collection can instead execute arbitrary repository-controlled shell commands. No trust check, approval gate, command allowlist, or process isolation is applied. ### Attack Path 1. An attacker places shell metacharacters or substitutions in one of the build command values in `.specclaw/config.yaml`. 2. A user invokes the SpecClaw verification workflow. 3. `verify.sh collect` reads the configured command. 4. The command is supplied to `run_capped`. 5. `eval "$cmd"` reparses and executes the complete attacker-controlled string. 6. The injected operation runs before the verifier captures and truncates its output. ### Impact Assessment The impact is arbitrary ...[truncated 385 chars]
Remediation
View remediation
"$tmpfile" 2>&1 } ``` - Store commands and arguments as structured configuration rather than shell strings. - Require user confirmation for repository-supplied verification commands. - Execute verification in an isolated environment without host credentials and with restricted filesystem and network access. - Record the exact executable and argument vector in verification evidence so reviewers can determine what was run. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build-context.sh:211
Finding

Task File Paths Can Read Files Outside the Project and Insert Them Into Agent Context

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify.sh:125
Finding

Verification Task Paths Permit Arbitrary Local File Collection

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
scripts/build-context.sh:326
Finding

Untrusted Project Documents Are Embedded Directly Into Privileged Coding-Agent Instructions

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description omits GitHub issue management, authentication use, repository detection, and status-file mutation tied to external synchronization. That mismatch is security-relevant because users may invoke the skill expecting local planning assistance while it can also interact with external services and consume credentials, increasing the risk of unintended data disclosure or unauthorized repository actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill description omits GitHub issue management, authentication use, repository detection, and status-file mutation tied to external synchronization. That mismatch is security-relevant because users may invoke the skill expecting local planning assistance while it can also interact with external services and consume credentials, increasing the risk of unintended data disclosure or unauthorized repository actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill description omits GitHub issue management, authentication use, repository detection, and status-file mutation tied to external synchronization. That mismatch is security-relevant because users may invoke the skill expecting local planning assistance while it can also interact with external services and consume credentials, increasing the risk of unintended data disclosure or unauthorized repository actions.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill description omits GitHub issue management, authentication use, repository detection, and status-file mutation tied to external synchronization. That mismatch is security-relevant because users may invoke the skill expecting local planning assistance while it can also interact with external services and consume credentials, increasing the risk of unintended data disclosure or unauthorized repository actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The build flow performs extensive automated writes, task-state edits, agent spawning, commits, merges, error logging, and notifications, yet the skill description does not clearly warn users about these side effects. In a privileged agent environment, this can lead to significant unintended codebase and branch changes before the user realizes the scope of automation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

Verification and GitHub sync can transmit acceptance criteria, changed file contents, test results, and status information to external systems, but the skill does not prominently warn about that privacy boundary. This is dangerous because repository content, proprietary code, or sensitive metadata may be shared outside the local environment unexpectedly.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/workflow-examples.md (reported line 33)May include surrounding context.

spec.md (excerpt):

markdown
## Acceptance Criteria
- [ ] AC-1: GIVEN a valid username/password WHEN POST /auth/login THEN return JWT access token (15min) + refresh token (7d)
- [ ] AC-2: GIVEN an expired access token WHEN POST /auth/refresh with valid refresh token THEN return new access + refresh tokens
- [ ] AC-3: GIVEN an invalid token WHEN accessing protected route THEN return 401 with error message

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/workflow-examples.md (reported line 34)May include surrounding context.

spec.md (excerpt):

markdown
## Acceptance Criteria
- [ ] AC-1: GIVEN a valid username/password WHEN POST /auth/login THEN return JWT access token (15min) + refresh token (7d)
- [ ] AC-2: GIVEN an expired access token WHEN POST /auth/refresh with valid refresh token THEN return new access + refresh tokens
- [ ] AC-3: GIVEN an invalid token WHEN accessing protected route THEN return 401 with error message

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The finalize subcommand automatically merges feature branches into the main branch and removes worktrees/branches, again without confirmation, and it also executes configured test/lint/build commands via eval before performing the merge flow. In the context of a spec-driven agent framework, this is especially dangerous because automated agent output or config can cause irreversible repository history changes and cleanup, potentially merging unsafe code or deleting isolation state before a human reviews the result.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'shell' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script executes command strings from config.yaml using eval inside run_capped, which allows shell metacharacters, command substitution, and chained commands to run with the privileges of the user invoking verification. In this skill context, the tool is explicitly meant to process project-controlled specs and configs, so a malicious repo or change can turn "verification" into arbitrary code execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Overly broad trigger phrases can cause unintended invocation of high-impact actions such as file creation, git changes, subprocess execution, and GitHub sync based on ordinary conversation. In a skill with powerful tools enabled, accidental activation materially increases the chance of unauthorized or surprising side effects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill initiates repository-modifying operations including file creation, git changes, subprocesses, and optional GitHub synchronization without an upfront warning in the skill description. Lack of side-effect disclosure undermines informed consent and makes accidental destructive or privacy-impacting use more likely.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The build triggers are especially dangerous because they may start a fully automated workflow that spawns agents, edits files, commits code, merges branches, and sends notifications. Generic conversational matches make this exploitable through ambiguous prompts or accidental phrasing, leading to substantial repository modification without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The autonomous mode triggers are vague and map to a mode that selects and executes the next actionable item automatically. Because this mode can chain planning, building, verification, and notifications with limited user involvement, accidental invocation could result in broad unintended modifications and external disclosures.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
88% confidence
Finding

The autonomous mode makes workflow decisions and executes plan/build/verify steps based on project status rather than a narrowly scoped user command. In a skill with write, exec, subagent, and notification capabilities, that level of autonomous progression increases the risk of unintended modifications and reduces meaningful human approval checkpoints.

Content

Scanner excerpt · SKILL.md (reported line 478)May include surrounding context.

md
1. Check `STATUS.md` for next actionable item
2. If proposal exists without plan → generate plan
3. If plan exists without implementation → build
4. If built without verification → verify
5. Respect `config.yaml` limits (max_tasks_per_run)
6. Notify user of results

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This example explicitly documents unattended execution that can spawn agents, modify code, and continue work across multiple nights with only status notifications. In a framework that drives code generation and builds, normalizing autonomous execution without prominent guardrails increases the risk of unauthorized or unsafe code changes, prompt-injection propagation, and unnoticed supply-chain or logic defects.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script reads arbitrary project files listed in task metadata and embeds their full contents into a prompt printed to stdout, which can expose secrets, credentials, proprietary code, or other sensitive material to downstream agents, logs, terminals, or external LLM services. In this skill, the script is specifically designed to feed coding agents, so the exfiltration path is more plausible: task definitions can cause broader-than-expected file inclusion and users may not realize sensitive repository content is being forwarded.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The setup subcommand automatically creates and checks out branches or worktrees based on config and user-supplied change names, which mutates repository state immediately without any explicit confirmation, dry-run mode, or opt-in flag. In a skill designed to orchestrate coding agents, this is risky because an upstream agent or untrusted spec/config can trigger persistent repository changes unexpectedly, increasing the chance of workflow disruption or accidental modification of the wrong repository.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 150)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 271)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 285)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 299)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 314)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/gh-sync.sh (reported line 317)May include surrounding context.

sh
local token="$1"
  local http_code
  http_code="$(curl -s -w '%{http_code}' -o /dev/null \
    "https://api.github.com/user" \
    -H "Authorization: token $token" \
    -H "Accept: application/vnd.github.v3+json" 2>/dev/null)" || true
  [[ "$http_code" -lt 400 ]]

Static analysis

No suspicious patterns detected.