Back to skill

Security audit

Privacy-first web search with DuckDuckGo-style bangs (!w, !yt, !gh)

Security checks for vulnerabilities and agentic risk

Overview

This search skill appears purpose-built for SearXNG, but its privacy claims and setup guidance understate that sensitive queries can go to public or plaintext endpoints.

Review this before installing if you plan to use it for sensitive searches. Prefer a self-hosted SearXNG instance, use HTTPS for any non-local endpoint, avoid public instances for confidential queries, and pin the SearXNG container image to a reviewed digest or version.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search.py:104
Finding

Remote Search Queries Can Be Transmitted Over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: scripts/search.py:16, scripts/search.py:104-124; related insecure configuration examples in SKILL.md:125-129, README.md:27-30, and INSTALL.md:85-90
Vulnerability Type: Plaintext transmission of potentially sensitive search queries
Risk Level: Medium

Vulnerable Code

python
# Default to localhost, override with SEARXNG_URL environment variable
SEARXNG_URL = os.environ.get('SEARXNG_URL', 'http://127.0.0.1:8080')
python
params = {
    'q': query,
    'language': language
}

if categories:
    params['categories'] = categories
if engines:
    params['engines'] = engines

url = f"{SEARXNG_URL}/search?{urllib.parse.urlencode(params)}"

try:
    headers = {
        'User-Agent': 'Mozilla/5.0 (OpenClaw Agent)',
        'Accept': 'text/html'
    }
    
    req = urllib.request.Request(url, headers=headers)
    
    with urllib.request.urlopen(req, timeout=15) as response:

The documentation explicitly permits a remote plaintext endpoint:

bash
export SEARXNG_URL=http://your-searxng-instance.com
python3 scripts/search.py "query"

Technical Analysis

Sending a search query to a SearXNG instance is necessary for the Skill's declared search functionality. However, accepting arbitrary remote http:// endpoints is not necessary and conflicts with the Skill's privacy-focused claims.

The query, language, categories, engines, and optional bang are URL-encoded into a GET request. When the configured endpoint uses HTTP, neither confidentiality nor transport integrity is provided. Network intermediaries can inspect or modify the request and response. Because the search terms are placed in the URL, they may also be retained in server, reverse-proxy, gateway, or monitoring logs.

