Back to skill

Security audit

paper claw

Security checks for vulnerabilities and agentic risk

Overview

This paper-digest skill is mostly purpose-aligned, but it needs Review because its example code can execute a Python script outside the reviewed skill package.

Install only if you are comfortable reviewing or fixing the package first. In particular, ensure the main script is packaged inside the skill directory, correct the SKILL_ROOT path handling, and require explicit confirmation before sending email or changing recipients/source configuration.

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

T09 · Insecure Skill Coding Practices

Warning
Location
example.py:14
Finding
Execution of an Unverified Python Script Outside the Skill Directory## Vulnerability Details **File Location**: `example.py`, lines 14 and 31-38 **Vulnerability Type**: Execution across the packaged Skill trust boundary **Risk Level**: Medium **Vulnerable Code**: ```python # Skill root directory SKILL_ROOT = Path(__file__).resolve().parents[1] PRESETS_DIR = Path(__file__).resolve().parent / "presets" ``` ```python cmd = ["python", str(SKILL_ROOT / "scripts" / "main.py")] if day: cmd.extend(["--day", day]) elif start_date and end_date: cmd.extend(["--start-date", start_date, "--end-date", end_date]) result = subprocess.run(cmd, capture_output=True, text=True, cwd=SKILL_ROOT) ``` ### Technical Analysis `example.py` is located at the root of the supplied Skill. Consequently, `Path(__file__).resolve().parents[1]` resolves to the parent of the Skill directory rather than the Skill directory itself. The `fetch_papers()` function then attempts to execute `scripts/main.py` beneath that external directory. The audited package does not contain `scripts/main.py`. Therefore, the code delegates execution to a file that is outside the reviewed package and whose integrity is not established. Although command arguments are passed as an array and do not create direct shell injection, the executable script path crosses the Skill trust boundary. This behavior is not necessary for the declared functionality. A paper-fetching implementation should be packaged within the Skill and resolved relative to its verified root. ### Attack Path 1. An attacker obtains write access to the parent directory of the installed Skill or causes the Skill to be installed beneath an attacker-controlled directory. 2. The attacker creates `scripts/main.py` under that parent directory. 3. An Agent or user invokes `fetch_papers()`. 4. `SKILL_ROOT` resolves to the external parent directory. 5. `subprocess.run()` launches the attacker-controlled Python script. 6. The script executes with the same opera ...[truncated 672 chars]
Remediation
## Remediation Suggestions 1. Resolve the Skill root to the directory containing `example.py`: ```python SKILL_ROOT = Path(__file__).resolve().parent ``` 2. Package `scripts/main.py` inside the Skill rather than depending on an external sibling or parent path. 3. Resolve and validate the target before execution: ```python script = (SKILL_ROOT / "scripts" / "main.py").resolve() if not script.is_relative_to(SKILL_ROOT.resolve()): raise ValueError("Script path escapes the Skill directory") if not script.is_file(): raise FileNotFoundError(script) ``` 4. Use `sys.executable` instead of the generic `python` command to ensure the intended Python interpreter is used: ```python import sys cmd = [sys.executable, str(script)] ``` 5. Verify the integrity or signature of executable packaged components before invocation where the deployment model permits package modification. 6. Run the Skill under a restricted operating-system account without access to unrelated credentials or sensitive files.

T09 · Insecure Skill Coding Practices

Note
Location
example.py:67
Finding
Path Traversal Through Unvalidated Date and Preset Identifiers## Vulnerability Details **File Location**: `example.py`, lines 67-83 and 133-137 **Vulnerability Type**: Improper validation of path components **Risk Level**: Low **Vulnerable Code**: ```python if format == "markdown": path = SKILL_ROOT / "content" / "posts" / f"{date}-arxiv-audio-digest.md" if path.exists(): return {"content": path.read_text(encoding="utf-8"), "format": "markdown"} elif format == "json": path = SKILL_ROOT / "data" / "processed" / f"{date}.json" if path.exists(): data = json.loads(path.read_text(encoding="utf-8")) return {"content": data, "format": "json"} elif format == "summary": path = SKILL_ROOT / "data" / "processed" / f"{date}.json" if path.exists(): data = json.loads(path.read_text(encoding="utf-8")) ``` ```python preset_path = PRESETS_DIR / f"{preset_id}.json" if not preset_path.exists(): return None return json.loads(preset_path.read_text(encoding="utf-8")) ``` ### Technical Analysis The externally supplied `date` and `preset_id` values are interpolated directly into filesystem paths. The implementation does not reject path separators, normalize and validate the resulting path, or confirm that the resolved file remains beneath the intended base directory. The schema in `tools.json` documents date formatting and allowlists preset identifiers, but these controls are not enforced by the Python functions themselves. Direct callers of `get_digest_content()` and `get_preset()` can supply values containing `../` components. The automatically appended filename suffixes constrain which external files can be reached. For example, the JSON branches can primarily target files whose resulting names end in `.json`. Nevertheless, suitably located JSON or digest files outside the intended directories can be read and returned. ### Attack Path 1. An untrusted caller gains the ability to invoke the Python API directly or ...[truncated 1033 chars]
Remediation
## Remediation Suggestions 1. Parse dates strictly instead of treating them as arbitrary path fragments: ```python from datetime import datetime parsed = datetime.strptime(date, "%Y-%m-%d") safe_date = parsed.strftime("%Y-%m-%d") ``` 2. Allowlist preset identifiers from trusted preset metadata or a fixed set: ```python allowed_presets = { "speech_audio", "nlp", "computer_vision", "general_ai", } if preset_id not in allowed_presets: raise ValueError("Invalid preset identifier") ``` 3. Add a reusable resolved-path containment check: ```python def safe_child(base: Path, filename: str) -> Path: base = base.resolve() candidate = (base / filename).resolve() if not candidate.is_relative_to(base): raise ValueError("Path escapes the permitted directory") return candidate ``` 4. Reject absolute paths, path separators, null bytes, and traversal components before constructing a filename. 5. Enforce validation in the Python implementation even when framework-level schemas are present, because direct callers can bypass tool-schema checks. 6. Apply least-privilege filesystem permissions so the Agent cannot read unrelated configuration, credential, or user-data files.
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
Findings (16)

