Back to skill

Security audit

Pincer

Security checks for vulnerabilities and agentic risk

Overview

Pincer appears to be a legitimate security wrapper, but its own implementation can auto-install or fetch untrusted skill code in ways that weaken the safety checks it promises.

Review carefully before installing. The project goal is reasonable, but this version should not be treated as a dependable security gate until mcp-scan is pinned, scanner errors fail closed, fetched filenames are confined to the temporary scan directory, the install fallback is removed or made non-executing, and auto-approval is corrected to require explicit trusted-publisher checks or disabled by default.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (5)

T08 · Insecure Dependencies

Error
Location
scripts/pincer.sh:347
Finding

Unpinned Remote Dependency Is Downloaded and Executed During Every Scan

Content
View full analysis
/dev/null; then echo '{"error": "uvx not installed"}' return 1 fi # Run mcp-scan and capture output local output output=$(uvx mcp-scan@latest --skills "$target" 2>&1) || true echo "$output" } ``` ### Technical Analysis The command `uvx mcp-scan@latest` retrieves and executes the latest available release of a third-party package. The effective code executed by the Skill can therefore change after this version of the Skill has been reviewed. Using `uvx` for the documented scanner integration is consistent with the declared functionality. However, selecting the mutable `latest` release unnecessarily expands the trust boundary. The security scanner runs with the invoking user's privileges and may receive paths to locally stored skills. A compromised upstream package, package registry account, release pipeline, or transitive dependency could consequently execute arbitrary code. This is a supply-chain weakness rather than evidence that the current `mcp-scan` package is malicious. ### Attack Path 1. An attacker compromises the `mcp-scan` package, its release pipeline, its registry account, or a dependency selected by the latest release. 2. The attacker publishes a malicious version that becomes the release resolved by `mcp-scan@latest`. 3. A user invokes `pincer scan` or `pincer install`. 4. `uvx` retrieves and executes the attacker-controlled package. 5. The payload runs with the user's privileges before Pincer makes its installation decision. ### Impact Assessment Successful exploitation provides arbitrary code execution under the account running Pincer. The malicious package could read or modify any files available to that account, access user credentials and environment va ...[truncated 274 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pincer.sh:347
Finding

Scanner Failures and Unrecognized Output Are Classified as Clean

Content
View full analysis
/dev/null; then echo '{"error": "uvx not installed"}' return 1 fi # Run mcp-scan and capture output local output output=$(uvx mcp-scan@latest --skills "$target" 2>&1) || true echo "$output" } parse_mcp_scan_result() { local output="$1" # Check for critical warnings if echo "$output" | grep -qiE 'malware|malicious|reverse.?shell|exfiltrat'; then echo "malware" elif echo "$output" | grep -qE '\[W00[789]\]|\[W01[012]\]'; then # W007: credential handling, W008: machine state, W009+: various high-risk echo "high_risk" elif echo "$output" | grep -qE '\[W0[0-9]{2}\]'; then echo "warnings" else echo "clean" fi } ``` The parsed result is then treated as a successful scan: ```bash mcp_output=$(run_mcp_scan "$skill_path" 2>&1) mcp_result=$(parse_mcp_scan_result "$mcp_output") mcp_warnings=$(extract_mcp_warnings "$mcp_output") scan_results+=("mcp_scan:$mcp_result") case "$mcp_result" in malware) risk_level="malware" issues+=("mcp-scan: potential malware detected") [[ "$JSON_OUTPUT" != "true" ]] && danger "mcp-scan: ${RED}MALWARE DETECTED${NC}" ;; high_risk) [[ "$risk_level" =~ ^(clean|caution)$ ]] && risk_level="danger" issues+=("mcp-scan: high-risk patterns detected") [[ "$JSON_OUTPUT" != "true" ]] && danger "mcp-scan: high-risk warnings" ;; warnings) [[ "$risk_level" == "clean" ]] && risk_level="caution" warnings+=("mcp-scan: some warnings (review recommended)") [[ "$JSON_OUTPUT" != "true" ]] && warn "mcp-scan: warnings (likely benign)" ;; clean) [[ "$JSON_OUTPUT" != "true" ]] && ok "mcp-scan: passed" ;; esac ``` ### Technical Analysis The `|| true` construct discards the exit s ...[truncated 1634 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pincer.sh:274
Finding

