Back to skill

Security audit

Academic Paper Search

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent academic search helper, but it can send a SEARCHAPI_API_KEY value to SerpApi, which is a credential-boundary risk users should review before installing.

Review before installing. Use only a SerpApi key with this version, avoid setting SEARCHAPI_API_KEY unless the provider routing is fixed, and rotate any SearchAPI key that may already have been used. Treat all search terms and DOI-enrichment titles as data sent to external services, so avoid confidential, unpublished, regulated, or personally sensitive research topics unless that disclosure is acceptable.

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

Error
Location
scripts/scholar-search.mjs:68
Finding

SearchAPI Credential Disclosed to the SerpApi Endpoint in Scholar Search

Content
View full analysis

Vulnerability Details

File Location: scripts/scholar-search.mjs, lines 68 and 238-248
Vulnerability Type: Cross-provider API credential disclosure
Risk Level: High

Vulnerable Code

js
const apiKey = (process.env.SERPAPI_API_KEY || process.env.SEARCHAPI_API_KEY || '').trim();
js
const u = new URL('https://serpapi.com/search.json');
u.searchParams.set('engine', 'google_scholar');
u.searchParams.set('q', query);
u.searchParams.set('num', String(n));
u.searchParams.set('api_key', apiKey);
u.searchParams.set('hl', lang || 'en');
if (yearFrom) u.searchParams.set('as_ylo', yearFrom);
if (yearTo) u.searchParams.set('as_yhi', yearTo);

