Back to skill

Security audit

Error Recovery

Security checks for vulnerabilities and agentic risk

Overview

The skill is purpose-aligned for agent recovery, but it includes under-scoped automation that can press Enter in unrelated tmux panes and mutate local recovery state.

Review before installing. Use this skill only if you are comfortable with hooks or cron jobs reading tmux pane contents, writing recovery state under session directories, and deleting stale lock files. Do not run the included rate-limit script unattended unless it is narrowed to known agent panes and performs a final prompt-safety check before sending input.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/rate-limit-recovery.sh:24
Finding

Unsafe Automatic Keystroke Injection Across All tmux Panes

Content
View full analysis
/dev/null | while read -r PANE_ID; do # Capture last 20 lines CONTENT=$(tmux capture-pane -p -t "$PANE_ID" -S -20 2>/dev/null || echo "") [ -z "$CONTENT" ] && continue # Check for rate limit patterns if echo "$CONTENT" | grep -qiE '(rate.?limit|429|Too Many Requests|try again in|Retry-After|overloaded_error)'; then # Check cooldown COOLDOWN_FILE="${COOLDOWN_DIR}/${PANE_ID//\//_}" if [ -f "$COOLDOWN_FILE" ]; then LAST=$(cat "$COOLDOWN_FILE" 2>/dev/null || echo "0") NOW=$(date +%s) ELAPSED=$((NOW - LAST)) if [ "$ELAPSED" -lt "$COOLDOWN_SECONDS" ]; then continue fi fi # Send Enter to resume tmux send-keys -t "$PANE_ID" Enter 2>/dev/null || true date +%s > "$COOLDOWN_FILE" echo "Recovered pane $PANE_ID (rate limit detected)" >&2 fi done ``` ### Technical Analysis The script enumerates every pane in the current user's tmux server and sends an Enter keystroke whenever any of the previous 20 lines contains a broad rate-limit pattern. The matched text does not have to be the pane's current prompt. It may be stale terminal history, command output, source code, documentation, or attacker-controlled text. The script does not: - Restrict scanning to panes explicitly registered as managed agent sessions. - Verify the foreground process in the pane. - Recapture the pane immediately before sending input. - Confirm that the final lines still contain an active rate-limit prompt. - Reject destructive confirmation prompts. - Require evidence that the rate limit has expired. This contradicts the mandatory safety procedure documented in `SKILL.md:41` and `references/rate-limit.md:25-39`, which requires a second capture and rejection of confi ...[truncated 1720 chars]
Remediation
View remediation
/dev/null || true) ``` 4. Require the current final lines—not older scrollback—to contain a narrowly defined rate-limit prompt. 5. Reject confirmation and destructive-operation indicators, including: ```text [y/N], [Y/n], [yes/no], confirm, delete, overwrite, force push ``` 6. Prefer notification and manual recovery over automatic input when confidence is incomplete. 7. Confirm that the retry time has elapsed where a `Retry-After` value is available. 8. Add tests using a mocked `tmux` executable for: - Stale rate-limit text followed by a normal prompt. - Destructive confirmation prompts. - Unmanaged panes. - Changed pane content between initial detection and action. - Valid, current rate-limit prompts. 9. Fail closed: if process verification, recapture, or parsing fails, do not send any keystroke. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
references/graceful-degradation.md:27
Finding

Unvalidated Hook Identifiers Used in Persistent State Paths

Content
View full analysis
/dev/null || echo 0) COUNT=$((COUNT + 1)) echo "$COUNT" > "$FAIL_FILE" if [ "$COUNT" -ge 2 ]; then # 查找 fallback FALLBACK=$(grep -i "$(echo $TOOL | sed 's/mcp__//;s/__/.*/')" \ .working-state/fallback-tools.md 2>/dev/null | head -1) if [ -n "$FALLBACK" ]; then echo "{\"hookSpecificOutput\":{\"additionalContext\":\"[DEGRADATION] ${TOOL} 已连续失败 ${COUNT} 次。建议切换到替代工具:\n${FALLBACK}\n不要继续重试失败的工具。\"}}" else echo "{\"hookSpecificOutput\":{\"additionalContext\":\"[DEGRADATION] ${TOOL} 已连续失败 ${COUNT} 次,无已知替代。请换一种方法完成当前任务。\"}}" fi fi else # 成功时重置计数 rm -f "$FAIL_FILE" 2>/dev/null fi ``` ### Technical Analysis The documented PostToolUse hook derives `SESSION_ID` and `TOOL` from hook-provided JSON and directly interpolates both values into `FAIL_FILE`. Neither identifier is validated, normalized, or checked against an allowlist. Shell quoting prevents ordinary shell command injection, but it does not prevent path traversal. Values containing `/`, `..`, or absolute-path-like components can change the resolved location of the state file. The hook subsequently performs reads, writes, and deletion against that constructed path: - `cat "$FAIL_FILE"` - `echo "$COUNT" > "$FAIL_FILE"` - `rm -f "$FAIL_FILE"` The exact reachable path depends on existing directories and filesystem permissions. Nevertheless, implementing this exa ...[truncated 1569 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (25)

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · tests/test_rate_limit.py (reported line 14)May include surrounding context.

