Back to skill

Security audit

Neoantigen Predictor

Security checks for vulnerabilities and agentic risk

Overview

This NIH biosketch skill appears purpose-aligned, but its dependency setup and unrestricted file-output behavior need review before installation.

Review before installing. Use an isolated virtual environment, prefer the documented python-docx package over requirements.txt as written, pin dependency versions, and only run PubMed features when you are comfortable sending publication identifiers or author queries to NIH. Choose output paths carefully because existing writable files can be overwritten.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Incorrect and Unpinned Third-Party Dependencies

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-2; related imports and documentation at scripts/main.py:20-30 and SKILL.md:27-34
Vulnerability Type: Dependency-name inconsistency and unpinned dependencies
Risk Level: Medium

Vulnerable Code

text
docx
requests

The implementation expects the python-docx project through the following imports:

python
try:
    from docx import Document
    from docx.shared import Inches, Pt, RGBColor
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    HAS_DOCX = True
except ImportError:
    HAS_DOCX = False

try:
    import requests
    HAS_REQUESTS = True
except ImportError:
    HAS_REQUESTS = False

Technical Analysis

The dependency manifest specifies docx, whereas the documented dependency is python-docx. Although python-docx exposes the docx import namespace, docx and python-docx are distinct distribution names in package repositories. Installing from requirements.txt can therefore retrieve a package other than the one the implementation and documentation intend.

Neither dependency has an exact version constraint or integrity hash. Consequently, subsequent installations may resolve to newly published package versions that were not reviewed with this project. This increases exposure to dependency confusion, compromised upstream releases, unexpected breaking changes, and non-reproducible builds.

The audit did not establish that either currently resolved package is malicious. The vulnerability is the uncontrolled and inconsistent dependency-resolution process.