let data;
try {
  data = await fetchJson(u, { headers: { 'Accept': 'application/json' } });

Technical Analysis

The script treats SERPAPI_API_KEY and SEARCHAPI_API_KEY as interchangeable credentials, but the request destination is unconditionally fixed to https://serpapi.com/search.json. If only SEARCHAPI_API_KEY is configured, its value is therefore sent to SerpApi rather than to the provider for which it was provisioned.

The credential is also placed in the URL query string. Although HTTPS protects the request in transit, the complete URL is visible to the destination service and may be retained in server access logs, reverse-proxy logs, monitoring systems, or diagnostic records.

Sending a search query and a valid credential to the selected search provider is necessary for the declared Scholar search functionality. Sending a credential associated with a different provider is not necessary and violates least-privilege and credential-boundary principles.

Attack Path

  1. A user follows the Skill documentation and configures SEARCHAPI_API_KEY.
  2. SERPAPI_API_KEY is absent, causing the script to select SEARCHAPI_API_KEY.
  3. The user invokes scholar-search.mjs with an academic search query.
  4. The script inserts the select ...[truncated 1092 chars]
Remediation
View remediation

Remediation Suggestions

  1. Bind every accepted credential variable to its corresponding provider endpoint. Use SERPAPI_API_KEY only with serpapi.com.
  2. If the public edition supports only SerpApi, remove the SEARCHAPI_API_KEY fallback and reject configurations that do not provide SERPAPI_API_KEY.
  3. If both providers must be supported, select an allowlisted endpoint according to the configured credential and implement provider-specific request parameters.
  4. Reject ambiguous configurations rather than silently routing one provider's credential to another provider.
  5. Prefer an authorization header over a URL parameter when the provider supports it. If a query parameter is mandatory, ensure URLs containing credentials are redacted from errors, telemetry, and application logs.
  6. Update SKILL.md and metadata so the documented environment requirements exactly match runtime behavior.
  7. Add automated tests asserting that SEARCHAPI_API_KEY can never be transmitted to serpapi.com, and that each supported credential can reach only an explicitly allowlisted hostname.
  8. Rotate any SEARCHAPI_API_KEY previously used with this implementation if disclosure is considered possible.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/web-search.mjs:41
Finding

SearchAPI Credential Disclosed to the SerpApi Endpoint in Web Search

Content
View full analysis

Vulnerability Details

File Location: scripts/web-search.mjs, lines 41 and 59-66
Vulnerability Type: Cross-provider API credential disclosure
Risk Level: High

Vulnerable Code

js
const apiKey = (process.env.SERPAPI_API_KEY || process.env.SEARCHAPI_API_KEY || '').trim();
js
const u = new URL('https://serpapi.com/search.json');
u.searchParams.set('engine', 'google');
u.searchParams.set('q', query);
u.searchParams.set('num', String(n));
u.searchParams.set('api_key', apiKey);
u.searchParams.set('hl', lang || 'en');

let data;
try {
  data = await fetchJson(u, { headers: { 'Accept': 'application/json' } });

Technical Analysis

The web-search script accepts either SERPAPI_API_KEY or SEARCHAPI_API_KEY, while always transmitting the selected value to https://serpapi.com/search.json. Consequently, a credential loaded from SEARCHAPI_API_KEY crosses its expected provider boundary and is disclosed to SerpApi.

The credential is included as the api_key URL query parameter. HTTPS prevents ordinary network observers from reading it in transit, but it does not prevent the receiving service, reverse proxies, access-log systems, or monitoring infrastructure from recording the full request URL.

Network transmission of a user query and a provider-specific API key is intrinsic to the declared web-search functionality. Transmission of a differently scoped provider credential to a fixed SerpApi hostname exceeds the minimum privileges and data disclosure required to perform that function.

Attack Path

  1. A user configures SEARCHAPI_API_KEY as permitted by the Skill metadata and documentation.
  2. The environment does not contain a nonempty SERPAPI_API_KEY.
  3. The user invokes web-search.mjs.
  4. The script selects the SearchAPI credential and places it in the request URL.
  5. The request is sent to serpapi.com, exposing the foreign credential to that service and its log ...[truncated 784 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove support for SEARCHAPI_API_KEY if all requests are intended to use SerpApi.
  2. Otherwise, implement explicit provider selection and route each credential only to its matching, allowlisted hostname.
  3. Fail securely when the provider and credential type do not match; do not silently use a fallback credential with a fixed endpoint.
  4. Use a request authorization header if supported by the chosen provider. Where URL authentication is unavoidable, redact the api_key parameter from all logging and diagnostics.
  5. Align the Skill metadata and documentation with the actual provider implementation.
  6. Add tests that mock network requests and verify that no SEARCHAPI_API_KEY value can appear in a request to serpapi.com.
  7. Consider separate scripts or provider adapters to make credential-to-endpoint binding explicit and auditable.
  8. Rotate credentials that may already have been transmitted to the unintended endpoint.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Use this skill for **paper-first retrieval**. Prefer `scholar-search.mjs` when the user needs academic literature, candidate references, DOI clues, citation sig

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill is advertised for academic paper and Google Scholar retrieval, but the code hard-codes engine=google, which performs a general web search instead of a scholar-specific search. This can silently return non-scholarly or SEO-manipulated sources, undermining evidence-oriented workflows and causing users or downstream agents to trust irrelevant or lower-quality results as academic evidence.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires environment secrets and performs networked searches, but the manifest does not declare a restrictive tool scope such as explicit permissions or allowed-tools. That creates an authorization and transparency gap: an orchestrator or reviewer may not realize the skill can exfiltrate user queries and use API keys against external services.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The activation text is very broad and can cause the skill to be selected for many generic research or verification requests, increasing unnecessary external data disclosure. Over-broad routing is dangerous here because the skill sends user-provided queries to third-party search providers, so sensitive academic, institutional, or unpublished research topics could be transmitted without a narrowly scoped trigger.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description does not clearly warn that user queries may be sent to SerpApi/SearchAPI and Crossref. This is a real privacy and consent issue because users may provide confidential research ideas, draft titles, or sensitive topics expecting local assistance, while the skill transmits them to external services.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
- DOI enrichment may query the public Crossref API when a DOI is not obvious in the search result.
- This skill is best used as the **front end of a literature workflow**: retrieve → verify → deduplicate → format citations.
- Review/survey detection is heuristic, so verify important claims on the destination page.
- For publication or academic writing tasks, do not treat search output as final truth without checking the destination page.

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 · scripts/scholar-search.mjs (reported line 190)May include surrounding context.

js
const normalizedTitle = normalizeText(title);
  if (!normalizedTitle) return null;

  const u = new URL('https://api.crossref.org/works');
  u.searchParams.set('query.title', title);
  u.searchParams.set('rows', '5');
  u.searchParams.set('select', 'DOI,title,URL,issued,container-title,score');

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The CLI help text describes the tool as generic web search, which conflicts with the skill metadata claiming academic paper discovery. This mismatch increases the risk of operator confusion and misuse, making it more likely that consumers believe the tool is performing scholarly retrieval when it is actually executing broad web searches.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The help text states a default UI language hint of en, and the code later enforces lang = 'en' unless the user explicitly overrides it. This is a natural-language locale policy issue because the skill defaults to a specific language rather than offering a neutral or user-driven default.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.