Back to skill

Security audit

Target Novelty Scorer

Security checks for vulnerabilities and agentic risk

Overview

This skill presents itself as real biomedical literature mining, but the included implementation generates simulated results while also allowing loosely scoped report writes.

Review before installing. Treat any scores or reports from this version as synthetic demonstration output, not real PubMed/PMC evidence. Avoid using --output with arbitrary or absolute paths, do not open CSV exports from untrusted target inputs in a spreadsheet, and prefer a fixed, reviewed dependency set before running it in a research environment.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:444
Finding
Unrestricted Output Path Allows Arbitrary File Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:412-416` and `scripts/main.py:444-447` **Vulnerability Type**: Unrestricted filesystem write **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument( "--output", "-o", help="Output file path (default: stdout)" ) ``` ```python if args.output: with open(args.output, "w", encoding="utf-8") as f: f.write(output) print(f"Report saved to: {args.output}") ``` ### Technical Analysis The `--output` argument accepts an arbitrary path and passes it directly to `open()` in truncating write mode. The implementation does not canonicalize the path, confine it to an approved output directory, reject traversal components, check for symbolic links, or prevent replacement of an existing file. This behavior contradicts the security checklist in `SKILL.md`, which identifies workspace-restricted output as a required control. Although the flaw does not grant privileges beyond those already held by the process, it exposes every file writable by the current operating-system account to replacement. ### Attack Path 1. An attacker controls or influences the arguments used to invoke the Skill. 2. The attacker supplies an output path targeting an existing writable file, for example: ```bash python scripts/main.py --target BRCA1 \ --output ../../writable-project/config.json \ --format json ``` 3. Path traversal resolves outside the intended project or output directory. 4. `open(args.output, "w")` opens the destination in truncation mode. 5. The existing file is erased and replaced with the generated report. A symbolic-link attack is also possible when an attacker can create a link at the selected output location: the script follows the link and writes to its target. ### Impact Assessment The attacker can overwrite files accessible to the operating-system identity running the Skill. Potential consequences include: - Destruction or corruption of projec ...[truncated 423 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create a dedicated output directory under the Skill workspace. - Resolve both the approved directory and requested destination with `pathlib.Path.resolve()`. - Reject any destination that is not a descendant of the approved output directory. - Reject absolute paths unless explicitly required and validated. - Prevent symbolic-link traversal by checking path components and using platform-appropriate no-follow file-opening controls. - Avoid silently replacing existing files. Use exclusive creation mode (`"x"`) unless overwrite behavior is explicitly authorized. - If replacement is required, write to a securely created temporary file in the same directory and atomically rename it after validation. - Return a generic error that does not unnecessarily expose internal filesystem paths. Example confinement check: ```python from pathlib import Path output_root = (Path.cwd() / "output").resolve() output_root.mkdir(parents=True, exist_ok=True) destination = (output_root / args.output).resolve() if output_root not in destination.parents: raise ValueError("Output path must remain inside the output directory") with destination.open("x", encoding="utf-8") as file: file.write(output) ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:350
Finding
CSV Formula Injection Through Attacker-Controlled Target Value<![CDATA[ ## Vulnerability Details **File Location**: `scripts/main.py:350-376` **Vulnerability Type**: CSV formula injection and improper CSV escaping **Risk Level**: Medium ### Vulnerable Code ```python def format_csv_output(result: NoveltyScore) -> str: """Format CSV output""" headers = [ "target", "novelty_score", "confidence", "research_heat", "uniqueness", "research_depth", "collaboration", "trend", "total_papers", "recent_papers", "clinical_trials", "interpretation" ] values = [ result.target, result.novelty_score, result.confidence, result.breakdown['research_heat'], result.breakdown['uniqueness'], result.breakdown['research_depth'], result.breakdown['collaboration'], result.breakdown['trend'], result.metadata['total_papers'], result.metadata['recent_papers'], result.metadata['clinical_trials'], f'"{result.interpretation}"' ] return ",".join(map(str, values)) ``` ### Technical Analysis `result.target` originates from the user-controlled `--target` argument and is inserted directly into a CSV record. Values beginning with spreadsheet formula indicators such as `=`, `+`, `-`, or `@` can be interpreted as formulas when the exported file is opened in spreadsheet software. The function also constructs CSV manually with `",".join(...)`. It does not correctly quote or escape commas, double quotes, carriage returns, or line feeds. Consequently, an attacker can alter the record structure, inject additional cells or rows, and place formula payloads into cells other than the original target field. The `headers` list is defined but is not included in the returned output, and the interpretation is manually surrounded with quotes without escaping embedded quote characters. ### Attack Path 1. An attacker provides a crafted target value, such as: ```bash python scripts/main.py \ --target '= ...[truncated 1397 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Use Python's standard `csv` module rather than manually joining values. - Neutralize text cells beginning with `=`, `+`, `-`, `@`, tab, carriage return, or line feed before writing them. - Apply neutralization after trimming or account for leading whitespace, because some spreadsheet applications ignore leading whitespace before formula markers. - Quote all fields using a consistent CSV policy. - Add tests covering commas, quotes, line breaks, formula prefixes, and Unicode text. - Warn recipients that exported CSV files contain untrusted data where complete formula suppression cannot be guaranteed across all spreadsheet applications. Example: ```python import csv import io def neutralize_spreadsheet_cell(value: object) -> object: if not isinstance(value, str): return value dangerous_prefixes = ("=", "+", "-", "@", "\t", "\r", "\n") if value.startswith(dangerous_prefixes): return "'" + value return value def format_csv_output(result: NoveltyScore) -> str: values = [ neutralize_spreadsheet_cell(result.target), result.novelty_score, result.confidence, result.breakdown["research_heat"], result.breakdown["uniqueness"], result.breakdown["research_depth"], result.breakdown["collaboration"], result.breakdown["trend"], result.metadata["total_papers"], result.metadata["recent_papers"], result.metadata["clinical_trials"], neutralize_spreadsheet_cell(result.interpretation), ] stream = io.StringIO(newline="") writer = csv.writer(stream, quoting=csv.QUOTE_ALL) writer.writerow(values) return stream.getvalue() ``` ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unpinned and Unnecessary Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-2` **Vulnerability Type**: Uncontrolled dependency resolution **Risk Level**: Low ### Vulnerable Code ```text dataclasses numpy ``` The documented installation command executes dependency resolution without version or integrity constraints: ```bash pip install -r requirements.txt ``` ### Technical Analysis Both dependencies are specified without exact versions or cryptographic hashes. Each installation therefore resolves whatever package release is available from the configured Python package index at that time. This makes builds non-reproducible and permits future, unreviewed releases to enter the execution environment. The `dataclasses` package is unnecessary for the declared Python 3.9 or newer runtime because `dataclasses` is part of the Python standard library. Retaining an unnecessary package expands the supply-chain attack surface. The dependency documentation is also inconsistent: `SKILL.md` lists `requests`, `pandas`, `biopython`, and `numpy`, while `requirements.txt` contains only `dataclasses` and `numpy`. Although the missing packages are not imported by the current implementation, this inconsistency impairs dependency review and may cause users to install additional packages manually from unverified sources. No evidence was found that either declared package is currently malicious. The vulnerability is the unsafe dependency-management practice, not a confirmed compromise of those packages. ### Attack Path 1. A user follows the documented installation procedure: ```bash pip install -r requirements.txt ``` 2. `pip` queries its configured package index and resolves the current releases of `dataclasses` and `numpy`. 3. Because no versions or hashes are specified, the selected artifacts may differ from those originally reviewed. 4. If a future release, package-index account, configured mirror, or distribution artifact is compromised, malicious package code can ...[truncated 592 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove `dataclasses` because the project requires Python 3.9 or newer. - Pin `numpy` to a reviewed, compatible version. - Generate and enforce hashes for every installed distribution using a lock-file or hash-checking workflow. - Install with `pip --require-hashes` in controlled environments. - Synchronize `SKILL.md` with the dependencies actually imported by the implementation. - Use a trusted package index and disable unintended fallback indexes. - Regularly scan pinned dependencies for known vulnerabilities. - Review and deliberately update dependencies rather than accepting new releases automatically. A minimal requirements file should use a reviewed exact version and hash: ```text numpy==<reviewed-version> \ --hash=sha256:<reviewed-distribution-hash> ``` ]]>
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
95% confidence
Finding
The documented behavior claims real literature mining from PubMed/PMC and database-selectable analysis, while the implementation reportedly uses simulated data and ignores database settings. This is dangerous because users may make scientific, regulatory, or prioritization decisions based on fabricated or misleading outputs that appear evidence-based.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill advertises Python execution and file output but does not declare any explicit tool scope such as allowed tools or permissions. In an agent environment, that omission weakens policy enforcement and can let the skill write files without clear user-visible constraints, increasing the chance of unintended or abusive filesystem actions.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill documentation describes external API access and report generation but does not clearly warn that input targets and associated metadata may be transmitted to third-party services and written to disk. In biomedical workflows, even seemingly simple target lists can be sensitive research context, so the lack of disclosure can cause unintended data exposure and weakens informed consent by users.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The code and CLI present this tool as performing PubMed-based literature mining, but the implementation only generates pseudo-random simulated results seeded from the query string. In a bioinformatics or target-prioritization workflow, this can mislead users into treating fabricated evidence as real analysis, causing incorrect scientific, business, or research decisions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
dataclasses
numpy
Confidence
95% confidence
Finding
The dependency list is unpinned, so installations may resolve to different versions over time. This creates supply-chain and reproducibility risk because a future incompatible or vulnerable release could be pulled without review, even though `dataclasses` itself is generally low risk and is only needed on older Python versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
dataclasses
numpy
Confidence
98% confidence
Finding
`numpy` is unpinned, which means the environment may install any available version, including releases with known security defects or breaking behavior. Because this skill performs biological literature and trend analysis, it likely processes external data at scale, so dependency drift can increase the chance of vulnerable code being introduced into runtime environments.

Unverifiable Dependency: numpy has 16 known advisory(ies) (CVE-2014-1859 (Numpy arbitrary file write via symlink attack); CVE-2021-41495 (NumPy NULL Pointer Dereference); CVE-2021-33430 (NumPy Buffer Overflow (Disputed)) +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
90% confidence
Finding
The manifest does not specify a `numpy` version, so it is impossible to verify whether the deployed package is affected by one of the known advisories. This is dangerous because a resolver may select a vulnerable version in some environments, leaving the skill exposed to memory-safety, denial-of-service, or file-handling issues associated with affected NumPy releases.

Intent-Code Divergence

Low
Confidence
90% confidence
Finding
The CLI offers a database-selection option suggesting the user can choose among PubMed, PMC, or all sources, but the argument is ignored entirely. This is deceptive interface behavior that can cause users to rely on an assumed data source or breadth of coverage that never actually affects execution.

Static analysis

No suspicious patterns detected.