Back to skill

Security audit

Emerging Topic Scout

Security checks for vulnerabilities and agentic risk

Overview

This research trend scanner is mostly purpose-aligned, but it needs review because it can overwrite arbitrary files, uses browser-like headers to work around site protections, and installs broad unpinned dependencies.

Install only in an isolated virtual environment and run it from a limited workspace. Treat arXiv/feed fetching as the safer path, review whether any bioRxiv/medRxiv access attempts comply with those sites' terms, constrain any report output path yourself, and prefer pinned dependencies before routine use.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/main.py:632
Finding

Unrestricted Output Path Allows Arbitrary File Overwrite

Content
View full analysis

Vulnerability Details

File Location: scripts/main.py, lines 632-635 and 681-684
Vulnerability Type: Arbitrary file overwrite through an unrestricted user-controlled path
Risk Level: Medium

Vulnerable Code

python
parser.add_argument(
    "--save",
    type=str,
    help="Save output to file"
)
python
if args.save:
    with open(args.save, 'w', encoding='utf-8') as f:
        f.write(output)
    print(f"\nOutput saved to: {args.save}")

Technical Analysis

The --save argument accepts an arbitrary filesystem path. The supplied value is passed directly to open() in write mode without path normalization, workspace-boundary enforcement, symlink validation, file-type validation, or overwrite confirmation.

Opening a file with mode w creates it if it does not exist and truncates it if it does. Consequently, any file writable by the process can be replaced with generated report content. Absolute paths, ../ traversal sequences, and symlinks pointing outside the project are not rejected.

This exceeds the minimum filesystem privileges required for the declared functionality. Report generation only requires writing to a controlled output directory. It also contradicts the security checklist in SKILL.md, which states that output should be restricted to the workspace.

Attack Path

  1. An attacker supplies task content or instructions that influence the Agent to save a report to a crafted path.
  2. The Agent invokes the Skill with an argument such as --save ../../some-writable-file.
  3. The script passes that path directly to open() using truncating write mode.
  4. If the process has permission to write the target, its existing content is destroyed and replaced by the generated report.
  5. The same path can be exploited through a symlink placed in an otherwise expected output location.

No privilege escalation beyond the operating-system permissions of the invoking process occurs. Exploitation is limited to fi ...[truncated 699 chars]

Remediation
View remediation

Remediation Suggestions

  1. Define a dedicated output directory beneath the project workspace, such as output/.
  2. Resolve both the output directory and requested path with Path.resolve().
  3. Reject any path whose resolved value is not a descendant of the approved output directory.
  4. Reject existing symlinks and verify parent path components before opening the file.
  5. Use exclusive creation mode (x) by default to prevent silent overwrites.
  6. Require an explicit, separate overwrite flag when replacement is intentional.
  7. Consider accepting only a filename rather than a complete path.
  8. Apply an allowlist of appropriate report extensions based on the selected output format.

Example hardening pattern:

python
output_dir = (Path(__file__).parent.parent / "output").resolve()
output_dir.mkdir(parents=True, exist_ok=True)

requested = (output_dir / Path(args.save).name).resolve()
if output_dir not in requested.parents:
    raise ValueError("Output path must remain inside the output directory")
if requested.is_symlink():
    raise ValueError("Symbolic-link output paths are not permitted")

with requested.open("x", encoding="utf-8") as f:
    f.write(output)

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Loosely Constrained and Unnecessary Third-Party Dependencies Expand Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: scripts/requirements.txt, lines 1-7; additionally requirements.txt, lines 1-4
Vulnerability Type: Non-reproducible dependency installation and excessive dependency scope
Risk Level: Medium

Vulnerable Code

scripts/requirements.txt:

text
requests>=2.28.0
feedparser>=6.0.10
pandas>=1.5.0
scikit-learn>=1.1.0
numpy>=1.23.0
textblob>=0.17.1
pyyaml>=6.0

Root requirements.txt:

text
dataclasses
feedparser
requests
textblob

Technical Analysis

