Back to skill

Security audit

skll-scan

Security checks for vulnerabilities and agentic risk

Overview

The skill is a purpose-aligned scanner, but it overstates its security coverage and includes risky operational guidance users should review before relying on it.

Treat this as a review-required scanner, not a source of installation approval. Do not rely on a low result as proof a skill is safe; manually review SKILL.md, install scripts, manifests, and non-Python/JS/TS files. Avoid running it as root, avoid the cron example unless you harden and monitor it, and do not submit internal domains or URLs to third-party threat-intel APIs without approval.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/skill-scan.py:240
Finding
Predictable Temporary Report Path Allows Symlink-Based File Overwrite## Vulnerability Details **File Location**: `scripts/skill-scan.py`, lines 240-243 **Vulnerability Type**: Predictable temporary file and unsafe file creation **Risk Level**: Medium ### Vulnerable Code ```python # 保存报告 report_file = f"/tmp/skill-scan-{os.path.basename(skill_path)}.json" with open(report_file, 'w') as f: json.dump(report, f, indent=2, ensure_ascii=False) ``` ### Technical Analysis The report filename is derived predictably from the basename of the scanned directory and is written directly into the shared `/tmp` directory. The call to `open(..., 'w')` follows symbolic links and does not use exclusive creation, symlink protection, or secure file permissions. A local attacker who can write to `/tmp` can pre-create the expected report path as a symbolic link to another file. If the scanner is subsequently run by a more privileged account, opening the report truncates and writes to the symbolic-link target. The generated report also contains scanned file paths and matched source-code excerpts. Its permissions depend on the process umask, potentially exposing source fragments containing credentials or other sensitive values to local users. ### Attack Path 1. The attacker identifies or predicts the basename of a directory that a privileged user will scan. 2. The attacker calculates the report path, such as `/tmp/skill-scan-target.json`. 3. The attacker creates that path as a symbolic link to a file writable by the scanner's account. 4. A privileged user invokes the scanner against the target directory. 5. The scanner follows the symbolic link when opening the report with write mode. 6. The target file is truncated and replaced with scanner-generated JSON. ### Impact Assessment Successful exploitation can overwrite or corrupt files accessible to the account running the scanner. The maximum privilege obtained is bounded by that account's existing filesystem permiss ...[truncated 386 chars]
Remediation
## Remediation Suggestions - Use `tempfile.NamedTemporaryFile` or `tempfile.mkstemp` to create an unpredictable report file atomically. - Create reports with permissions limited to the owner, such as mode `0600`. - If a stable output filename is required, place it in a user-controlled output directory and use exclusive creation with `O_CREAT | O_EXCL`. - Explicitly reject symbolic links and verify that the opened file is a regular file. - Consider requiring an explicit output path instead of automatically writing to shared temporary storage. - Redact likely credentials, tokens, and secret values from captured source excerpts. - Avoid running the scanner with elevated privileges unless strictly necessary.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/skill-scan.py:141
Finding
Restricted File-Type Coverage Can Produce Misleading Low-Risk Results## Vulnerability Details **File Location**: `scripts/skill-scan.py`, lines 141-158 **Vulnerability Type**: Incomplete security scanning and unsafe assurance **Risk Level**: Medium ### Vulnerable Code ```python all_findings = [] all_domains = [] # 扫描所有 .ts/.js/.py 文件 for ext in ["*.ts", "*.js", "*.py"]: for file in skill_path.rglob(ext): # 跳过 node_modules if "node_modules" in str(file): continue print(f"📄 扫描文件:{file}") # 代码模式扫描 findings = scan_code_patterns(file) all_findings.extend(findings) # 提取域名 domains = extract_domains(file) all_domains.extend(domains) ``` ### Technical Analysis The scanner analyzes only files ending in `.ts`, `.js`, or `.py`. It does not inspect `SKILL.md`, shell scripts, PowerShell scripts, package manifests, configuration files, templates, extensionless executables, or other formats capable of containing dangerous instructions and executable behavior. Domain extraction is performed only inside the same restricted loop, so network indicators in ignored files are also omitted. This is particularly important for an Agent Skill because instructions in `SKILL.md` can influence agent behavior without requiring a conventional source file. The documentation presents the utility as a pre-installation security scanner and describes a low result as safe to install. An attacker can therefore place malicious behavior entirely in an ignored file and receive a low-risk report, creating a false sense of security. ### Attack Path 1. An attacker creates a Skill containing benign or empty `.ts`, `.js`, and `.py` files. 2. The malicious instructions or commands are placed in an ignored file such as `SKILL.md`, `install.sh`, or a package lifecycle configuration. 3. A user runs the scanner before ...[truncated 820 chars]
Remediation
## Remediation Suggestions - Inspect all relevant text files rather than limiting analysis to three source-code extensions. - Add mandatory handling for `SKILL.md`, shell scripts, PowerShell, batch files, package manifests, lock files, configuration files, and installation hooks. - Detect binary files explicitly and enforce file-size and total-scan limits to prevent resource exhaustion. - Add Agent-specific checks for instruction hijacking, safety overrides, remote payload retrieval, persistence instructions, and sensitive-file access. - Analyze package lifecycle scripts and dependencies for supply-chain risks. - Extract URLs and domains from every supported textual file. - Report skipped files and unsupported formats prominently. - Replace the phrase “Safe to install” with a clear statement that a low result does not establish safety and must be combined with manual review. - Add regression tests in which malicious behavior appears exclusively in each supported file type.

T09 · Insecure Skill Coding Practices