Untrusted ClawHub Filenames Can Escape the Temporary Scan Directory

Content
View full analysis
&1) # Parse files from output (format: "filename size hash type") local files files=$(echo "$files_output" | grep -E '^\S+\s+[0-9]+[BKM]' | awk '{print $1}' || true) if [[ -z "$files" ]]; then debug "No files found for $skill_slug" return 1 fi # Download each file for file in $files; do local file_dir file_dir=$(dirname "$dest_dir/$file") mkdir -p "$file_dir" # Fetch file and strip any prefix lines (like "- Fetching skill") clawhub inspect "$skill_slug" --file "$file" ${version:+--version "$version"} 2>/dev/null | sed '/^- /d' > "$dest_dir/$file" || { debug "Failed to fetch $file" } done return 0 } ``` ### Technical Analysis Filenames returned by `clawhub inspect --files` are treated as trusted relative paths. The code neither rejects `..` path components nor canonicalizes the final destination before creating directories and writing data. A filename such as `../../target-file` causes `"$dest_dir/$file"` to resolve outside the intended skill directory. The remote content is written before the downloaded skill is scanned, so the scan does not prevent this filesystem modification. The shell quoting prevents ordinary whitespace splitting at the write operation, but it does not prevent filesystem path traversal. ### Attack Path 1. An attacker publishes or causes ClawHub to return a skill manifest containing a filename with traversal components, such as `../../.config/example`. 2. A user runs `pincer scan attacker-skill` or `pincer in ...[truncated 964 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pincer.sh:635
Finding

Predictable Shared Temporary File Allows Scan-Result Tampering and Symlink Attacks

Content
View full analysis
/tmp/pincer-risk-level ``` The installation command later retrieves the decision from the same shared path: ```bash local risk_level risk_level=$(cat /tmp/pincer-risk-level 2>/dev/null || echo "unknown") rm -f /tmp/pincer-risk-level ``` ### Technical Analysis The scan result is transferred through a fixed pathname in the globally shared `/tmp` directory. The file is not created atomically, its ownership and type are not verified, and symlinks are not rejected. Another local process can pre-create the path as a symbolic link, replace the result between the write and read operations, or race concurrent Pincer executions. Although the script already creates a private directory with `mktemp -d`, it does not use that directory for the risk-state file. ### Attack Path A result-tampering attack can proceed as follows: 1. A local attacker monitors for Pincer execution. 2. The attacker races or repeatedly replaces `/tmp/pincer-risk-level`. 3. After scanning, the attacker writes `clean` into the shared file before `cmd_install` reads it. 4. Pincer uses the attacker-controlled result for its installation decision. 5. A skill that should have been blocked may proceed through the clean installation path. A symlink attack can proceed as follows: 1. The attacker creates `/tmp/pincer-risk-level` as a symbolic link to another file writable by the victim. 2. Pincer executes `echo "$risk_level" > /tmp/pincer-risk-level`. 3. The shell follows the link and overwrites the target file with the risk-level string. ### Impact Assessment A local attacker may alter the security decision used by an installation operation or cause a limited overwrite of a victim-owned file. The overwrite content is constrained to a Pincer risk-l ...[truncated 227 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pincer.sh:107
Finding

URL Allowlist Uses Unanchored Substring Matching

Content
View full analysis
/dev/null || echo "") # Extract URLs (improved regex) local urls urls=$(echo "$content" | grep -oE 'https?://[a-zA-Z0-9./?=_&%-]+' | sort -u || true) for url in $urls; do local is_safe=false for pattern in "${SAFE_URL_PATTERNS[@]}"; do if echo "$url" | grep -qE "$pattern"; then is_safe=true break fi done if [[ "$is_safe" == "false" ]]; then # Skip very short URLs (likely truncated) [[ ${#url} -gt 15 ]] && unsafe_urls+=("$url") fi done echo "${unsafe_urls[*]:-}" } ``` ### Technical Analysis The allowlist patterns are searched against the complete URL using unanchored regular expressions. They do not validate the parsed hostname or enforce DNS-label boundaries. For example, URLs using hosts such as `github.com.attacker.example` or `evilgithub.com` contain the substring `github.com` and are therefore marked safe even though they are not controlled by GitHub. Similar bypasses apply to the other entries. The URL extraction expression is also not a standards-compliant URL parser, which makes security decisions based on its output fragile. ### Attack Path 1. An attacker embeds an external URL in `SKILL.md`. 2. The URL uses an attacker-controlled hostname containing an allowlisted domain as a substring, such as `https://github.c ...[truncated 707 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (24)

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 · README.md (reported line 29)May include surrounding context.

