Back to skill

Security audit

Brave Api Search

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate Brave search skill, but its tool manifest builds shell command strings from user input in a way that could allow command injection in some runtimes.

Review this skill before installing. Its Brave API access is purpose-aligned, but install only in a runtime that passes tool arguments safely without shell interpretation, or after the manifest is changed to use structured executable-and-argument invocation. Do not send secrets, regulated data, or confidential internal queries to Brave through this skill unless that is approved for your environment.

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

T09 · Insecure Skill Coding Practices

Error
Location
skill.json:14
Finding
Shell Command Injection Through Unescaped Tool Command Templates## Vulnerability Details **File Location**: `skill.json`, lines 14, 51, 78, and 83 **Vulnerability Type**: Shell command injection through unescaped template interpolation **Risk Level**: High **Classification**: T09: Insecure Skill Coding Practices ### Vulnerable Code ```json "command": "node {{workspace}}/brave_search.js --query \"{{query}}\" --count {{count|10}} --country {{country|us}} --freshness {{freshness|}} --extra-snippets {{extra_snippets|false}} --summary {{summary|false}}", ``` ```json "command": "node {{workspace}}/brave_suggest.js --query \"{{query}}\" --count {{count|5}} --country {{country|US}} --rich {{rich|false}}", ``` ```json "command": "node {{workspace}}/brave_spellcheck.js --query \"{{query}}\" --country {{country|US}}" ``` ```json "command": "node {{workspace}}/brave_answers.js --query \"{{query}}\" --country {{country|us}} --enable-citations {{enable_citations|true}} --enable-research {{enable_research|false}} --enable-entities {{enable_entities|false}} --stream {{stream|true}}", ``` ### Technical Analysis All four tool definitions construct commands by directly interpolating user-controlled values into a command string. The `query` parameter is placed between double quotes, but this does not provide safe shell escaping. An embedded double quote can terminate the intended argument, after which shell operators may introduce an additional command. Other interpolated fields, such as `country`, are also inserted as shell text rather than passed as structured process arguments. Exploitability depends on the Skill runtime invoking the generated command through a shell or equivalent command-string parser. Under that common execution model, a malicious query can alter command structure instead of remaining a single argument. For example, a query shaped like the following could terminate the quoted argument and append another command: ```text "; touch /tmp/skill-injection; # ``` This ...[truncated 1534 chars]
Remediation
## Remediation Suggestions 1. Replace command strings with a structured executable-and-arguments format so the runtime launches Node.js without invoking a shell. For example: ```json { "executable": "node", "arguments": [ "{{workspace}}/brave_search.js", "--query", "{{query}}", "--count", "{{count|10}}", "--country", "{{country|us}}" ] } ``` 2. Configure the runtime to use an API equivalent to `spawn` or `execFile` with `shell: false`, passing each value as a separate argument. 3. Apply the same correction to all four affected tool definitions. Protect every interpolated field, not only `query`. 4. Enforce schema validation before execution: - Restrict `country` to a valid two-letter country code. - Restrict numeric values to documented ranges. - Restrict booleans and enumerated options to expected values. - Preserve queries as opaque string arguments rather than shell fragments. 5. If the platform only supports command strings, use the platform’s documented, context-appropriate shell-escaping facility for every substituted value. Do not rely on surrounding values with double quotes or on custom ad hoc escaping. 6. Add regression tests containing quotes, command substitutions, semicolons, pipes, redirection operators, and newline characters. Verify that these inputs are delivered literally to the JavaScript process and never interpreted as shell syntax. 7. Run the Skill with a restricted environment and filesystem permissions to reduce impact if another command-construction flaw is introduced.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (18)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The description claims a broader multi-capability skill: real-time web search, autosuggest, and AI-powered answers using Brave Search API, with both search and answers API keys required. However, this code chunk is narrowly focused on Brave AI Answers only. It calls the Brave chat/completions endpoint, requires only BRAVE_ANSWERS_API_KEY, and formats streamed/non-streamed answer content, citations, entities, and token/cost usage. There is no code for search result retrieval, no autosuggest endpoint usage, and no handling of BRAVE_SEARCH_API_KEY. This is a material description-to-behavior mismatch because major declared capabilities are absent from the actual code shown.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code clearly matches much of the search-related description: it performs real-time Brave web search, supports current web content queries, and can fetch an AI-generated summary grounded in search results. However, there are material description/behavior mismatches. First, no autosuggest functionality appears anywhere in the code. Second, the description claims AI-powered answers using the official Brave Answers API and says BRAVE_ANSWERS_API_KEY is required, but the code only calls Brave Search endpoints (/web/search and /summarizer/search) and only reads BRAVE_SEARCH_API_KEY. So while the skill is broadly a Brave search tool, the declared capabilities and required credentials overstate or misstate what is actually implemented.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says the skill performs real-time web search, autosuggest, and AI-powered grounded answers. However, the supplied code only performs spellchecking for a query using Brave's spellcheck endpoint and formats correction suggestions. This is a materially different primary purpose from search, autosuggest, or AI answers. While it is still within the broader Brave API ecosystem, the implemented capability is not represented by the description, and the declared required keys also do not match the code's actual accepted key set.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The description presents a broader multi-function skill covering search, autosuggest, and AI answers. This code chunk only covers the autosuggest portion. It queries Brave's suggest endpoint, formats suggestions, and uses short-term caching. There is no code for general web search results retrieval, no answers endpoint usage, and no citation-producing AI response logic. Additionally, the code does not require or use BRAVE_ANSWERS_API_KEY; instead it accepts autosuggest/search API key variables. This is a material description-to-behavior mismatch because the declared primary capabilities significantly exceed what the provided code actually does.

