Back to skill

Security audit

Minduploadedcrab Skillguard

Security checks for vulnerabilities and agentic risk

Overview

This is a real security-scanner skill, but its scanner can cross the intended scan boundary and can be made to skip files, so users should review it before relying on it.

Treat this as a review-required scanner, not a definitive security gate. Run it only in a low-privilege or isolated environment, avoid scanning untrusted packages that contain symlinks unless you inspect them first, do not trust package-provided .skillguard-ignore exclusions, and manually review SKILL.md even when the tool reports PASS.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/skillguard.py:82
Finding
Out-of-Scope Symlink Targets Are Read During Scanning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skillguard.py:82-85`, `scripts/skillguard.py:329-353`, and `scripts/skillguard.py:359-367` **Vulnerability Type**: Improper symlink boundary enforcement **Risk Level**: High ### Vulnerable Code ```python def get_skill_files(skill_path: Path) -> list: files = [] for root, dirs, filenames in os.walk(skill_path): dirs[:] = [d for d in dirs if d not in {"node_modules", ".git", "__pycache__", ".venv", "venv"}] for fname in filenames: files.append(Path(root) / fname) return files ``` ```python def scan_symlinks(files: list, skill_path: Path, result: ScanResult): """Detect symlinks that could point to sensitive files outside the skill directory.""" for f in files: if f.is_symlink(): rel = f.relative_to(skill_path) try: target = f.resolve() except (RuntimeError, OSError): result.add(Finding( severity=SEVERITY_HIGH, category="symlink", message=f"Broken or looping symlink: {rel}", file=str(rel), evidence=f"Raw target: {os.readlink(f)}", )) continue try: target.relative_to(skill_path) severity = SEVERITY_LOW except ValueError: severity = SEVERITY_CRITICAL msg = (f"Symlink escapes skill directory: {rel} -> {target}" if severity == SEVERITY_CRITICAL else f"Internal symlink: {rel} -> {target}") result.add(Finding( severity=severity, category="symlink", message=msg, file=str(rel), evidence=f"Target: {target}", )) ``` ```python for fpath in files: suffix = fpath.suffix.lower() if suffix not in TEXT_EXTENSIONS: continue ...[truncated 2787 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Resolve and validate every path immediately before opening it: ```python root = skill_path.resolve() resolved = fpath.resolve(strict=True) try: resolved.relative_to(root) except ValueError: continue ``` 2. Do not content-scan any symlink by default. Record the symlink as a finding and skip it: ```python if fpath.is_symlink(): continue ``` 3. Perform boundary validation inside `read_file_safe()` as a defense-in-depth measure, rather than relying only on callers. 4. Open files using platform-supported no-follow controls such as `O_NOFOLLOW` where available, then verify the opened file descriptor to reduce time-of-check/time-of-use races. 5. Avoid returning content from external targets in evidence fields. 6. Add regression tests for symlinks targeting: - Files outside the skill root. - SSH keys and cloud credential files. - Relative escape paths. - Chained symlinks. - Targets changed between validation and opening. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/skillguard.py:88
Finding
Untrusted Skill-Controlled Ignore File Can Suppress Security Scanning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skillguard.py:88-99` and `scripts/skillguard.py:356-365` **Vulnerability Type**: Attacker-controlled security exclusion mechanism **Risk Level**: High ### Vulnerable Code ```python def load_ignorelist(skill_path: Path) -> set: """Load .skillguard-ignore file if it exists. Returns set of relative paths to skip.""" ignore_file = skill_path / ".skillguard-ignore" ignored = set() if ignore_file.exists(): with open(ignore_file) as f: for line in f: line = line.strip() if line and not line.startswith("#"): ignored.add(line) return ignored ``` ```python files = get_skill_files(skill_path) result.file_count = len(files) ignored = load_ignorelist(skill_path) scan_hidden_files(files, skill_path, result) scan_symlinks(files, skill_path, result) scan_npm_package(skill_path, patterns, result) for fpath in files: suffix = fpath.suffix.lower() if suffix not in TEXT_EXTENSIONS: continue rel_path = str(fpath.relative_to(skill_path)) if rel_path in ignored: continue content = read_file_safe(fpath) ``` ### Technical Analysis The package being audited is untrusted, but it is allowed to provide `.skillguard-ignore` inside its own root. Any relative path listed in that file is skipped before its content is read or analyzed. This gives the subject of the security scan direct control over the scanner's coverage. A malicious package can place dangerous behavior in a source file and list that source file in `.skillguard-ignore`. The scanner may report the ignore file as a hidden file, but that medium-severity finding does not identify or analyze the omitted payload. Because risk scores are generated only from recorded findings, excluding malicious files can materially lower the score and lead to a misleading PASS or WARN verdict. This defeats the scanner's declared purpose of detecting mal ...[truncated 1403 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not honor exclusion files located inside an untrusted skill during security audits. 2. If exclusions are necessary, accept them only from a trusted, user-controlled path outside the scanned package, such as a command-line option: ```bash skillguard scan ./skill --ignore-file ~/.config/skillguard/ignore ``` 3. Treat every excluded executable or text file as an explicit finding and prevent a PASS verdict when security-relevant files were omitted. 4. Include an `excluded_files` field in JSON output and clearly state that the scan was incomplete. 5. Require an explicit opt-in flag before applying exclusions. 6. Consider supporting separate modes: - **Security mode:** no package-provided exclusions. - **Development mode:** trusted local exclusions are allowed but prominently reported. 7. Add regression tests proving that a target package cannot hide malicious content through `.skillguard-ignore`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/skillguard.py:368
Finding
Markdown Files Bypass Non-Prompt Security Scanners<![CDATA[ ## Vulnerability Details **File Location**: `scripts/skillguard.py:368-379` **Vulnerability Type**: Incomplete security scanning and content-type bypass **Risk Level**: Medium ### Vulnerable Code ```python result.scanned_count += 1 if suffix in (".md",): scan_prompt_injection(content, rel_path, patterns, result) continue if suffix in (".json", ".env", ".yaml", ".yml", ".toml"): scan_credential_access(content, rel_path, patterns, result) continue if suffix not in SCANNABLE_EXTENSIONS: continue scan_credential_access(content, rel_path, patterns, result) scan_network_exfil(content, rel_path, patterns, result) scan_dangerous_ops(content, rel_path, patterns, result) scan_filesystem_abuse(content, rel_path, patterns, result) scan_obfuscation(content, rel_path, result) scan_env_access(content, rel_path, result) ``` ### Technical Analysis Markdown files are processed only by `scan_prompt_injection()`. The unconditional `continue` prevents Markdown content from being checked for credential access, network exfiltration indicators, dangerous commands, filesystem abuse, or obfuscation. This is significant because `SKILL.md` is the primary instruction document loaded or followed by an agent. A malicious skill can express harmful behavior as operational instructions rather than executable source code. If those instructions avoid the fixed phrases in `prompt_injection_markers`, the scanner may not produce a finding. For example, instructions can direct an agent or user to read a credential file, execute a shell command, or submit data to an external endpoint without saying “ignore previous instructions,” “run this command,” or another exact marker. The current prompt-injection detector also searches only for fixed substrings and does not establish whether instructions request dangerous capabilities. The strings in `data/patterns.json`, including “ignore previous instructions,” “forget everything,” and “you are now,” are inert signatures ...[truncated 1561 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not stop scanning Markdown after prompt-injection analysis. Apply additional instruction-aware checks before continuing. 2. Add Markdown-specific detection for: - Requests to read credential, wallet, SSH, cloud, or environment files. - Shell commands and interpreter invocations. - Downloads and remote script execution. - Uploads, webhooks, and outbound data transmission. - Persistence or configuration modification instructions. 3. Parse fenced code blocks and inline commands separately so executable examples receive appropriate analysis. 4. Distinguish documentation that merely discusses a dangerous pattern from imperative instructions directing an agent to perform it. 5. Expand beyond exact substring matching by detecting intent and combinations of sensitive sources, actions, and external destinations. 6. Report uncertainty rather than PASS when a skill document contains operational commands that cannot be safely classified. 7. Add adversarial tests using paraphrased credential theft and exfiltration instructions that do not contain existing marker strings. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (18)

YARA rule 'agent_skill_credential_exfiltration_webhook': AI agent skill credential harvesting followed by webhook or external exfiltration [agent_skills]

Critical
Category
YARA Match
Content
w/openclaw.json",
    ".clawdbot/clawdbot.json",
    ".moltbot/moltbot.json",
    ".evm-wallets.json",
    ".env",
    ".ssh/",
    ".gnupg/",
    ".aws/credentials",
    ".config/solana/",
    "config.json",
    "credentials.json",
    "secrets.json",
    "private_key",
    "privateKey",
    "mnemonic",
    "seed_phrase",
    "api_key",
    "apiKey",
    "API_KEY",
    "OPENROUTER_API_KEY",
    "OPENAI_API_KEY",
    "ANTHROPIC_API_KEY",
    "ELEVENLABS_API_KEY",
    "BRAVE_API_KEY",
    "BLAND_API_KEY",
    "GITHUB_TOKEN",
    "DISCORD_TOKEN",
    "TELEGRAM_BOT_TOKEN",
    "SLACK_TOKEN",
    "DATABASE_URL",
    "SECRET_KEY",
    "ACCESS_TOKEN",
    "REFRESH_TOKEN",
    "botToken",
    "jwt",
    "JWT",
    "bearer",
    "solanaPrivateKey",
    "SOLANA_PRIVATE_KEY"
  ],
  "exfil_patterns": [
    "requests.post",
    "requests.put",
    "urllib.request.urlopen",
    "http.client.HTTPSConnection",
    "fetch(",
    "axios.post",
    "axios.put",
    "XMLHttpRequest",
    "WebSocket(",
Confidence
85% confidence
Finding
YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Ae1

High
Category
analysis-evasion
Content
n, prompt injection, and permission overreach before installation. Run: python3 scripts/skillguard.py scan <skill-directory>"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
n, prompt injection, and permission overreach before installation. Run: python3 scripts/skillguard.py scan <skill-directory>"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
n, prompt injection, and permission overreach before installation. Run: python3 scripts/skillguard.py scan <skill-directory>"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
n, prompt injection, and permission overreach before installation. Run: python3 scripts/skillguard.py scan <skill-directory>"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
n, prompt injection, and permission overreach before installation. Run: python3 scripts/skillguard.py scan <skill-directory>"
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
".clawdbot/clawdbot.json",
    ".moltbot/moltbot.json",
    ".evm-wallets.json",
    ".env",
    ".ssh/",
    ".gnupg/",
    ".aws/credentials",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".clawdbot/clawdbot.json",
    ".moltbot/moltbot.json",
    ".evm-wallets.json",
    ".env",
    ".ssh/",
    ".gnupg/",
    ".aws/credentials",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".clawdbot/clawdbot.json",
    ".moltbot/moltbot.json",
    ".evm-wallets.json",
    ".env",
    ".ssh/",
    ".gnupg/",
    ".aws/credentials",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".env",
    ".ssh/",
    ".gnupg/",
    ".aws/credentials",
    ".config/solana/",
    "config.json",
    "credentials.json",
Confidence
90% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".aws/credentials",
    ".config/solana/",
    "config.json",
    "credentials.json",
    "secrets.json",
    "private_key",
    "privateKey",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
".config/solana/",
    "config.json",
    "credentials.json",
    "secrets.json",
    "private_key",
    "privateKey",
    "mnemonic",
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Instruction Override

High
Category
Prompt Injection
Content
"os.environ"
  ],
  "prompt_injection_markers": [
    "ignore previous instructions",
    "ignore all previous",
    "disregard above",
    "forget everything",
Confidence
80% confidence
Finding
This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Content
se": [
    "os.remove(",
    "os.unlink(",
    "shutil.rmtree(",
    "fs.unlinkSync",
    "fs.rmdirSync",
    "fs.rmSync",
    "os.rename(",
    "shutil.move(",
    "open(.*'w'",
    "open(.*'a'",
    "fs.writeFileSync",
    "fs.appendFileSync",
    "../",
    "..\\\\",
    "path.join.*\\.\\.",
    "os.path.expanduser",
    "Path.home()",
    "os.environ"
  ],
  "prompt_injection_markers": [
    "ignore previous instructions",
    "ignore all previous",
    "disregard above",
    "forget everything",
    "new instructions",
    "override",
    "system prompt",
    "you are now",
    "pretend you are",
    "act as if",
    "do not follow",
    "bypass",
    "jailbreak",
    "DAN mode",
    "developer mode",
    "ignore safety",
    "ignore restrictions",
    "execute the following",
    "run this command",
    "send to webhook",
    "transmit to",
    "upload to",
    "exfiltrate"
  ],
  "suspicious_domains": [
    "ngrok.io",
    "ngrok-free.app",
    "webhook.site",
    "requestbin.co
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
"jailbreak",
    "DAN mode",
    "developer mode",
    "ignore safety",
    "ignore restrictions",
    "execute the following",
    "run this command",
Confidence
90% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
"DAN mode",
    "developer mode",
    "ignore safety",
    "ignore restrictions",
    "execute the following",
    "run this command",
    "send to webhook",
Confidence
90% confidence
Finding
Skill attempts to nullify the agent's safety policies or restrictions ('you have no restrictions', 'ignore your guidelines', 'do anything now'). This is a direct jailbreak that disables guardrails.

YARA rule 'offensive_tool_references': References to well-known offensive security tools [hacktools]

High
Category
YARA Match
Content
"bypass",
    "jailbreak",
    "DAN mode",
    "developer mode",
    "ignore safety",
    "ignore restrictions",
    "execute the following",
    "run this command",
    "send to webhook",
    "transmit to",
    "upload to",
    "exfiltrate"
  ],
  "suspicious_domains": [
    "ngrok.io",
    "ngrok-free.app",
    "webhook.site",
    "requestbin.com",
    "pipedream.net",
    "hookbin.com",
    "burpcollaborator.net",
    "interact.sh",
    "oastify.com",
    "dnslog.cn",
    "ceye.io",
    "beeceptor.com",
    "requestcatcher.com",
    "mockbin.org",
    "paste.ee",
    "pastebin.com",
    "hastebin.com",
    "transfer.sh",
    "file.io",
    "0x0.st"
  ],
  "malicious_npm_packages": [
    "event-stream",
    "flatmap-stream",
    "ua-parser-js",
    "coa",
    "rc",
    "colors",
    "faker",
    "node-ipc",
    "peacenotwar"
  ],
  "suspicious_npm_scripts": [
    "preinstall",
    "postinstall",
    "preuninstall"
  ]
}
Confidence
70% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.dynamic_code_execution

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/skillguard.py:221

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/skillguard.py:221