python
@pytest.fixture
def env(tmp_path):
    e = os.environ.copy()
    e["HOME"] = str(tmp_path)
    sessions = tmp_path / ".openclaw" / "shared-context" / "sessions"
    sessions.mkdir(parents=True)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill describes shell commands, file deletion, tmux interaction, and network-capable tooling, but it does not declare any explicit tool scope or allowed-tools boundary. That makes the skill easier to invoke with broader-than-necessary capabilities, increasing the chance of unintended command execution or destructive state changes during recovery workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill instructs automatic deletion of .lock files based only on age, without an explicit user warning or stronger validation that the lock is truly stale. Lock files often protect concurrency and state integrity; deleting them prematurely can corrupt workflows, break mutual exclusion, or allow overlapping sessions to operate on shared state.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill describes automatically scavenging transcript content and writing recovered session data to sessions/$SESSION/handoffs/scavenged.md without an explicit warning or approval step. Recovered transcripts may contain sensitive data, partial secrets, or misleading unfinished reasoning, so automatic persistence increases confidentiality and integrity risk.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding

Referencing npx @anthropic-ai/claude-code without a pinned version allows the fetched package version to drift over time, creating supply-chain and reproducibility risk. In a recovery skill, this is more dangerous because the command may be run during failure handling when operators are more likely to trust automation and less likely to verify what is being installed or executed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guidance recommends automatic cleanup and rollback of residual state after a crash, including reverting partially written files and clearing stale state, but it does not require an explicit user confirmation or prominent warning about possible data loss. In a recovery hook that runs automatically at session start, this can cause unintended deletion or rollback of legitimate work if the heuristics misclassify state as stale or corrupted.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The implementation automatically deletes lock files older than 15 minutes with find .claims -name "*.lock" -mmin +15 -delete, which is a destructive action based solely on age. If a lock is still valid, long-running, or the clock/environment is inconsistent, this can break coordination guarantees and allow concurrent sessions or processes to operate on the same resources, leading to corruption or race conditions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document recommends truncate conversation head as an irreversible fallback that discards early context, but it does not explicitly require warning the user, obtaining confirmation, or defining strict safety boundaries for when destructive context loss is acceptable. In an error-recovery skill, this is more dangerous because the mechanism may be triggered automatically during degraded states, causing silent loss of task constraints, prior decisions, or safety-relevant instructions and increasing the chance of incorrect or unsafe downstream behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill promotes automatic fallback from higher-level tools to shell/CLI alternatives such as gh api and psql without clearly warning that substitutes may execute local commands, rely on different credentials, or access broader local/system resources. In an error-recovery context, this is more dangerous because the agent is already in a failure loop and may eagerly switch to a more privileged or less constrained path, causing unintended command execution or data exposure.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding

npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill content is written entirely in Chinese, including the operational guidance and user-facing messages, with no indication that language selection is optional or that the skill is intended only for a Chinese-speaking context. This can violate a language/locale policy when users have not opted into Chinese or when the skill is expected to be generally usable.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This markdown skill file presents all operational instructions, warnings, and examples exclusively in Chinese. The policy requires flagging language or locale constraints when a skill forces a specific language without user opt-in, and the file does not offer alternatives or explain that it is intended only for a Chinese-speaking audience.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document explicitly instructs a daemon to analyze dead-session transcripts, including thinking blocks, and extract unsaved findings into archival memory without any privacy guardrails, consent requirement, minimization rule, or prohibition on storing sensitive reasoning and user data. In this error-recovery context, the pattern is more dangerous because stale-session recovery is likely to operate automatically across many sessions, turning accidental retention of sensitive prompts, secrets, and internal reasoning into a systematic data-exfiltration and over-retention mechanism.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_rate_limit.py (reported line 25)May include surrounding context.

python
def test_script_is_runnable(self, env):
        """Script should be a valid bash file."""
        e, _ = env
        result = subprocess.run(
            ["bash", "-n", str(SCRIPTS_DIR / "rate-limit-recovery.sh")],
            capture_output=True, text=True, env=e, timeout=10,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_rate_limit.py (reported line 38)May include surrounding context.

python
e["PATH"] = "/usr/bin:/bin"
        # If tmux is in /usr/bin or /bin, we can't easily remove it.
        # Instead, check that the script runs and exits 0.
        result = subprocess.run(
            ["bash", str(SCRIPTS_DIR / "rate-limit-recovery.sh")],
            capture_output=True, text=True, env=e, timeout=10,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_rate_limit.py (reported line 57)May include surrounding context.

python
e["PATH"] = "/usr/bin:/bin"
        # If tmux is in /usr/bin or /bin, we can't easily remove it.
        # Instead, check that the script runs and exits 0.
        result = subprocess.run(
            ["bash", str(SCRIPTS_DIR / "rate-limit-recovery.sh")],
            capture_output=True, text=True, env=e, timeout=10,
        )

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · tests/test_rate_limit.py (reported line 47)May include surrounding context.

python
def test_creates_cooldown_dir(self, env):
        """Script should create the cooldown directory."""
        e, tmp = env
        subprocess.run(
            ["bash", str(SCRIPTS_DIR / "rate-limit-recovery.sh")],
            capture_output=True, text=True, env=e, timeout=10,
        )

Overly Broad Trigger

Low
Category
Trigger Abuse
Confidence
70% confidence
Finding

Overly Broad Trigger: '限速' is too short and may match unintended inputs

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The natural-language instructions and examples are presented in Chinese throughout the file. Under the policy, forcing a specific language without user opt-in can be a locale-policy issue unless the restriction is explicitly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file's instructional content is written primarily in Chinese while the heading and technical labels are in English, which effectively imposes a language choice on readers. The policy requires avoiding forced language/locale without opt-in or documented justification, and no such choice or justification appears in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file presents the operational guidance entirely in Chinese, which can impose a fixed language on users without opt-in. Under the policy, forcing a specific language without offering choice or justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill documentation is entirely in Chinese, including operational guidance and warnings, with no indication that the user can choose another language or that the skill is intentionally region-specific. Per SQP-3, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

This markdown file documents a hook that writes failure state to sessions/${SESSION_ID}/failure-tracker.json and updates it on each failure, but the surrounding description does not warn users that session metadata will be persisted to disk. Because SQP-2 applies to markdown files when behavior affecting user data or system integrity is undocumented, this omission is a mild disclosure gap.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The file presents operational guidance primarily in Chinese, with embedded English terms, but does not state that the skill is intended only for Chinese-speaking users or offer an alternate language option. Under the language/locale policy, forcing a specific language without user opt-in can be a policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code performs active state-changing behavior by injecting an Enter keystroke into arbitrary tmux panes and persisting cooldown timestamps to disk. While comments describe the behavior for readers of the script, there is no runtime disclosure or confirmation to users who may execute it via cron, so the potentially surprising automation is easy to miss.

Content

No source excerpt is available for this finding.