Note
Location
references/threat-intel-apis.md:164
Finding
API Key Included in Google Safe Browsing Request URL## Vulnerability Details **File Location**: `references/threat-intel-apis.md`, lines 164-180 **Vulnerability Type**: Credential exposure through URL query parameters **Risk Level**: Low ### Vulnerable Code ```python def check_safebrowsing(url, api_key): endpoint = "https://safebrowsing.googleapis.com/v4/threatMatches:find" payload = { "client": { "clientId": "skill-scan", "clientVersion": "1.0.0" }, "threatInfo": { "threatTypes": ["MALWARE", "SOCIAL_ENGINEERING", "UNWANTED_SOFTWARE"], "platformTypes": ["ANY_PLATFORM"], "threatEntryTypes": ["URL"], "threatEntries": [{"url": url}] } } resp = requests.post(f"{endpoint}?key={api_key}", json=payload) data = resp.json() ``` ### Technical Analysis The integration example places the Google API key in the URL query string. Although HTTPS protects the request in transit, complete URLs may be recorded by client diagnostics, exception handlers, proxies, monitoring products, or application logs. This code is documentation rather than behavior executed by the current scanner. However, it is presented as copy-and-paste integration guidance and may propagate the unsafe credential-handling pattern into downstream implementations. The payload also transmits the inspected URL to Google Safe Browsing. That network disclosure is consistent with the declared threat-intelligence functionality, but internal or sensitive URLs should not be submitted without an explicit privacy policy or user approval. ### Attack Path 1. A developer copies the reference implementation into an active scanner. 2. The scanner sends requests containing the API key in the query string. 3. Infrastructure or application diagnostics record the complete request URL. 4. A user with access to those logs obtains the API key. 5. The exposed key is reused against enabl ...[truncated 585 chars]
Remediation
## Remediation Suggestions - Prefer an authorization header or another non-URL authentication mechanism when supported by the provider. - If the API requires a query-string key, explicitly document that request URLs must be redacted from logs and diagnostics. - Configure monitoring systems, HTTP clients, and proxies to replace the `key` parameter with a redacted value. - Apply API restrictions, application restrictions, quota limits, and billing alerts to the key. - Store credentials outside source code using a protected credential store or environment-specific secret manager. - Rotate the key immediately if it is ever captured in logs. - Require explicit user consent before submitting internal domains or sensitive URLs to external threat-intelligence services. - Provide a local-only mode for private indicators.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Credential Access

High
Category
Privilege Escalation
Content
r"shutil\.(copy|move|remove)"
    ],
    "sensitive": [
        r"process\.env",
        r"process\.argv",
        r"os\.environ",
        r"secret\s*=",
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding
The skill documentation describes and instructs use of capabilities equivalent to file read/write, network access, and shell execution, but the skill metadata does not declare any tool scope such as permissions or allowed-tools. This creates a governance gap: reviewers and enforcement systems cannot reliably understand or constrain the skill's operational power, increasing the chance of over-privileged or unexpected execution.

Session Persistence

Medium
Category
Rogue Agent
Content
### Periodic Audit

Create a cron job for weekly audits:

```bash
# /etc/cron.d/skill-scan
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
### Periodic Audit

Create a cron job for weekly audits:

```bash
# /etc/cron.d/skill-scan
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.

External Transmission

Medium
Category
Data Exfiltration
Content
**Purpose**: IP address reputation checking

**API Endpoint**: `https://api.abuseipdb.com/api/v2/check`

**Authentication**: API Key required (free tier available)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
**Purpose**: IP address reputation checking

**API Endpoint**: `https://api.abuseipdb.com/api/v2/check`

**Authentication**: API Key required (free tier available)
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}
    }
    
    resp = requests.post(f"{endpoint}?key={api_key}", json=payload)
    data = resp.json()
    
    if 'matches' in data:
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Session Persistence

Medium
Category
Rogue Agent
Content
## Configuration Example

Create a config file at `~/.skill-scan/config.json`:

```json
{
Confidence
80% confidence
Finding
The documentation recommends storing multiple API keys in a persistent plaintext JSON file under the user's home directory without mentioning permission hardening, secret-store alternatives, or encryption. If local files are exposed through weak permissions, backups, multi-user systems, or malware, these credentials could be abused to query paid services or access threat-intel accounts.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The testing section provides copy-paste commands that transmit queried domains to third-party services, but the warning about privacy and external disclosure appears much earlier and is not adjacent to the test examples. In practice, users may run these examples on internal or sensitive domains without realizing they are disclosing telemetry to external vendors.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Test URLhaus
curl -X POST https://urlhaus-api.abuse.ch/v1/host/ \
  -d "host=google.com"

# Test VirusTotal (replace API_KEY)
Confidence
88% confidence
Finding
The curl test example actively instructs users to send a host value to a third-party service without an adjacent disclosure warning. While intended for legitimate testing, such examples can cause accidental leakage of internal or investigative indicators when copied verbatim or adapted by users.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This Python file contains user-facing natural-language text entirely in Chinese, including the module description and usage instructions. Under the stated policy, forcing a specific language without user opt-in is a locale-policy violation unless the constraint is explicitly justified, which is not present here.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill advertises threat-intelligence API checking, but `check_threat_intel` only compares domains against a tiny hardcoded blacklist and returns `unknown` for everything else. This creates a false sense of security: users may trust scan results that omit real malicious domains because the documented external checks are not implemented.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The docstring states that the function performs threat-intelligence checks, but the code does not do so beyond a local blacklist lookup. Misleading security documentation in a scanner is dangerous because operators may make installation or distribution decisions based on inaccurate assumptions about what was actually checked.

Static analysis

No suspicious patterns detected.