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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.