Back to skill

Security audit

Arxiv Paper Downloader

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its paper-downloading purpose, but crafted arXiv IDs may allow file writes outside the selected download folder.

Install only if you are comfortable with a downloader that writes PDFs and metadata locally. Use a dedicated output directory and trusted arXiv IDs; the package should ideally validate IDs, enforce output-directory containment, document overwrite behavior, and pin dependencies before broad use.

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

Warning
Location
src/skill.py:101
Finding
Unvalidated arXiv ID Can Cause Output Path Traversal## Vulnerability Details **File Location**: `src/skill.py`, lines 101-114 **Vulnerability Type**: Path traversal through unsafe filename construction **Risk Level**: Medium ```python pdf_url = f"https://arxiv.org/pdf/{arxiv_id}.pdf" safe_title = "".join(c if c.isalnum() or c in " -_" else "_" for c in (title[:40] or arxiv_id)) filename = f"{arxiv_id}_{safe_title}.pdf" filepath = self.output_dir / filename if filepath.exists(): return {"status": "skipped", "path": str(filepath), "size": 0} try: resp = self.session.get(pdf_url, timeout=120) if resp.status_code == 200: self.output_dir.mkdir(parents=True, exist_ok=True) with open(filepath, "wb") as f: f.write(resp.content) ``` ### Technical Analysis The externally supplied `arxiv_id` is inserted directly into `filename`. Only the title-derived portion is sanitized. Consequently, an ID containing path separators, parent-directory components, or platform-specific path syntax can cause `filepath` to point outside `self.output_dir`. The public `download_by_arxiv_ids()` entry point accepts arbitrary strings and forwards them to this method without validating them against supported arXiv identifier formats. `Path` does not confine joined paths to the original base directory. For example, parent-directory components can be resolved by the operating system when the file is opened. Exploitation is conditional on the constructed arxiv.org request returning HTTP status 200 and on any required intermediate directories existing. These conditions reduce reliability but do not establish a safe filesystem boundary. The implementation also does not resolve the destination and verify that it remains beneath the configured output directory. ### Attack Path 1. An attacker supplies a crafted string containing path traversal components through `download_by_arxiv_ids()`. 2. The value is passed unchanged to `ArxivDownloader.download_pdf()`. 3 ...[truncated 963 chars]
Remediation
## Remediation Suggestions 1. Validate each identifier before constructing either the URL or filename. Permit only documented modern and legacy arXiv identifier formats using a full-string match. 2. Explicitly reject `/`, `\`, null bytes, parent-directory components, URL query markers, fragments, and unexpected percent-encoded characters. 3. Construct the filename exclusively from the validated identifier rather than retaining any raw user-supplied path characters. 4. Resolve both the base directory and candidate destination, then enforce containment before opening the file: ```python base = self.output_dir.resolve() destination = (base / filename).resolve() if destination.parent != base: raise ValueError("Invalid output path") ``` 5. Use `urllib.parse.quote()` with an empty safe-character set, or an equivalent URL-path encoder, after identifier validation when constructing the remote URL. 6. Add security tests covering `../`, absolute paths, Windows separators, URL fragments, query strings, percent encoding, and malformed legacy identifiers. 7. Consider opening new files in exclusive mode (`"xb"`) or using an atomic temporary-file replacement strategy to reduce unintended overwrites and partial files.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented purpose emphasizes pre-curated paper collections, but the skill also appears to support arbitrary user-supplied arXiv IDs and metadata export. This mismatch weakens user and platform trust boundaries because operators may approve the skill expecting a limited curated downloader while it can fetch broader remote content and create additional local files.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares no explicit tool scope or permissions even though its documented behavior requires network access and file writing. In agent environments, missing scope declarations can cause the skill to run with broader-than-expected privileges, reducing auditability and making unintended downloads or writes harder to control.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
Confidence
94% confidence
Finding
The dependency is specified as `requests>=2.28.0`, which allows installation of any future version and does not guarantee reproducible builds. This increases supply-chain risk because different environments may resolve to different releases, including versions later found to be vulnerable or incompatible.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding
Because `requests` is not pinned, it is impossible to verify whether the installed version is affected by known advisories. In a skill that downloads remote content from arXiv, an HTTP client library is security-relevant, so leaving its resolved version unconstrained increases the chance of pulling an affected release in some environments.

Missing User Warnings

Low
Confidence
92% confidence
Finding
The manifest advertises downloading papers to a local output directory but does not clearly warn that the skill will write files onto the user's filesystem. In an agent setting, silent local writes can surprise users, clutter storage, or overwrite expected locations if the caller does not fully understand the side effects.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This code performs an HTTP request to arXiv and writes the returned PDF to disk, but there is no confirmation prompt or explicit user-facing warning at the point of action about contacting an external service and creating files. Although downloading papers is the skill's purpose, the rule still calls for disclosure when safety-relevant operations like network access and file writes lack any clear warning in code or accompanying markdown.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The batch download flow creates a JSON metadata file containing category and per-paper results, but there is no explicit disclosure to the user that additional local files beyond PDFs will be created. This is a filesystem-modifying operation that should be clearly communicated, especially because it persists run details automatically.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The codebase consistently defines the paper category as "agent_testing" in the collections and public function docs, but the CLI advertises and restricts choices to "testing" with a default of "testing". As a result, the inline CLI help suggests a valid category that the downloader does not recognize, causing behavior that contradicts the documented interface intent.

Static analysis

No suspicious patterns detected.