md
- **Pre-install scanning** — Analyze skills before they touch your system
- **mcp-scan integration** — Leverages [Invariant Labs' mcp-scan](https://github.com/invariantlabs-ai/mcp-scan) for prompt injection and malware detection
- **Pattern detection** — Base64 payloads, `curl | sh`, quarantine removal, and more
- **Publisher trust** — Maintain lists of trusted and blocked publishers
- **Audit mode** — Quick-scan all installed skills
- **JSON output** — Scriptable for CI/CD integration

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
chmod +x ./scripts/pincer.sh

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 · SKILL.md (reported line 148)May include surrounding context.

md
| Base64 commands | 🚨 High | Encoded shell commands |
| Hex payloads | 🚨 High | Obfuscated binary data |
| `xattr -d quarantine` | 🚨 High | macOS Gatekeeper bypass |
| `curl \| sh` | 🚨 High | Pipe to shell execution |
| Password archives | 🚨 High | Hidden malicious payloads |
| Download + execute | ⚠️ Medium | `chmod +x && ./` patterns |
| `eval $var` | ⚠️ Medium | Dynamic code execution |

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

The tool reads and deletes /tmp/pincer-risk-level to control the install decision. Because this file lives in a predictable shared temporary location, a local attacker can tamper with it or exploit a race/symlink condition to alter the perceived risk and cause installation of a skill that should have been blocked.

Content

Scanner excerpt · scripts/pincer.sh (reported line 692)May include surrounding context.

sh
local risk_level
  risk_level=$(cat /tmp/pincer-risk-level 2>/dev/null || echo "unknown")
  rm -f /tmp/pincer-risk-level
  
  # Decision
  if [[ "$JSON_OUTPUT" == "true" ]]; then

Instruction Override

High
Category
Prompt Injection
Confidence
90% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · scripts/pincer.sh (reported line 973)May include surrounding context.

sh
${BOLD}Options:${NC}
  --json       Output JSON (for scripting)
  --force      Override security blocks (not for malware)

${BOLD}Trust Actions:${NC}
  add <publisher>      Add to trusted list

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill exposes shell-capable installation behavior via its install script and documented command usage, but it does not declare any explicit tool scope such as permissions or allowed-tools. This weakens reviewability and enforcement, because consumers cannot clearly see or restrict that the skill will modify the user's environment and invoke local binaries.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

md
label: "Install pincer to PATH"
        script: |
          chmod +x "${SKILL_DIR}/scripts/pincer.sh"
          mkdir -p ~/.local/bin
          ln -sf "${SKILL_DIR}/scripts/pincer.sh" ~/.local/bin/pincer
          echo ""
          echo "✅ pincer installed!"

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

Manage Trust

bash
# Add trusted publisher (auto-approve clean skills)
pincer trust add steipete

# Remove from trusted

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

Manage Trust

bash
# Add trusted publisher (auto-approve clean skills)
pincer trust add steipete

# Remove from trusted

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

Manage Trust

bash
# Add trusted publisher (auto-approve clean skills)
pincer trust add steipete

# Remove from trusted

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
| Level | Meaning | Action |
|-------|---------|--------|
| ✅ **CLEAN** | No issues | Auto-approve if trusted publisher |
| ⚠️ **CAUTION** | Warnings present | Prompt for approval |
| 🚨 **DANGER** | Suspicious patterns | Block (override with `--force`) |
| ☠️ **MALWARE** | Known malicious | Block (cannot override) |

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
| Level | Meaning | Action |
|-------|---------|--------|
| ✅ **CLEAN** | No issues | Auto-approve if trusted publisher |
| ⚠️ **CAUTION** | Warnings present | Prompt for approval |
| 🚨 **DANGER** | Suspicious patterns | Block (override with `--force`) |
| ☠️ **MALWARE** | Known malicious | Block (cannot override) |

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/pincer.sh (reported line 705)May include surrounding context.

sh
| Level | Meaning | Action |
|-------|---------|--------|
| ✅ **CLEAN** | No issues | Auto-approve if trusted publisher |
| ⚠️ **CAUTION** | Warnings present | Prompt for approval |
| 🚨 **DANGER** | Suspicious patterns | Block (override with `--force`) |
| ☠️ **MALWARE** | Known malicious | Block (cannot override) |

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

The default configuration shows autoApprove: "clean", which means installation decisions may be made without user review when the publisher is trusted and scans pass. This creates a security gap because trust and scanning heuristics can fail, allowing a malicious or compromised publisher to bypass manual scrutiny.

Content

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

md
"trustedPublishers": ["openclaw", "steipete", "invariantlabs-ai"],
  "blockedPublishers": [],
  "blockedSkills": [],
  "autoApprove": "clean",
  "logInstalls": true,
  "minDownloads": 0,
  "minAgeDays": 0

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
"trustedPublishers": ["openclaw", "steipete", "invariantlabs-ai"],
  "blockedSkills": [],
  "blockedPublishers": [],
  "autoApprove": "clean",
  "logInstalls": true,
  "minDownloads": 0,
  "minAgeDays": 0

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/pincer.sh (reported line 72)May include surrounding context.

sh
"trustedPublishers": ["openclaw", "steipete", "invariantlabs-ai"],
  "blockedSkills": [],
  "blockedPublishers": [],
  "autoApprove": "clean",
  "logInstalls": true,
  "minDownloads": 0,
  "minAgeDays": 0

Rp1

Medium
Category
MCP Rug Pull
Confidence
65% confidence
Finding

uvx/uv tool run commands without ==version create a rug-pull risk.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding

The script runs uvx mcp-scan@latest --skills "$target", which resolves and executes the latest remote package version at scan time. This creates a supply-chain risk: a compromised or malicious upstream release could execute arbitrary code on the user's machine during what is presented as a security scan.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

When file fetching fails, the fallback path performs clawhub install ... --no-input into a temporary directory before completing the security decision flow. In the context of a 'security-first' installer, this is dangerous because installation logic may execute hooks, scripts, or other side effects from an untrusted skill before the user has approved it.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/pincer.sh (reported line 702)May include surrounding context.

sh
case "$risk_level" in
    clean)
      local auto_approve
      auto_approve=$(jq -r '.autoApprove // "clean"' "$CONFIG_FILE")
      if [[ "$auto_approve" == "clean" ]]; then
        info "Auto-approved (clean + trusted config)."

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · scripts/pincer.sh (reported line 704)May include surrounding context.