Attack Path

  1. A user or automated environment installs dependencies with pip install -r requirements.txt.
  2. The package resolver retrieves the package named docx, rather than the documented python-docx distribution.
  3. The resolver also selects whatever requests and docx versions currently satisfy the unconstrained requireme ...[truncated 838 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace the incorrect distribution name with the intended package:
    text
    python-docx==<reviewed-version>
    requests==<reviewed-version>
    
  2. Select versions that have been reviewed against current security advisories and compatibility requirements.
  3. Generate a lock file or hash-verified requirements file, for example with pip-compile --generate-hashes.
  4. Install with hash enforcement where practical:
    bash
    pip install --require-hashes -r requirements.txt
    
  5. Run dependency vulnerability scanning in CI and update dependencies through a controlled review process.
  6. Keep SKILL.md, requirements.txt, and the actual import behavior consistent.
  7. Install dependencies inside an unprivileged, isolated virtual environment rather than into a system-wide Python installation.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:592
Finding

Unrestricted Output Paths Permit Overwriting Arbitrary Writable Files

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py:257, scripts/main.py:592-593, scripts/main.py:607-608, and scripts/main.py:625-626
Vulnerability Type: Unrestricted filesystem output and unsafe file overwrite
Risk Level: Medium

Vulnerable Code

The DOCX generation path saves directly to the user-controlled output path:

python
# Save document
doc.save(output_path)
print(f"Generated NIH Biosketch: {output_path}")

Each JSON-producing mode similarly opens the supplied path in write mode:

python
if args.template:
    template = generate_template()
    with open(args.output, 'w', encoding='utf-8') as f:
        json.dump(template, f, indent=2, ensure_ascii=False)
    print(f"Template generated: {args.output}")
    return
python
publications = importer.fetch_multiple(pmids)

with open(args.output, 'w', encoding='utf-8') as f:
    json.dump(publications, f, indent=2, ensure_ascii=False)
print(f"Imported {len(publications)} publications to {args.output}")
python
publications = importer.search_by_author(last_name, first_name)

with open(args.output, 'w', encoding='utf-8') as f:
    json.dump(publications, f, indent=2, ensure_ascii=False)
print(f"Found {len(publications)} publications for {first_name} {last_name}")

Technical Analysis

The --output argument accepts arbitrary absolute paths and path-traversal sequences. The code neither constrains the resolved path to an approved workspace nor checks whether the destination already exists. Python write mode truncates an existing file, while Document.save() also replaces an existing destination.

The code does not validate that the extension matches the selected operation. Thus, template or PubMed JSON can be written over any writable filename, and generated DOCX data can similarly replace an existing writable file.

This conflicts with the security control listed in SKILL.md, which ...[truncated 1825 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require an explicitly configured output directory and resolve every requested output against it:
    python
    workspace = Path(configured_output_directory).resolve()
    destination = (workspace / args.output).resolve()
    
    if not destination.is_relative_to(workspace):
        raise ValueError("Output path must remain inside the approved workspace")
    
  2. Reject absolute user-supplied paths unless an explicit trusted-administrator mode permits them.
  3. Validate mode-specific extensions:
    • .json for templates and PubMed results
    • .docx for generated biosketch documents
  4. Refuse to overwrite existing files by default. Require an explicit --force option for trusted interactive use.
  5. Where appropriate, create files atomically using exclusive creation or a temporary file within the destination directory followed by a controlled rename.
  6. Reject symlink destinations or verify the final resolved destination immediately before writing to reduce symlink-based workspace escapes.
  7. Run the Skill under a dedicated, least-privileged account with write access only to its designated output directory.
  8. Add tests covering absolute paths, ../ traversal, existing-file overwrite, symlink escape, invalid extensions, and destinations outside the workspace.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
97% confidence
Finding

The skill documents executable scripts with file read/write and network behavior but does not declare any explicit tool scope such as permissions or allowed-tools. This creates an authorization ambiguity where an agent or reviewer cannot easily determine the intended capability boundaries, increasing the risk of over-privileged execution or unsafe default tool access.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill is described as generating NIH biosketch documents, which does not inherently require outbound network access, yet it includes the requests library. In a document-generation context, unnecessary network capability expands the attack surface and could enable data exfiltration, remote content fetching, or unexpected communication with external services if later used by the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

User-supplied PMIDs and author-search terms are transmitted to external NIH PubMed services without an explicit privacy notice or confirmation step. Although the destination is legitimate, these queries can reveal research interests, author identities, affiliations, or draft biosketch activity to a third party.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Generating a biosketch can reasonably use publication metadata supplied by the user, and even PMID resolution may be an implementation convenience. But a broader author search feature introduces discovery functionality beyond document construction, enabling collection of publication data not explicitly provided as biosketch input.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest frames the skill as a document generator, which would ordinarily imply local transformation of provided data into a biosketch. However, the implementation exposes additional modes to query PubMed by PMID or author name and retrieve remote metadata, expanding behavior beyond straightforward document generation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The tool writes potentially sensitive personal and research information to an arbitrary user-specified path without checking for overwrites or warning about local data exposure. This can lead to accidental disclosure or destruction of existing files, especially when used in shared environments or automated workflows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill advertises automatic PubMed import over the network without clearly warning users that publication identifiers and related request data will be sent to an external service. While PMIDs are usually not highly sensitive, associated metadata or usage context may still reveal research activity, and the lack of disclosure undermines informed consent and safe operation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file first declares dependencies on python-docx and requests and provides a pip install command for them, but later states that no additional Python packages are required. This is an active contradiction in the skill documentation about what is needed to run the code.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The docx dependency is unpinned, so installations may resolve to different versions over time, reducing reproducibility and increasing supply-chain risk. A future or compromised release could introduce malicious behavior or security defects without any change to the skill itself.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
docx
requests

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

The requests dependency is also unpinned, which means the installed version is nondeterministic and may pull in a vulnerable or unexpected release. Because requests enables network communication, version drift here is more sensitive than for a purely local library and can expose the skill to known client-side HTTP issues.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
docx
requests

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
94% confidence
Finding

requests has multiple known advisories, and because no version is pinned, there is no way to verify whether the deployed skill uses a safe release. In a skill that may process sensitive professional or biographical data, an affected requests version could enable credential leakage, improper certificate handling, or other HTTP client weaknesses if the library is used.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.