Back to skill

Security audit

ddgs-search

Security checks for vulnerabilities and agentic risk

Overview

This is a disclosed web and arXiv search skill with normal network and install risks, not evidence of hidden or malicious behavior.

Install only if you are comfortable with user-level Python package installation and with your search queries being sent to third-party search providers and arXiv. Avoid using it for secrets, proprietary text, or personal data, and prefer a pinned reviewed ddgs version for reproducible installs.

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

T08 · Insecure Dependencies

Warning
Location
scripts/install.py:42
Finding

Unpinned Third-Party Dependency Installation

Content
View full analysis

Vulnerability Details

File Location: scripts/install.py:42-44
Vulnerability Type: Unpinned third-party package installation
Risk Level: Medium

Vulnerable Code

python
# 2. Install ddgs
print("Installing ddgs CLI...")
pip_install(["ddgs"])

The installation is also documented in SKILL.md:38-41:

bash
### Manual install
```bash
pip install ddgs
text

### Technical Analysis

The installer retrieves and installs `ddgs` without specifying a reviewed version or validating package integrity with cryptographic hashes. Pip therefore resolves whichever compatible release is available from its configured package index at installation time, including transitive dependencies.

This makes installations non-reproducible and allows package contents to change after the skill has been audited. The code invokes pip using an argument array rather than a shell, so no command-injection vulnerability was identified in this path. The risk instead arises from trusting mutable third-party artifacts without version or integrity constraints.

### Attack Path

1. An attacker compromises the `ddgs` package, one of its transitive dependencies, a maintainer account, or the package-distribution channel.
2. The attacker publishes a malicious release that satisfies pip's unconstrained dependency resolution.
3. A user runs `python3 scripts/install.py` as documented.
4. `pip_install(["ddgs"])` downloads the malicious release or dependency.
5. Attacker-controlled code executes during installation or when the installed module or CLI is subsequently invoked.
6. The code runs with the privileges and data access of the user executing the installer or search command.

### Impact Assessment

Successful exploitation could permit arbitrary code execution under the installing user's account. The resulting scope could include access to that user's files, environment variables, network credentials, and other resources available to the Python process.

The code does not req
...[truncated 214 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin ddgs to a specifically reviewed version rather than installing the latest available release:
python
pip_install(["ddgs==REVIEWED_VERSION"])
  1. Maintain dependencies in a lock or requirements file containing cryptographic hashes, and install with hash verification:
bash
python3 -m pip install --require-hashes -r requirements.txt
  1. Pin and hash all transitive dependencies, not only the direct ddgs dependency.

  2. Review dependency updates before changing the lock file, including package provenance, maintainer changes, release contents, and known vulnerabilities.

  3. Use an explicitly trusted package index and avoid configurations that permit dependency confusion through untrusted additional indexes.

  4. Update README.md and SKILL.md so documented installation commands use the same pinned, integrity-verified dependency process.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The code accurately supports one subset of the declared purpose: arXiv API search without API keys. However, the declared description emphasizes a broader primary capability—multi-engine web search via ddgs CLI across several search providers—which is absent from this code. Since the actual code is narrowly scoped to academic paper discovery on arXiv and lacks the advertised web-search engines and ddgs integration, the description does not accurately represent this supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code’s primary behavior is a ddgs CLI web text search wrapper, which aligns with part of the description. However, the description explicitly includes '+ arXiv API search' and suggests use for research paper discovery, but the supplied code contains no arXiv API integration or paper-specific retrieval logic. The code simply invokes ddgs text with a backend argument and reformats results. There is no evidence of additional search providers beyond whatever ddgs itself supports, and no separate implementation for Wikipedia or arXiv. This is a material description-to-behavior mismatch because a named capability (arXiv search) is absent.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
70% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/search.py (reported line 24)May include surrounding context.

python
result = subprocess.run(
            ["ddgs", "text", "-q", query, "-m", str(max_results), "-b", backend, "-o", tmp],
            capture_output=True, text=True, timeout=30,
            env={k: v for k, v in os.environ.items() if k in ("PATH", "HOME", "LANG", "TERM")}
        )

        if os.path.exists(tmp) and os.path.getsize(tmp) > 0:

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises installation and execution of Python scripts and a CLI that perform networked searches, but it does not declare any explicit tool scope or permissions. In an agent ecosystem, undeclared shell, network, environment, and file-write capabilities reduce reviewability and can cause the skill to be invoked with broader powers than users or orchestrators expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The description says to use the skill whenever a user needs web search or when other skills need a search backend, which is broad enough to trigger on many generic requests. Over-broad activation guidance can cause unnecessary invocation of a networked skill, increasing data exposure and the chance that sensitive prompts are sent to external services without a clear need.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill routes user queries to external search engines and the arXiv API but does not warn about that data transfer. In agent settings, users may include confidential, proprietary, or personal information in prompts, and silent transmission to third parties creates a privacy and compliance risk.

Content

No source excerpt is available for this finding.

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 · scripts/install.py (reported line 14)May include surrounding context.

python
def run(cmd, check=True):
    print(f"  → {' '.join(cmd)}")
    return subprocess.run(cmd, check=check, capture_output=True, text=True)


def pip_install(packages):

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

python
tmp = f.name

    try:
        result = subprocess.run(
            ["ddgs", "text", "-q", query, "-m", str(max_results), "-b", backend, "-o", tmp],
            capture_output=True, text=True, timeout=30,
            env={k: v for k, v in os.environ.items() if k in ("PATH", "HOME", "LANG", "TERM")}

Static analysis

No suspicious patterns detected.