Back to skill

Security audit

Web Research

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent web research CLI, but its install and URL-fetching behavior are broader than users should accept without review.

Review before installing. Prefer running the bundled web_research.py instead of the curl command, avoid passing secrets or internal URLs, restrict use to trusted http/https targets, and run it in a low-privilege environment if used by an agent or CI job.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Warning
Location
SKILL.md:31
Finding

Mutable Remote Python Payload Downloaded Without Integrity Verification

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
web_research.py:32
Finding

Unrestricted URL Fetching Enables Local-File Disclosure and SSRF

Content
View full analysis
str: """GET a URL and return the response body as text.""" req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT}) with urllib.request.urlopen(req, timeout=timeout) as resp: raw = resp.read() # Try UTF-8, fall back to latin-1 try: return raw.decode("utf-8") except UnicodeDecodeError: return raw.decode("latin-1") ``` ```python def cmd_fetch(args: argparse.Namespace) -> None: url = args.url try: html_text = _fetch(url) except Exception as e: print(f"⚠ Failed to fetch {url}: {e}", file=sys.stderr) sys.exit(1) text = _strip_html(html_text) # Show title if we can find it title_match = re.search(r"(.*?)", html_text, re.DOTALL) title = _strip_html(title_match.group(1)) if title_match else url output = args.output if output: with open(output, "w", encoding="utf-8") as f: f.write(text) print(f"✅ Downloaded {url}") print(f" Title: {title}") print(f" Saved to: {output} ({len(text)} chars)") else: print(f"📄 {title}\n") print(text[:3000]) ``` ```python p_fetch.add_argument("url", help="URL to fetch") ``` ### Technical Analysis The `fetch` command passes an unvalidated user-supplied URL directly to `urllib.request.urlopen`. There is no restriction to HTTP or HTTPS, no hostname or IP-address policy, and no redirect destination validation. Python's URL-opening mechanism supports handlers beyond ordinary public web requests, including `file://` resources. HTTP and HTTPS requests can also target loopback, link-local, private, reserved, or otherwise i ...[truncated 2290 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (13)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims citation export but the finding indicates that feature is absent while local file-writing via an output flag exists without declared permissions. Undocumented file writes are risky in agent environments because they can overwrite local files, persist untrusted fetched content, or be chained with other tooling despite users expecting read-only research behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill claims citation export but the finding indicates that feature is absent while local file-writing via an output flag exists without declared permissions. Undocumented file writes are risky in agent environments because they can overwrite local files, persist untrusted fetched content, or be chained with other tooling despite users expecting read-only research behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill claims citation export but the finding indicates that feature is absent while local file-writing via an output flag exists without declared permissions. Undocumented file writes are risky in agent environments because they can overwrite local files, persist untrusted fetched content, or be chained with other tooling despite users expecting read-only research behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README explicitly promotes live web search, Wikipedia lookups, and raw URL fetching, but it does not disclose that user queries and supplied URLs will be transmitted to third-party services and remote hosts. In an agent or CI context, this can cause unintentional disclosure of sensitive prompts, internal URLs, tokens embedded in URLs, or reconnaissance targets, especially when operators assume the tool is a local-only research helper.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
83% confidence
Finding

The skill advertises no explicit tool scope or permissions, yet the associated capability set includes file access, network access, and shell execution. In an agent setting, missing scope declarations can cause users or orchestrators to grant broader access than expected, increasing the chance of unsafe file writes, command execution, or outbound requests without informed consent.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
93% confidence
Finding

This helper executes arbitrary Python files found in the target product folder by invoking them with a self-test argument. In a CI verification harness, that means untrusted repository code can run during validation, enabling remote code execution on the CI runner or analyst machine if a submitted skill includes a malicious script that returns success and prints PASS.

Content

Scanner excerpt · ci/verify_product.py (reported line 37)May include surrounding context.

python
def has_self_test(fp):
    r = subprocess.run([sys.executable, fp, "self-test"], capture_output=True, text=True, timeout=30)
    return r.returncode == 0 and "PASS" in r.stdout

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · ci/verify_product.py (reported line 67)May include surrounding context.

python
all_ok &= axis(False, "frontmatter (no SKILL.md)")
        all_ok &= axis(False, "docs (no SKILL.md)")
    # 3 compiles
    comp_ok = all(subprocess.run([sys.executable, "-m", "py_compile", fp],
                                capture_output=True).returncode == 0 for fp in files)
    all_ok &= axis(comp_ok, "compiles (py_compile all .py)")
    # 4 self-test (any of 3 valid forms)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This path executes any test_*.py or *_test.py file present in the analyzed folder. Since those files come from the untrusted skill under review, a malicious contributor can place arbitrary code in a test file and have it executed automatically during verification, exposing CI secrets, modifying the workspace, or pivoting further into the environment.

Content

Scanner excerpt · ci/verify_product.py (reported line 79)May include surrounding context.

python
tests = [os.path.join(folder, f) for f in os.listdir(folder)
                 if (f.startswith("test_") or f.endswith("_test.py")) and f.endswith(".py")]
        if tests:
            st_ok = all(subprocess.run([sys.executable, t], capture_output=True, text=True,
                                      timeout=30).returncode == 0 for t in tests)
            st_note = f"{len(tests)} test_*.py"
        elif re.search(r"(?im)^test\s*:", skill_txt):

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · ci/verify_product.py (reported line 92)May include surrounding context.

python
# 7 deploy-ready
    ci = os.path.join(os.path.dirname(os.path.abspath(__file__)), "ci_check.py")
    if os.path.isfile(ci) and os.path.isfile(skill):
        r = subprocess.run([sys.executable, ci], cwd=folder, capture_output=True, text=True)
        all_ok &= axis(r.returncode == 0, "deploy-ready (ci/ci_check.py PASS)")
    else:
        all_ok &= axis(True, "deploy-ready (skipped)")

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The search, wiki, and fetch paths send user-provided search terms or URLs to DuckDuckGo, Wikipedia, or arbitrary remote hosts over the network. While network access is core to the tool's purpose, the file does not clearly disclose that user inputs will be transmitted to third-party services, which is a relevant privacy warning for a research utility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code performs a file write when --output is provided, but there is no confirmation prompt or cautionary warning about overwriting or modifying local files. Although the module docstring documents the option, it does not warn the user that invoking fetch --output will persist remote content to disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill supports live URL fetching but does not prominently warn users that it makes outbound network requests to external sites. In agent or CI contexts, this can lead to unintentional data exposure through request metadata, unexpected contact with third-party services, or execution in environments where network access should be tightly controlled.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code always queries en.wikipedia.org, forcing English-language results regardless of user preference or locale. This is a natural-language policy concern because the skill imposes a specific language without opt-in or a documented justification.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.