Memory Manipulation

High
Category
Memory Poisoning
Content
# View papers by category
cat data/processed/2026-03-10.json | jq '.grouped.ASR'

# Reset state and re-fetch
python scripts/reset_state.py
python scripts/main.py --day 2026-03-10
```
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Credential Access

High
Category
Privilege Escalation
Content
}
  ],
  "config": {
    "env_file": ".env",
    "config_dir": "config",
    "output_dir": "content/posts",
    "data_dir": "data/processed"
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
91% confidence
Finding
The skill documents capabilities that read files, write configuration/state, and execute shell commands, but it does not declare any explicit tool scope or permission boundaries. In agent environments, this increases the risk of over-broad execution because consumers cannot tell up front that running the skill may modify local files or invoke system commands.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The workflow documentation says email is automatically sent, but the skill description and execution guidance do not prominently warn that running the main workflow can transmit generated content to configured recipients. This is a meaningful side effect because an agent or user could trigger external communication and possible data disclosure without realizing it.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
elif start_date and end_date:
        cmd.extend(["--start-date", start_date, "--end-date", end_date])
    
    result = subprocess.run(cmd, capture_output=True, text=True, cwd=SKILL_ROOT)
    
    # Parse output to find generated files
    output = result.stdout + result.stderr
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
90% confidence
Finding
This example exposes a persistent reconfiguration path that writes to the skill's default configuration on disk, changing sources and classification behavior beyond a transient fetch/summarize operation. In an agent setting, that means a caller can silently alter future runs and steer what content is collected or how it is categorized, creating integrity and persistence risks.

Context-Inappropriate Capability

Medium
Confidence
85% confidence
Finding
The code provides an unjustified persistent reconfiguration mechanism relative to the paper-processing purpose by allowing presets to overwrite core defaults on disk. This increases danger in agent environments because one invocation can alter all subsequent behavior, enabling durable tampering rather than a one-time action.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The function persistently rewrites recipients.json, allowing modification of who receives future email digests. Even if intended functionality includes email delivery, exposing broad recipient editing in an example utility creates a state-changing capability that could redirect notifications or add unauthorized recipients without adequate safeguards.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The function writes personal contact information to a persistent recipients.json file without any user-facing warning, consent flow, or minimization controls. This creates privacy and governance risk because email addresses and names may be stored unexpectedly, exposed to other local users/processes, or retained longer than intended.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Although multiple languages are supported, the fetch_papers tool defaults the output language to "zh". A forced default locale in a general-purpose skill can be a policy issue when users are not explicitly offered or prompted for their language preference.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill exposes an email-sending action that can transmit generated digest content and recipient information to external parties, but the manifest does not warn that data leaves the local/system boundary. In an agent setting, this increases the risk of unintended exfiltration of research content, recipient addresses, or sensitive summaries if invoked without explicit user awareness.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The preset workflow states that apply_preset automatically updates config/default.json, but it does not clearly warn users that invoking it modifies local configuration files. In an agent setting, undocumented file mutation can lead to unintended persistent state changes and surprise reconfiguration.

Vague Triggers

Low
Confidence
90% confidence
Finding
This JSON manifest describes the skill as "Broad AI/ML research covering multiple domains," which is extremely wide in scope and does not define clear activation boundaries or exclusions. For a manifest file, this lack of specificity can make it unclear when the skill should be selected versus more specialized AI-related skills.

Vague Triggers

Low
Confidence
80% confidence
Finding
This JSON manifest includes the description "Broad AI/ML research covering multiple domains," which is highly general and lacks clear scope boundaries. In a manifest context, such broad wording can overlap with many common AI-related requests and makes it unclear when this preset should be selected versus more specific presets.

Natural-Language Policy Violations

Low
Confidence
79% confidence
Finding
This manifest embeds multilingual labels, including Japanese, but there is no natural-language indication of how locale is selected or whether users can opt into a preferred language. Under the policy rule, forcing or implicitly assuming a locale without documented choice can be a language/locale policy concern.

Vague Triggers

Low
Confidence
80% confidence
Finding
This manifest includes broad invocation descriptions such as "Configure data sources and categories" and similar update/configure actions elsewhere, without negative examples or contextual constraints. In a manifest file, such generic phrasing can overlap with common user requests and make unintended skill invocation more likely.

Static analysis

No suspicious patterns detected.