Back to skill

Security audit

Headless Brave Browser

Security checks for vulnerabilities and agentic risk

Overview

The skill does provide Brave web search and page extraction, but it can fetch arbitrary HTTP/HTTPS URLs from the user's network environment and lacks strong response-size limits.

Review before installing if you run agents on a network with internal web services. Use this skill in a network-isolated environment or with egress controls, avoid feeding it untrusted/private URLs, be cautious with --content, and update or review the dependency lockfile before use.

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/utils.js:136
Finding

Unrestricted HTTP Fetching Enables Server-Side Request Forgery

Content
View full analysis
_fetchAndExtract(url.toString(), maxLen); ``` ```js async function _fetchAndExtract(url, maxLen) { let html; let finalUrl = url; try { const response = await fetch(url, { headers: { "User-Agent": "Mozilla/5.0 (compatible; BraveSearchBot/2.0; +https://github.com/kelexine)", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate, br", }, signal: AbortSignal.timeout(config.FETCH_TIMEOUT_MS), redirect: "follow", }); ``` ### Technical Analysis The URL validator only restricts the protocol to HTTP or HTTPS. It does not reject destinations resolving to: - IPv4 or IPv6 loopback addresses - RFC1918 private network ranges - Link-local addresses - Internal DNS names - Reserved or special-use address ranges - Cloud metadata and other infrastructure-local addresses Mo ...[truncated 2199 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/content-fetcher.js:86
Finding

Unbounded HTTP Response Buffering Enables Memory and CPU Exhaustion

Content
View full analysis
= 100."); process.exit(1); } ``` ### Technical Analysis The code calls `response.text()`, which buffers the complete decompressed HTTP response in memory before extraction or truncation occurs. It does not: - Enforce a maximum response-body size - Reject an excessive `Content-Length` - Limit bytes while streaming the response - Limit the decompressed representation of compressed responses - Place an upper bound on the `--max-length` argument After buffering the complete response, the code creates a JSDOM document and performs Readability and Markdown conversion. These operations can create additional in-memory representations and consume subs ...[truncated 1500 chars]
Remediation
View remediation
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 (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description presents a complete web search and extraction skill, but the supplied code chunk is only a utility module for bounded concurrency. While bounded concurrency is one supporting feature mentioned in the description, the code lacks the primary behavior of the skill: no network access, no Brave API interaction, no page fetching, no extraction pipeline, and none of the other named resilience/logging/truncation features. Therefore the supplied code does not accurately represent the declared purpose and is a material mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description emphasizes headless web search via the Brave Search API plus content extraction and several resilience/concurrency features. The supplied code chunk is specifically a command-line content extractor for one provided URL. It parses CLI arguments, validates a URL, calls fetchPageContent on that URL, and prints extracted content or JSON. Retry is hinted via the retry: true option, and structured logging is partially consistent, but the core declared purpose of search is absent from this code. There is also no evidence here of Brave Search API integration, circuit breaker behavior, or bounded parallel fetching. This is therefore a material description-behavior mismatch, with the code implementing only a subset focused on URL content extraction.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/search.js "query" # Basic (5 results)

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
93% confidence
Finding

The lockfile pins jsdom's transitive dependency ws to 8.19.0, and the static analysis reports two known advisories affecting that exact version. Because this skill fetches and parses remote web content, any vulnerable WebSocket handling in the dependency chain increases exposure to attacker-controlled input and could enable denial of service or memory disclosure if the vulnerable code path is reachable.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

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

js
async function fetchBraveResults(searchQuery, count) {
	return withRetry(
		async () => breaker.call(async () => {
			const url = new URL("https://api.search.brave.com/res/v1/web/search");
			url.searchParams.set("q",     searchQuery);
			url.searchParams.set("count", String(Math.min(count, 20)));

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The dependency uses a caret version range, which allows npm to install newer compatible releases over time. This can introduce supply-chain risk because future upstream changes or a compromised published version could be pulled into builds without an explicit review, reducing reproducibility and making security posture drift over time.

Content

Scanner excerpt · package.json (reported line 16)May include surrounding context.

json
"content": "./content.js"
	},
	"dependencies": {
		"@mozilla/readability": "^0.6.0",
		"jsdom":                "^27.0.1",
		"turndown":             "^7.2.2",
		"turndown-plugin-gfm":  "^1.0.2"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
93% confidence
Finding

The jsdom dependency is specified with a caret range, so later patch/minor versions may be resolved automatically. In a package that processes remote web content, silent dependency drift is especially relevant because parser and DOM-handling libraries are security-sensitive and can become an attack surface if a bad release or compromised package is consumed.

Content

Scanner excerpt · package.json (reported line 17)May include surrounding context.

json
},
	"dependencies": {
		"@mozilla/readability": "^0.6.0",
		"jsdom":                "^27.0.1",
		"turndown":             "^7.2.2",
		"turndown-plugin-gfm":  "^1.0.2"
	}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
91% confidence
Finding

Using a version range for turndown permits unreviewed upstream updates to enter the build, creating a software supply-chain exposure. While this is not an immediate exploit by itself, it weakens change control and may allow compromised or vulnerable releases to be incorporated unexpectedly.

Content

Scanner excerpt · package.json (reported line 18)May include surrounding context.

json
"dependencies": {
		"@mozilla/readability": "^0.6.0",
		"jsdom":                "^27.0.1",
		"turndown":             "^7.2.2",
		"turndown-plugin-gfm":  "^1.0.2"
	}
}

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
91% confidence
Finding

The turndown-plugin-gfm package is not pinned to an exact version, so future installs may fetch different code than originally tested. This increases supply-chain risk and can undermine reproducibility, especially in automation-oriented skills that may be deployed across multiple environments.

Content

Scanner excerpt · package.json (reported line 19)May include surrounding context.

json
"@mozilla/readability": "^0.6.0",
		"jsdom":                "^27.0.1",
		"turndown":             "^7.2.2",
		"turndown-plugin-gfm":  "^1.0.2"
	}
}

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The request headers hard-code Accept-Language: en-US,en;q=0.9, which imposes a specific language/locale preference for fetched content. This is a natural-language policy concern because the skill does not offer any user choice or documented justification for forcing English.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The help text says --content will fetch and include full page content, but it does not clearly warn that enabling this option triggers additional outbound requests to each search result URL. Because this behavior can contact third-party sites based on user queries, a clearer user-facing disclosure would improve safety transparency.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.