Back to skill

Security audit

Academic Translator

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says: it fetches or reads academic papers, translates/summarizes them, and answers paper-related questions, with some ordinary but worth-noting network and temporary-file risks.

Install only if you are comfortable with the agent downloading papers, extracting text from PDFs you provide, using web search for paper context, and storing the current paper's metadata/text temporarily under /tmp. Avoid processing sensitive unpublished PDFs unless your environment protects /tmp appropriately, and prefer limiting pages or file sizes for very large papers.

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
fetch_arxiv.py:28
Finding
ArXiv Metadata Retrieved over Unencrypted HTTP## Vulnerability Details **File Location**: `fetch_arxiv.py`, lines 28-32 **Vulnerability Type**: Plaintext network communication **Risk Level**: Medium ### Vulnerable Code ```python def fetch_metadata(arxiv_id: str) -> dict: """Fetch metadata via arxiv API.""" url = f"http://export.arxiv.org/api/query?id_list={arxiv_id}" r = requests.get(url, timeout=30) r.raise_for_status() text = r.text ``` ### Technical Analysis The application retrieves paper metadata from the arXiv API over plaintext HTTP. Although the subsequently downloaded PDF uses HTTPS, the title, authors, abstract, publication date, and other metadata are obtained through an unauthenticated and unencrypted transport. An attacker with a position on the network path, such as a malicious wireless access point, compromised gateway, or upstream network operator, can intercept and modify the HTTP response. The modified response is parsed and presented as trusted arXiv metadata. Because this content is subsequently used for summaries, translations, and research responses, forged metadata can affect the integrity of agent-generated content. ### Attack Path 1. A user asks the skill to retrieve an arXiv paper. 2. `fetch_metadata()` sends a plaintext HTTP request to `export.arxiv.org`. 3. An on-path attacker intercepts the request or response. 4. The attacker replaces XML fields such as the paper title, author names, abstract, or publication date. 5. The script parses the manipulated response without authenticity verification. 6. The forged metadata is returned in JSON and may be incorporated into summaries, translations, or answers presented to the user. ### Impact Assessment The vulnerability compromises the integrity and authenticity of retrieved paper metadata. An attacker can cause the agent to present false academic information or process attacker-controlled text as if it came from arXiv. This issue does not directly provide l ...[truncated 166 chars]
Remediation
## Remediation Suggestions 1. Replace the plaintext endpoint with the HTTPS equivalent: ```python url = f"https://export.arxiv.org/api/query?id_list={arxiv_id}" ``` 2. Keep TLS certificate verification enabled; do not pass `verify=False` to `requests`. 3. Validate that redirects remain on approved HTTPS arXiv domains. 4. Parse the response with a safe XML parser rather than regular expressions. 5. Confirm that the returned entry corresponds to the requested normalized arXiv identifier before trusting its metadata. 6. Treat metadata as untrusted external content when incorporating it into agent prompts or user-facing responses.

T09 · Insecure Skill Coding Practices

Warning
Location
fetch_arxiv.py:54
Finding
Unbounded PDF Download and Extraction Can Exhaust Local Resources## Vulnerability Details **File Location**: `fetch_arxiv.py`, lines 54-68; `extract_pdf.py`, lines 7-17 **Vulnerability Type**: Unbounded resource consumption **Risk Level**: Medium ### Vulnerable Code `fetch_arxiv.py` downloads the complete response without enforcing a maximum size: ```python def download_pdf(arxiv_id: str, output_dir: str = ".") -> str: url = f"https://arxiv.org/pdf/{arxiv_id}.pdf" os.makedirs(output_dir, exist_ok=True) path = os.path.join(output_dir, f"{arxiv_id.replace('/', '_')}.pdf") if os.path.exists(path): return path r = requests.get(url, timeout=120, stream=True) r.raise_for_status() with open(path, "wb") as f: for chunk in r.iter_content(8192): f.write(chunk) return path ``` `extract_pdf.py` processes all pages by default and accumulates all extracted text in memory: ```python def extract(path: str, max_pages: int = 0) -> dict: doc = fitz.open(path) pages = [] for i, page in enumerate(doc): if max_pages and i >= max_pages: break text = page.get_text("text") pages.append({"page": i + 1, "text": text}) return { "total_pages": len(doc), "extracted_pages": len(pages), "pages": pages, } ``` ### Technical Analysis The download routine streams data to disk but does not validate the response `Content-Type`, inspect or limit `Content-Length`, or stop after a maximum number of bytes. The request timeout does not provide a total response-size limit and therefore does not prevent a large response from consuming substantial disk space. The extraction routine defaults to processing every page when `max_pages` is omitted or zero. It stores every page's extracted text in a list and then serializes the complete result as one JSON object. Large or structurally pathological PDF files can therefore consume excessive CPU, memory, disk ...[truncated 2006 chars]
Remediation
## Remediation Suggestions 1. Define a strict maximum PDF size appropriate for the application. 2. Reject responses whose `Content-Length` exceeds that limit. 3. Track the cumulative number of streamed bytes and terminate the download when the limit is exceeded, because `Content-Length` may be absent or inaccurate: ```python max_bytes = 100 * 1024 * 1024 downloaded = 0 with open(path, "wb") as f: for chunk in r.iter_content(8192): if not chunk: continue downloaded += len(chunk) if downloaded > max_bytes: raise ValueError("PDF exceeds the permitted size") f.write(chunk) ``` 4. Validate that the response has an expected PDF media type and verify the downloaded file signature before passing it to PyMuPDF. 5. Remove partial files if downloading or validation fails. 6. Enforce maximum page count, extracted character count, processing time, and per-page output size during extraction. 7. Process or emit pages incrementally instead of retaining the complete extracted document and serialized JSON output in memory. 8. Run PDF parsing with operating-system memory, CPU, file-size, and execution-time limits in a restricted worker process. 9. Close documents explicitly with a context manager: ```python with fitz.open(path) as doc: # bounded extraction ``` 10. Apply the same size and page restrictions to uploaded or local PDFs, not only remotely downloaded files.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Vague Triggers

High
Confidence
98% confidence
Finding
The '[any question]' command creates an effectively unbounded invocation scope, allowing the skill to claim relevance for nearly any user query once paper context exists. This is dangerous because it can silently expand the skill from a specialized translator into a general-purpose agent that performs web research and answers unrelated questions under the guise of the stored paper context.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger condition is broad enough to activate on common user actions such as providing a PDF or asking to analyze a paper, which can cause the skill to take over conversations outside a narrowly intended scope. Over-broad activation increases the chance of unintended file processing, web access, and stateful storage in /tmp for requests where the user did not explicitly ask to invoke this skill.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The instruction 'Default translation direction: English → Chinese (unless user specifies otherwise)' establishes a language default that may override user expectations without explicit opt-in. This is a natural-language locale policy concern because it privileges a specific language absent an affirmative user choice.

Missing User Warnings

Low
Confidence
81% confidence
Finding
The script sends HTTP requests to arXiv APIs and PDF endpoints, but there is no runtime notice, logging, or explicit warning to the user that external network access will occur. Although network access is central to the script's purpose, the implementation itself lacks any visible disclosure mechanism.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This code performs a filesystem write by creating the output directory and saving a downloaded PDF, but it provides no confirmation prompt, logging, or explicit user-facing warning beyond the terse module docstring. For a code file, file writes should have some visible disclosure unless clearly communicated elsewhere.

Static analysis

No suspicious patterns detected.