T09 · Insecure Skill Coding Practices
- Location
content.js:7- Finding
Server-Side Request Forgery Through Unrestricted URL Fetching
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a web search/content extraction skill, but it fetches arbitrary web pages from the agent’s network position without destination safeguards and its Brave API disclosure does not match the implementation.
Install only if you are comfortable with this skill sending searches to Brave and fetching arbitrary pages from the machine running the agent. Avoid using it with secrets, internal URLs, or in environments that can reach private services or cloud metadata endpoints unless outbound network access is sandboxed or filtered.
content.js:7Server-Side Request Forgery Through Unrestricted URL Fetching
Claiming Brave Search API usage while actually scraping Brave HTML results and fetching arbitrary third-party webpages creates a materially different trust and risk profile than described. This can bypass expected API-based controls, rate limits, or contractual boundaries, and exposes the agent to hostile web content under a deceptively narrow description.
Claiming Brave Search API usage while actually scraping Brave HTML results and fetching arbitrary third-party webpages creates a materially different trust and risk profile than described. This can bypass expected API-based controls, rate limits, or contractual boundaries, and exposes the agent to hostile web content under a deceptively narrow description.
Referenced artifact was not completely inspected
./search.js "query" # Basic search (5 results)
Referenced artifact was not completely inspected
./search.js "query" # Basic search (5 results)
Referenced artifact was not completely inspected
./search.js "query" # Basic search (5 results)
Referenced artifact was not completely inspected
./search.js "query" # Basic search (5 results)
The lockfile pins transitive dependency ws to version 8.18.3, and the supplied advisories indicate that this version is affected by an uninitialized memory disclosure and a memory-exhaustion denial of service condition. In the context of a web-search/content-extraction skill using jsdom, ws may be reachable through library behavior even if not directly imported by the skill, so shipping a known vulnerable version increases risk to any environment that processes attacker-controlled network content.
The skill performs network-capable actions but does not declare any explicit tool scope, permissions, or allowed-tools boundaries in its manifest. That omission weakens governance and user awareness, making it easier for an agent to invoke outbound network behavior without clear policy constraints or disclosure.
The skill sends user-supplied queries and URLs to external services and websites, yet the description does not warn users that their inputs may leave the local environment. This creates privacy and data-handling risk, especially if users unknowingly submit secrets, internal URLs, or sensitive research terms.
The skill sends the user's search query to Brave Search and, when --content is used, also fetches third-party pages referenced by search results. In a search skill this behavior is expected, but it still creates a real privacy risk because potentially sensitive user input is transmitted externally without any built-in notice, consent mechanism, or filtering.
The description says to use the skill for "searching documentation, facts, or any web content," which is extremely broad and lacks constraints or exclusion conditions. For a markdown skill description, this kind of open-ended trigger scope can overlap with many ordinary requests and does not clearly define when the skill should or should not be invoked.
The phrase "Any task requiring web search without interactive browsing" is a catch-all activation description rather than a specific trigger boundary. It does not define constraints, exclusions, or concrete invocation criteria, increasing the risk of over-invocation.
The request hard-codes an Accept-Language header of en-US,en;q=0.9, which forces a specific language preference for fetched content. This is a natural-language locale constraint with no user choice or documented justification in the file.
The dependency uses a caret range, which allows automatic installation of newer compatible releases rather than an exact audited version. This creates a supply-chain risk because future upstream releases could introduce vulnerable or malicious code without any change to this repository.
"author": "Mario Zechner",
"license": "MIT",
"dependencies": {
"@mozilla/readability": "^0.6.0",
"jsdom": "^27.0.1",
"turndown": "^7.2.2",
"turndown-plugin-gfm": "^1.0.2"
The jsdom dependency is specified with a caret range, so builds may resolve to different package versions over time. That weakens reproducibility and increases exposure to supply-chain compromise or newly introduced vulnerable transitive code.
"license": "MIT",
"dependencies": {
"@mozilla/readability": "^0.6.0",
"jsdom": "^27.0.1",
"turndown": "^7.2.2",
"turndown-plugin-gfm": "^1.0.2"
}
Using a non-exact semver range for turndown permits unreviewed patch/minor releases to be pulled into the environment. In a skill that processes external web content, dependency integrity matters because parser or conversion libraries are part of the attack surface.
"dependencies": {
"@mozilla/readability": "^0.6.0",
"jsdom": "^27.0.1",
"turndown": "^7.2.2",
"turndown-plugin-gfm": "^1.0.2"
}
}
The turndown-plugin-gfm package is not pinned to a single exact release, allowing dependency drift across installs. This is a real but low-severity supply-chain concern because upstream changes could alter behavior or introduce insecure code unexpectedly.
"@mozilla/readability": "^0.6.0",
"jsdom": "^27.0.1",
"turndown": "^7.2.2",
"turndown-plugin-gfm": "^1.0.2"
}
}
The request header forces "Accept-Language: en-US,en;q=0.9", which imposes a specific language/locale preference regardless of the user's settings or choice. This is a natural-language policy concern because it fixes output behavior to English without any documented opt-in or locale selection mechanism.
No suspicious patterns detected.