The root dependency file contains no version constraints. The script-specific dependency file specifies only minimum versions, without exact pins, upper bounds, package hashes, or a reviewed lock file. Installation can therefore resolve to different package and transitive-dependency versions over time.

Several declared packages are unnecessary for the reviewed executable. pandas, scikit-learn, numpy, and pyyaml are not imported by scripts/main.py. TextBlob is imported but never used. The dataclasses package is also unnecessary on supported modern Python versions where dataclasses is part of the standard library.

Every additional package expands the supply-chain attack surface and may execute build or installation logic under the privileges of the user running pip. The two inconsistent requirements files also make it unclear which dependency set is authoritative.

No evidence establishes that the currently named packages are malicious. The vulnerability is the unsafe, excessive, and non-reproducible dependency policy rather than a confirmed compromised package.

Attack Path

  1. A user follows the installation instructions and runs pip install -r requirements.txt or pip install -r scripts/requirements.txt.
  2. The package resolver selects the newest releases satisfying the broad or absent constraints, including transitive dependencies.
  3. A future compromised release, malicious transitive dependency, or unsafe ...[truncated 1006 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove dependencies not required by the executable, including pandas, scikit-learn, numpy, and pyyaml.
  2. Remove the unused TextBlob import and dependency unless it is incorporated into an implemented feature.
  3. Remove the dataclasses backport when the minimum supported Python version already provides it.
  4. Maintain one authoritative dependency manifest instead of two inconsistent files.
  5. Pin each direct and transitive dependency to a reviewed version.
  6. Generate and verify cryptographic hashes, for example through a hash-locked requirements file.
  7. Install with hash enforcement:
bash
pip install --require-hashes -r requirements.lock
  1. Audit dependencies regularly with a vulnerability scanner and review updates before changing the lock file.
  2. Perform installation and execution in an isolated, least-privileged environment with restricted filesystem and credential access.
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 (35)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The declared purpose does not match the documented behavior: it mentions monitoring bioRxiv/medRxiv and academic discussions, but the skill actually uses arXiv as a primary source, stores historical data locally, and does not clearly implement discussion-source monitoring. Behavior mismatches are dangerous because reviewers and users may approve or invoke the skill under false assumptions about what data it accesses, persists, or transmits.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code deliberately impersonates a browser to evade simple bot detection, which is not necessary for the stated purpose of consuming research feeds and APIs. This is dangerous because it enables covert scraping against publisher defenses, increases legal/compliance exposure, and makes the skill easier to repurpose for unauthorized large-scale collection from external services.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documents code execution 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 may run the skill with broader capabilities than users expect, increasing the chance of unintended filesystem access or outbound requests.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/README.md (reported line 213)May include surrounding context.

md
4. **Semantic Scholar Open Research Corpus**
   - 200M+ papers
   - Available for download
   - URL: https://api.semanticscholar.org/corpus

---

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest scopes the skill to bioRxiv/medRxiv preprints plus academic discussions, but the code adds an arXiv feed as a selectable source and only fetches preprint/RSS data. There is no code for forums, social platforms, comment systems, or other discussion sources, so the implemented behavior differs materially from the stated scope.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 172)May include surrounding context.

md
BIORXIV_RSS = "https://www.biorxiv.org/rss/recent.rss"
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 220)May include surrounding context.

md
BIORXIV_RSS = "https://www.biorxiv.org/rss/recent.rss"
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/README.md (reported line 20)May include surrounding context.

md
BIORXIV_RSS = "https://www.biorxiv.org/rss/recent.rss"
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/README.md (reported line 39)May include surrounding context.

md
BIORXIV_RSS = "https://www.biorxiv.org/rss/recent.rss"
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main.py (reported line 30)May include surrounding context.

python
BIORXIV_RSS = "https://www.biorxiv.org/rss/recent.rss"
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 177)May include surrounding context.

md
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/README.md (reported line 70)May include surrounding context.

md
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/main.py (reported line 31)May include surrounding context.

