Back to skill

Security audit

Dependency Impact Analyzer

Security checks for vulnerabilities and agentic risk

Overview

The skill has a coherent dependency-analysis purpose, but its command examples can turn package names or repository dependency versions into executable Python code.

Review and harden the command snippets before installing or using this skill. Do not run the impact workflow on untrusted repositories or crafted package names until dynamic values are passed as arguments instead of interpolated into Python source; avoid unpinned npx execution and run audits without unnecessary secrets in the environment.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:78
Finding
Arbitrary Python Code Execution Through Unsafe Variable Interpolation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 78–85, 100–114, and 150–164 **Vulnerability Type**: Python code injection **Risk Level**: High ### Vulnerable Code At lines 78–85, the user-controlled package name is embedded directly into Python source: ```bash CURRENT=$(python3 -c " import json d = json.load(open('package.json')) v = d.get('dependencies',{}).get('$PACKAGE') or d.get('devDependencies',{}).get('$PACKAGE') or 'not found' print(v) " 2>/dev/null) echo "Current: $PACKAGE@$CURRENT" ``` At lines 100–114, the repository-derived `CURRENT` value is embedded into another Python program: ```bash npm info "$PACKAGE" versions --json 2>/dev/null | python3 -c " import json, sys, re try: versions = json.load(sys.stdin) current = '$CURRENT'.lstrip('^~>=') current_major = current.split('.')[0] if current != 'not found' else '0' latest = versions[-1] if isinstance(versions, list) else versions latest_major = latest.split('.')[0] if current_major != latest_major: print(f'⚠️ MAJOR version change: {current} → {latest} (likely breaking changes)') else: print(f'✅ Same major version: {current} → {latest} (should be backward compatible)') except Exception as e: print(f'Could not check versions: {e}') " 2>/dev/null ``` At lines 150–164, the package name is again embedded directly into generated Python source: ```bash python3 -c " import json lock = json.load(open('package-lock.json')) pkg = '$PACKAGE' rdeps = [] packages = lock.get('packages', lock.get('dependencies', {})) for name, info in packages.items(): deps = info.get('dependencies', {}) if pkg in deps: clean_name = name.replace('node_modules/', '') rdeps.append(f'{clean_name} (requires {pkg}@{deps[pkg]})') if rdeps: print(f'{len(rdeps)} packages also depend on {pkg}:') for r in rdeps[:20]: print(f' {r}') else: print(f'No other packages depend on {pkg} (leaf dependency)') " 2>/dev/null ``` ## ...[truncated 3137 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Never interpolate command arguments or repository-derived values into source code passed to `python3 -c`. Pass all dynamic values as positional arguments or environment variables and treat them strictly as data. For example, replace the current-version lookup with: ```bash CURRENT=$(python3 - "$PACKAGE" <<'PY' import json import sys package = sys.argv[1] with open("package.json", encoding="utf-8") as handle: data = json.load(handle) version = ( data.get("dependencies", {}).get(package) or data.get("devDependencies", {}).get(package) or "not found" ) print(version) PY ) ``` Pass both the current version and registry response safely when checking major versions: ```bash npm info "$PACKAGE" versions --json 2>/dev/null | python3 - "$CURRENT" <<'PY' import json import sys current = sys.argv[1].lstrip("^~>=") versions = json.load(sys.stdin) latest = versions[-1] if isinstance(versions, list) else versions current_major = current.split(".")[0] if current != "not found" else "0" latest_major = latest.split(".")[0] if current_major != latest_major: print(f"Major version change: {current} -> {latest}") else: print(f"Same major version: {current} -> {latest}") PY ``` Likewise, pass the package name as `sys.argv[1]` in the reverse-dependency analysis: ```bash python3 - "$PACKAGE" <<'PY' import json import sys package = sys.argv[1] with open("package-lock.json", encoding="utf-8") as handle: lock = json.load(handle) # Continue analysis using `package` only as data. PY ``` Additional hardening measures: 1. Validate npm package names against an appropriate allowlist pattern before registry operations. 2. Do not rely on shell or Python quote escaping as the primary defense; use argument boundaries. 3. Treat all manifest and lockfile values as untrusted repository input. 4. Avoid suppressing all errors during security-relevant operations, because doing so can conceal malformed input and attempted explo ...[truncated 254 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding
The skill recommends running `npx package-size` without pinning a version, which can fetch and execute whatever version is current on the registry at runtime. In a dependency-analysis skill, that creates a supply-chain execution risk: a compromised or newly malicious release could run arbitrary code in the user's environment when they follow the guidance.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The documentation states the skill supports JS/TS, Python, Go, and Rust projects, but the code only contains search and analysis logic for JS/TS, Python, and Go patterns. There are no Cargo.toml, Cargo.lock, or Rust `use`/`extern crate` handling paths, so the stated capability does not match the actual implemented behavior.

Intent-Code Divergence

Low
Confidence
72% confidence
Finding
The note frames the skill as non-executing and limited to reporting coverage gaps, but the code later invokes `npm audit --json`. While this does not run the project's tests, it does perform an active package-manager audit operation, making the comment's description of runtime behavior misleadingly narrow.

Static analysis

No suspicious patterns detected.