Credential Access

High
Category
Privilege Escalation
Content
Set your Brave API keys in a local `.env` file (recommended):

```bash
# .env (do not commit)
BRAVE_SEARCH_API_KEY=your_key_here
BRAVE_ANSWERS_API_KEY=your_key_here
AUTOSUGGEST_API_KEY=your_key_here   # optional, for autosuggest only
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill declares network and environment-variable capabilities but does not explicitly scope or declare them via permissions/allowed-tools. This weakens reviewability and containment because users and hosting platforms cannot easily tell that the skill will read API keys and transmit queries to an external service.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill handles user queries by sending them to Brave's external APIs, but the description does not prominently warn users that their queries and possibly contextual content leave the local environment. This creates privacy and data-governance risk, especially if users submit sensitive prompts, internal URLs, or proprietary research terms.

External Transmission

Medium
Category
Data Exfiltration
Content
## Security & Packaging Notes

- This skill only calls Brave official endpoints under `https://api.search.brave.com/res/v1`.
- It requires `BRAVE_SEARCH_API_KEY` and `BRAVE_ANSWERS_API_KEY` (keep them in `.env`, not inline in commands/chats).
- Optionally accepts `AUTOSUGGEST_API_KEY` or `BRAVE_AUTOSUGGEST_API_KEY` for autosuggest.
- It does not request persistent/system privileges and does not modify system config.
Confidence
91% confidence
Finding
This skill explicitly transmits data to an external third-party endpoint. External transmission is expected for a search skill, but it remains a real security concern because any user-supplied query, research topic, or contextual text sent through the tool may be exposed to external processing and logging.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
- This skill only calls Brave official endpoints under `https://api.search.brave.com/res/v1`.
- It requires `BRAVE_SEARCH_API_KEY` and `BRAVE_ANSWERS_API_KEY` (keep them in `.env`, not inline in commands/chats).
- Optionally accepts `AUTOSUGGEST_API_KEY` or `BRAVE_AUTOSUGGEST_API_KEY` for autosuggest.
- It does not request persistent/system privileges and does not modify system config.
- All scripts are Node.js 18+ native (no external dependencies).
Confidence
60% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The request payload explicitly sets `language: 'en'`, forcing a specific language/locale for responses. This is a natural-language policy concern because the file provides no user opt-in, override, or documented region-specific justification for restricting output to English.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The fallback request body again sets `language: 'en'`, so both execution paths enforce English responses. Because there is no visible opt-in or locale selection mechanism, this violates the language/locale policy criterion.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
This code sends the user's search query and, when supplied, precise geolocation metadata (lat/long, city, state, country, postal code, timezone) to Brave's external API without any explicit user-facing notice, consent flow, or minimization. In an agent skill context, this can expose sensitive prompts, interests, or location data to a third party unexpectedly, creating privacy and compliance risk even though the transmission is part of the skill's intended functionality.

External Transmission

Medium
Category
Data Exfiltration
Content
// Brave Autosuggest - uses Brave Search API suggest endpoint
// Requires: AUTOSUGGEST_API_KEY, BRAVE_AUTOSUGGEST_API_KEY, or BRAVE_SEARCH_API_KEY env var

const BASE_URL = 'https://api.search.brave.com/res/v1';
const { parseArgs, fetchWithRetry, createCache } = require('./utils');

// Shared cache: key = query+country+rich, TTL = 60s
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
// Brave Autosuggest - uses Brave Search API suggest endpoint
// Requires: AUTOSUGGEST_API_KEY, BRAVE_AUTOSUGGEST_API_KEY, or BRAVE_SEARCH_API_KEY env var

const BASE_URL = 'https://api.search.brave.com/res/v1';
const { parseArgs, fetchWithRetry, createCache } = require('./utils');

// Shared cache: key = query+country+rich, TTL = 60s
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
// Brave Autosuggest - uses Brave Search API suggest endpoint
// Requires: AUTOSUGGEST_API_KEY, BRAVE_AUTOSUGGEST_API_KEY, or BRAVE_SEARCH_API_KEY env var

const BASE_URL = 'https://api.search.brave.com/res/v1';
const { parseArgs, fetchWithRetry, createCache } = require('./utils');

// Shared cache: key = query+country+rich, TTL = 60s
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
// Brave Autosuggest - uses Brave Search API suggest endpoint
// Requires: AUTOSUGGEST_API_KEY, BRAVE_AUTOSUGGEST_API_KEY, or BRAVE_SEARCH_API_KEY env var

const BASE_URL = 'https://api.search.brave.com/res/v1';
const { parseArgs, fetchWithRetry, createCache } = require('./utils');

// Shared cache: key = query+country+rich, TTL = 60s
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Low
Confidence
95% confidence
Finding
The documentation first states that disabling streaming means citations and entity data will not be available, and that non-streaming loses those features. Later, the technical details claim non-streaming mode applies parseCitations() and parseEntities() so citations and entities are extracted even without streaming. These statements actively conflict about the tool's actual behavior.

Missing User Warnings

Low
Confidence
91% confidence
Finding
This code performs an outbound HTTP request containing the user's query parameter and an API credential, but the file provides no user-facing warning or disclosure beyond implementation comments. For code files, network calls that transmit user or system data should have some visible confirmation, logging, or documented warning unless the behavior is clearly disclosed elsewhere.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
brave_spellcheck.js:17