The script does not validate the URL scheme or distinguish loopback endpoints from remote endpoints. It therefore silently accepts inse ...[truncated 1452 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse SEARXNG_URL with urllib.parse.urlparse before constructing requests.
  2. Require HTTPS whenever the destination is not a loopback address.
  3. Permit HTTP only for explicitly recognized loopback hosts such as 127.0.0.1, ::1, and localhost.
  4. Reject unsupported schemes, missing hostnames, URL fragments, and URLs containing embedded credentials.
  5. Normalize the base URL before appending /search to avoid ambiguous URL construction.
  6. Clearly document that a public SearXNG instance receives the user's queries and must be trusted.
  7. Prefer POST requests where supported to reduce query exposure in URL logs, while recognizing that HTTPS remains necessary.
  8. Preserve TLS certificate verification and do not add options that disable hostname or certificate validation.
  9. Consider requiring an explicit opt-in flag before allowing connections to public or non-loopback instances.

T08 · Insecure Dependencies

Note
Location
INSTALL.md:23
Finding

SearXNG Container Dependency Is Not Pinned to an Immutable Version

Content
View full analysis

Vulnerability Details

File Location: INSTALL.md:23-25, INSTALL.md:35-46; equivalent unpinned installation commands in README.md:16-19 and CLAWHUB.md:69-74
Vulnerability Type: Mutable and unverified third-party container dependency
Risk Level: Low

Vulnerable Configuration

bash
docker run -d -p 8080:8080 --name searxng searxng/searxng
yaml
services:
  searxng:
    image: searxng/searxng:latest
    container_name: searxng
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./config:/etc/searxng
      - ./data:/var/cache/searxng

Technical Analysis

The installation instructions use either an implicit default tag or the mutable latest tag. A mutable tag can resolve to different image contents over time, so two installations following the same audited instructions may execute different code.

No malicious package or intentionally deceptive dependency was identified in the project. The image name is consistent with the declared SearXNG software. The issue is the absence of an immutable release version and digest, which weakens reproducibility and supply-chain verification.

Because the SearXNG container receives every search query and makes outbound requests to search engines, compromise of that dependency would place sensitive query data and returned results under attacker control.

Attack Path

  1. The user follows the documented Docker installation command.
  2. Docker resolves searxng/searxng or searxng/searxng:latest at installation or update time.
  3. The mutable upstream tag changes, an upstream account or build pipeline is compromised, or an unintended release is published under the tag.
  4. A subsequent pull retrieves image contents different from those originally reviewed.
  5. The altered container starts and receives all queries submitted by scripts/search.py.
  6. Malicious container code can record or forward searches ...[truncated 846 chars]
Remediation
View remediation

Remediation Suggestions

  1. Select a reviewed, stable SearXNG release instead of using latest or an implicit tag.
  2. Pin the image by immutable digest, for example searxng/searxng@sha256:....
  3. Record the corresponding release version and digest in all installation documents.
  4. Verify image provenance or signatures when supported by the publisher.
  5. Use an explicit update process that reviews release notes, verifies the new digest, and tests the image before deployment.
  6. Apply container hardening such as a read-only root filesystem, dropped Linux capabilities, resource limits, and a non-root runtime where compatible.
  7. Restrict outbound network access to destinations required by SearXNG and limit write access to only the necessary configuration and cache directories.
  8. Keep installation examples synchronized across INSTALL.md, README.md, and CLAWHUB.md so insecure commands are not retained in secondary documentation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

Tainted flow: 'req' from os.environ.get (line 122, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
93% confidence
Finding

The request target is derived from the SEARXNG_URL environment variable with no validation, allowing an attacker who can influence the runtime environment to redirect requests to arbitrary internal or external endpoints. In an agent context this creates SSRF risk, because the skill will issue HTTP requests and include user query data to the attacker-chosen destination; the default use of plain HTTP also increases exposure to interception or tampering.

Content

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

python
req = urllib.request.Request(url, headers=headers)
        
        with urllib.request.urlopen(req, timeout=15) as response:
            html = response.read().decode('utf-8')
            
            # Parse HTML

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill makes strong privacy claims that are not enforced by the documented implementation, including randomized fingerprints and guaranteed masking from downstream profiling. Users may rely on these assurances for sensitive searches, but the actual behavior depends on the external SearXNG instance and even defaults to plain HTTP locally, which can undermine confidentiality and mislead users into unsafe use.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The installation instructions reference the Docker image searxng/searxng without a fixed tag or digest, so deployments may pull a different image over time. This creates a supply-chain and reproducibility risk: a future upstream change or compromised latest image could alter behavior or introduce malicious code into environments that follow the documentation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The installation instructions use an unpinned container image in a docker run example, which causes Docker to pull whatever image is currently published under that tag. This creates a supply-chain risk: a compromised upstream image, unexpected breaking change, or malicious retagging could lead users to run unreviewed code during installation.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · INSTALL.md (reported line 64)May include surrounding context.

bash
# On the host:
sudo cp -r /path/to/searxng-bangs /app/skills/

# Or if OpenClaw is running in Docker:
docker cp searxng-bangs/ <container-name>:/app/skills/

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The README instructs users to run a Docker image by name only (searxng/searxng) without a pinned tag or digest, which makes the installation non-reproducible and exposes users to supply-chain risk if a newer, compromised, or unexpected image is served later. In a security/privacy-focused skill, this is more concerning because users are likely to trust the setup for sensitive searches, so a malicious or altered container could undermine both host integrity and privacy expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README recommends using public SearXNG instances but does not clearly warn that all search queries, metadata, and potentially sensitive research terms will be sent to a third-party server operator. Because this skill is explicitly marketed as privacy-first, the omission can mislead users into disclosing sensitive queries to an untrusted public instance, making the context more dangerous than a generic search tool.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill documents executable behaviors that use environment configuration and make network requests, but it does not declare any tool scope or permissions boundary. This creates a transparency and governance gap: users or orchestrators may invoke a skill without realizing it can exfiltrate queries to remote services or read environment-provided configuration.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The quick-start guidance encourages immediate use without clearly warning that search queries are transmitted to a SearXNG instance and may then be forwarded to third-party search engines. In a privacy-oriented skill, omission of this data-flow warning can cause users to submit secrets, internal project names, or regulated data under a false sense of safety.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The documentation recommends public community-run instances without a strong trust warning, even though those operators can observe queries and metadata and may have different logging or security practices. Because the skill is explicitly marketed as privacy-respecting, this context makes understated trust risks more dangerous by encouraging sensitive use through untrusted intermediaries.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation emphasizes privacy benefits and mentions public/custom instances, but it does not clearly warn that queries may still transit a chosen SearXNG server and be forwarded to downstream search engines. This can mislead users into believing searches are fully local or anonymous, causing unintended disclosure of sensitive search terms to third-party infrastructure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The bang documentation explains how to route queries to specific engines such as Google, YouTube, GitHub, and Amazon, but it omits a clear warning that using bangs can intentionally send the query to those external services. In a privacy-focused skill, this omission is especially risky because users may assume the same privacy posture applies even when bangs direct searches to third-party platforms with their own tracking and logging.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The function signature hard-codes language="en", which establishes English as the default locale behavior without asking the user to choose or opt in. The policy allows locale constraints when users are offered a language choice or when the constraint is clearly justified, neither of which is expressed here as a documented policy justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The command-line path initializes language = "en", causing the script to force English unless the user manually overrides it with --lang. This is a natural-language locale policy concern because the script imposes a specific language by default rather than explicitly requesting or negotiating the user's preference.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The usage examples specifically highlight a German search via --lang de, which can be read as promoting a particular locale preference in the skill's natural-language guidance. Because the document does not explain whether language is user-selectable by default or why German is singled out, this may conflict with language/locale neutrality expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code sends the user's search query to the configured SearXNG instance over HTTP(S), but there is no user-facing notice at execution time about the outbound network request or the fact that query contents are transmitted to an external service. For code files, network calls that transmit user data should have some visible disclosure unless the warning appears elsewhere in skill documentation, which is not present in this file.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.