Back to skill

Security audit

Web Search

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward DuckDuckGo web-search skill with expected network use and optional file export, but users should be careful with unpinned installation and output paths.

Install in a virtual environment, consider pinning duckduckgo-search to a reviewed version, do not search for secrets or confidential data, and use --output only with ordinary workspace result files that you are willing to create or replace.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:20
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:20
Vulnerability Type: Supply-chain exposure through an unpinned dependency
Risk Level: Medium

Vulnerable Code

bash
pip install duckduckgo-search

The installed package is subsequently imported by scripts/search.py:

python
try:
    from duckduckgo_search import DDGS
except ImportError as e:
    print(f"Error: Missing required dependency: {e}", file=sys.stderr)
    print("Install with: pip install duckduckgo-search", file=sys.stderr)
    sys.exit(1)

Technical Analysis

The installation instruction retrieves the latest available release of duckduckgo-search without a fixed version, lockfile, package hash, or other integrity control. Consequently, the code reviewed during this audit does not fully determine the code that will execute when the Skill is installed or invoked.

Python packages can execute code during installation or when imported. If the upstream package, its publishing account, or the configured Python package index is compromised, a malicious release could execute under the privileges of the user installing or running the Skill. Ordinary upstream changes could also introduce incompatible or vulnerable behavior without any corresponding change to this repository.

This finding does not establish that the current duckduckgo-search package is malicious; it identifies an avoidable supply-chain trust weakness.

Attack Path

  1. An attacker compromises the upstream package, its publisher account, or a package source used by the victim.
  2. The attacker publishes a malicious release under the expected package name.
  3. A user follows the documented pip install duckduckgo-search instruction.
  4. Because no version or hash is specified, the package resolver downloads the attacker-controlled release.
  5. Malicious code executes during installation or when scripts/search.py imports duckduckgo_search.
  6. The pa ...[truncated 547 chars]
Remediation
View remediation

Remediation Suggestions

  • Pin the dependency to a reviewed, exact version, for example through a version-locked requirements file.
  • Generate and verify cryptographic hashes, such as with pip install --require-hashes -r requirements.txt.
  • Maintain a lockfile and review dependency updates before adoption.
  • Install dependencies in an isolated virtual environment using a nonprivileged account.
  • Document the supported package version and test compatibility against that version.
  • Use automated dependency vulnerability and provenance scanning in the release process.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search.py:558
Finding

Unrestricted Output Path Can Overwrite Arbitrary Writable Files

Content
View full analysis

Vulnerability Details

File Location: scripts/search.py:558-560
Vulnerability Type: Unrestricted filesystem write and silent file replacement
Risk Level: Medium

Vulnerable Code

python
if args.output:
    output_path = Path(args.output)
    output_path.parent.mkdir(parents=True, exist_ok=True)
    output_path.write_text(output, encoding='utf-8')
    print(f"✓ Results saved to {args.output}", file=sys.stderr)
    print(f"  Found {len(results)} result(s)", file=sys.stderr)
else:
    print(output)
    print(f"\nFound {len(results)} result(s)", file=sys.stderr)

Technical Analysis

The value supplied through --output is converted directly into a filesystem path. The program then creates any missing parent directories and writes the formatted search results without restricting the destination, checking whether the target already exists, or requesting overwrite confirmation.

Path.write_text() opens an existing target for replacement, truncating its prior contents. Absolute paths and traversal-containing relative paths are accepted. The operation remains constrained by the operating-system permissions of the invoking user, but any file writable by that user may be replaced.

If an agent constructs this command from untrusted instructions, an attacker can select a sensitive writable destination rather than a normal results file. Search-result content is externally sourced, which may also permit attacker-influenced text to be written into the selected file.

Attack Path

  1. An attacker supplies instructions or input that causes the Skill to use a sensitive path as the --output value.
  2. The agent invokes the script with that path, such as an existing user configuration or project file.
  3. The script accepts the path without validation or confirmation.
  4. Missing parent directories are created where permissions allow.
  5. write_text() truncates and replaces the target with format ...[truncated 626 chars]
Remediation
View remediation

Remediation Suggestions

  • Resolve the requested path with Path.resolve() and restrict output to a designated results directory.
  • Reject absolute paths and paths that escape the approved directory.
  • Refuse to replace existing files by default, using exclusive creation mode.
  • Add an explicit --force option if replacement is required and clearly warn before overwriting.
  • Avoid automatically creating arbitrary parent-directory trees unless that behavior is explicitly requested.
  • Where symbolic links are a concern, reject symlink targets and perform race-resistant file creation.
  • Use a secure implementation similar to:
python
base_dir = Path.cwd().joinpath("results").resolve()
requested = Path(args.output)

if requested.is_absolute():
    raise ValueError("Absolute output paths are not allowed")

output_path = base_dir.joinpath(requested).resolve()
if base_dir not in output_path.parents:
    raise ValueError("Output path escapes the results directory")

output_path.parent.mkdir(parents=True, exist_ok=True)
with output_path.open("x", encoding="utf-8") as handle:
    handle.write(output)
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents the ability to write arbitrary output files via the --output option, but it does not declare any explicit tool scope or permissions boundaries. In an agent setting, undocumented file-write capability can lead to unintended local persistence, overwriting files, or writing sensitive externally sourced content into unsafe locations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill sends user queries and retrieves results from DuckDuckGo, but the documentation does not warn that prompts, search terms, and related metadata are transmitted to an external service. Users may unintentionally disclose sensitive or regulated information because they are not informed that their data leaves the local environment.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script accepts a user-controlled --output path and writes search results to that path, creating parent directories as needed. For a skill whose stated purpose is only to perform web search and return formatted results, this is an unnecessary filesystem side effect that can overwrite or plant files in arbitrary locations accessible to the process.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code performs local filesystem writes using Path(args.output), mkdir(parents=True, exist_ok=True), and write_text() on an untrusted path. This enables arbitrary file creation or overwrite within the agent's permissions, which expands the skill from web search into local state modification without clear justification from the declared functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill encourages saving search results to local files but does not warn users that externally sourced content and possibly sensitive queries may persist on disk. This increases the risk of accidental retention, later disclosure, or ingestion by other tools that monitor or process local files.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.