sh
case "$risk_level" in
    clean)
      local auto_approve
      auto_approve=$(jq -r '.autoApprove // "clean"' "$CONFIG_FILE")
      if [[ "$auto_approve" == "clean" ]]; then
        info "Auto-approved (clean + trusted config)."

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The autoApprove feature is active in the control path that treats a clean scan as sufficient to proceed. This is risky in context because the script markets itself as a security gate, but its scans are heuristic and partly depend on remote tooling, so automatic approval can create unwarranted trust.

Content

Scanner excerpt · scripts/pincer.sh (reported line 703)May include surrounding context.

sh
case "$risk_level" in
    clean)
      local auto_approve
      auto_approve=$(jq -r '.autoApprove // "clean"' "$CONFIG_FILE")
      if [[ "$auto_approve" == "clean" ]]; then
        info "Auto-approved (clean + trusted config)."
      else

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The autoApprove feature is active in the control path that treats a clean scan as sufficient to proceed. This is risky in context because the script markets itself as a security gate, but its scans are heuristic and partly depend on remote tooling, so automatic approval can create unwarranted trust.

Content

Scanner excerpt · scripts/pincer.sh (reported line 703)May include surrounding context.

sh
case "$risk_level" in
    clean)
      local auto_approve
      auto_approve=$(jq -r '.autoApprove // "clean"' "$CONFIG_FILE")
      if [[ "$auto_approve" == "clean" ]]; then
        info "Auto-approved (clean + trusted config)."
      else

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script persists scan state in a predictable fixed path, /tmp/pincer-risk-level, then later reads it back to decide whether installation should proceed. Because /tmp is world-writable and the filename is predictable, another local process could pre-create, replace, or race this file and influence security decisions, potentially downgrading or corrupting the scan outcome.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.