python
MEDRXIV_RSS = "https://www.medrxiv.org/rss/recent.rss"
ARXIV_QBIO_RSS = "https://export.arxiv.org/rss/q-bio"  # arXiv Quantitative Biology
BIORXIV_API = "https://api.biorxiv.org/details/biorxiv"
MEDRXIV_API = "https://api.medrxiv.org/details/medrxiv"
DATA_DIR = Path(__file__).parent.parent / "data"
DATA_DIR.mkdir(exist_ok=True)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The explicit comment about using headers to bypass bot detection is a trust and compliance red flag because it signals deliberate evasion of publisher access controls while the tool presents itself as a normal research client elsewhere. In this context, the comment corroborates potentially deceptive scraping behavior and increases the likelihood of policy-violating or unauthorized collection practices.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The natural-language text lists adding "Accept-Language" headers as an attempted solution to access protected sites. This implies use of a specific language/locale signal for operational purposes, but the documentation provides no user opt-in or justification for imposing a locale-related setting.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency list is unpinned, so builds may resolve to different versions over time, reducing reproducibility and increasing supply-chain risk if a newly released package version is vulnerable or malicious. In this specific case, dataclasses is especially unnecessary on modern Python versions because it is part of the standard library in Python 3.7+, which can also create compatibility ambiguity.

Content

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

text
dataclasses
feedparser
requests
textblob

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

feedparser is declared without a version pin, so installations are not reproducible and may pull in a vulnerable or incompatible release. Because the package has a history of security advisories, leaving the version unspecified makes it impossible to verify whether deployments are safe.

Content

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

text
dataclasses
feedparser
requests
textblob

Unverifiable Dependency: feedparser has 10 known advisory(ies) (CVE-2011-1157 (feedparser Cross-site Scripting vulnerability); CVE-2009-5065 (feedparser Cross-site Scripting vulnerability); CVE-2011-1158 (feedparser Cross-site Scripting vulnerability) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
95% confidence
Finding

feedparser has multiple historical advisories, but because no version is pinned, the manifest does not allow verification that a safe release will be installed. In a skill that ingests untrusted external feeds and preprint metadata, this uncertainty is more concerning because parsing attacker-controlled content is part of normal operation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
99% confidence
Finding

requests is unpinned, which creates a supply-chain and reproducibility risk because future installs may silently resolve to versions with known flaws or behavioral changes. Since this skill likely fetches remote content from external academic sources, the networking library is security-relevant and should be tightly controlled.

Content

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

text
dataclasses
feedparser
requests
textblob

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

requests has known advisories, and without version pinning there is no way to confirm that deployments avoid affected releases. Because this skill likely performs outbound HTTP requests to external sources, a vulnerable requests version could expose credentials, weaken transport handling, or otherwise increase risk during normal network operations.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

textblob is also unpinned, so builds may vary over time and unexpectedly consume vulnerable or incompatible releases. While not obviously as security-sensitive as a networking library, it still contributes to supply-chain exposure and operational instability.

Content

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

text
dataclasses
feedparser
requests
textblob

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The request header forces the locale to 'en-US,en', which is a natural-language/locale preference embedded in the skill. The file does not offer the user a language choice or explain why an English locale is required, so this conflicts with the language/locale policy criteria.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
96% confidence
Finding

The dependency is specified with only a lower bound, so builds may resolve to different versions over time. This weakens reproducibility and can unintentionally introduce vulnerable or incompatible releases through normal dependency updates or supply-chain compromise.

Content

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

text
requests>=2.28.0
feedparser>=6.0.10
pandas>=1.5.0
scikit-learn>=1.1.0

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

Requests has multiple known advisories, but the manifest does not specify an exact version, so the deployed package could resolve to a vulnerable release. In a skill that fetches external content from preprint sources, HTTP client issues can matter because they operate on untrusted network input and may expose credentials or weaken transport handling depending on the installed version.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

Using an unpinned feedparser version allows future installs to pull different releases than originally tested. That creates supply-chain and stability risk because a later vulnerable or malicious package version could be installed without code changes.

Content

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

text
requests>=2.28.0
feedparser>=6.0.10
pandas>=1.5.0
scikit-learn>=1.1.0
numpy>=1.23.0

Static analysis

No suspicious patterns detected.