Back to skill

Security audit

searxng-web-search

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent SearXNG search wrapper, but its setup examples can expose a persistent search service with weak secrets and unpinned dependencies.

Review before installing. If you use this skill, bind SearXNG to `127.0.0.1`, avoid exposing port 8080 to untrusted networks, enable rate limiting or put it behind authenticated access, generate a real unique secret key, pin the Docker image and dependencies, and avoid sending secrets or private data as search queries.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
references/REFERENCE.md:7
Finding
Predictable SearXNG Secret Caused by Quoted Heredoc<![CDATA[ ## Vulnerability Details **File Location**: `references/REFERENCE.md`, lines 7-25 **Vulnerability Type**: Predictable cryptographic secret **Risk Level**: High ### Vulnerable Code ```bash cat > searxng/settings.yml << 'EOF' use_default_settings: true server: secret_key: "$(openssl rand -hex 32)" bind_address: "0.0.0.0" port: 8080 limiter: false image_proxy: true search: safe_search: 0 default_lang: "all" formats: - html - json EOF ``` ### Technical Analysis The heredoc delimiter is single-quoted (`<< 'EOF'`), which disables shell expansion throughout the heredoc. Consequently, `$(openssl rand -hex 32)` is not executed. The generated `settings.yml` contains the literal, publicly documented value: ```yaml secret_key: "$(openssl rand -hex 32)" ``` This results in every deployment following these instructions receiving the same predictable secret rather than a cryptographically random value. Security controls that depend on the SearXNG server secret may therefore operate with a known key. ### Attack Path 1. An administrator follows the documented quick-deployment procedure. 2. The quoted heredoc writes the literal command substitution into `settings.yml`. 3. The SearXNG container starts with the predictable, publicly known secret. 4. An attacker who can reach the instance identifies that it was deployed using this guide. 5. The attacker uses knowledge of the secret when targeting server functionality whose integrity depends on that key. The exact exploitable server operations depend on the installed SearXNG version and how it uses `server.secret_key`, but the secret cannot be treated as confidential or deployment-specific. ### Impact Assessment The issue does not directly grant host or container privileges. It weakens application-level trust boundaries by deploying a known server secret. Potentially affected scope includes sessions, signed values, request-integrity controls, or other SearXNG features that derive securit ...[truncated 26 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Generate the secret before constructing the configuration and interpolate only that generated value: ```bash SECRET_KEY="$(openssl rand -hex 32)" test -n "$SECRET_KEY" || { echo "Failed to generate SearXNG secret" >&2 exit 1 } cat > searxng/settings.yml << EOF use_default_settings: true server: secret_key: "$SECRET_KEY" bind_address: "0.0.0.0" port: 8080 limiter: true image_proxy: true search: safe_search: 0 default_lang: "all" formats: - html - json EOF ``` Alternatively, retain a quoted heredoc with a conspicuous placeholder and add a separate, validated replacement operation. The deployment procedure should fail if the resulting value is empty, unchanged, or equal to a documented placeholder. Restrict the resulting configuration file to the service owner where supported. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/REFERENCE.md:14
Finding
Unrestricted SearXNG Service Exposed on All Host Interfaces<![CDATA[ ## Vulnerability Details **File Location**: `references/REFERENCE.md`, lines 14-30 **Additional Locations**: `assets/settings.example.yml:16-21`, `README.md:43-44`, `SKILL.md:145-147` **Vulnerability Type**: Excessive network exposure and disabled abuse controls **Risk Level**: High ### Vulnerable Code ```yaml bind_address: "0.0.0.0" port: 8080 limiter: false image_proxy: true ``` ```bash docker run -d --name searxng \ -p 8080:8080 \ -v "$(pwd)/searxng:/etc/searxng" \ --restart unless-stopped \ searxng/searxng:latest ``` The example configuration repeats the same unsafe defaults: ```yaml # For private/agent use, bind to localhost and reverse-proxy bind_address: "0.0.0.0" # Disable rate limiter for private instances used by agents. # For public instances, set to true and configure limiter.toml. limiter: false ``` ### Technical Analysis Docker's `-p 8080:8080` syntax publishes the service on all host interfaces by default. The SearXNG process is also configured to listen on `0.0.0.0`, and its request limiter is disabled. This combination creates a remotely reachable, unrestricted metasearch endpoint whenever the host firewall or surrounding network permits access. A local agent only requires access through loopback or another explicitly trusted network path, so exposure on every interface exceeds the minimum network scope required by the declared functionality. The comment in `assets/settings.example.yml` says to bind to localhost while the actual value is `0.0.0.0`, increasing the chance that users misunderstand the effective exposure. ### Attack Path 1. An administrator runs the documented Docker command on a workstation, server, or cloud host. 2. Docker publishes TCP port 8080 on all available host interfaces. 3. The SearXNG JSON API accepts requests without the rate limiter. 4. A remote party discovers or is otherwise able to reach port 8080. 5. The party submits repeated or automated searches through the instance. 6. The requ ...[truncated 952 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Publish the service exclusively on loopback for local-agent use: ```bash docker run -d --name searxng \ -p 127.0.0.1:8080:8080 \ -v "$(pwd)/searxng:/etc/searxng:ro" \ --restart unless-stopped \ searxng/searxng:<reviewed-version> ``` Additional hardening measures: 1. Enable the SearXNG limiter by default: ```yaml server: limiter: true ``` 2. If remote access is necessary, place the service behind an authenticated TLS reverse proxy and permit only trusted clients or networks. 3. Apply host firewall rules that deny unsolicited access to port 8080. 4. Correct the misleading localhost comment or change the value and deployment architecture so that it is accurate. 5. Document that disabling the limiter is appropriate only when another trusted access-control and rate-limiting layer exists. 6. Avoid exposing `/config` and the JSON API to untrusted networks where the deployment does not require them. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
assets/settings.example.yml:2
Finding
Copy-Ready Configuration Contains a Fixed Placeholder Secret<![CDATA[ ## Vulnerability Details **File Location**: `assets/settings.example.yml`, lines 2-21 **Vulnerability Type**: Hardcoded default secret **Risk Level**: Medium ### Vulnerable Code ```yaml # Copy this file to your SearXNG config directory: # cp settings.example.yml /etc/searxng/settings.yml # # IMPORTANT: The "json" format MUST be listed under search.formats # for the API to work. Without it, requests with format=json return 403. use_default_settings: true server: # Generate a unique secret key for your instance: # openssl rand -hex 32 secret_key: "CHANGE_ME_TO_A_RANDOM_STRING" # For private/agent use, bind to localhost and reverse-proxy bind_address: "0.0.0.0" # Disable rate limiter for private instances used by agents. # For public instances, set to true and configure limiter.toml. limiter: false ``` ### Technical Analysis The example explicitly instructs users to copy the file into the active SearXNG configuration directory, but the file contains a fixed and publicly known secret. The accompanying comment recommends generating a secret but does not enforce replacement. Configuration placeholders commonly reach production when copy-and-run instructions are followed literally. SearXNG may then start with `CHANGE_ME_TO_A_RANDOM_STRING` as its actual server secret. ### Attack Path 1. An administrator copies `settings.example.yml` as instructed. 2. The administrator overlooks the comment or assumes the placeholder is acceptable for a local deployment. 3. The service starts with the publicly documented secret. 4. The deployment later becomes reachable through Docker port publishing, a reverse proxy, or a network configuration change. 5. An attacker who recognizes the example configuration knows the application secret and targets functionality that relies on it. ### Impact Assessment The issue does not directly provide operating-system privileges. It removes the confidentiality and uniqueness expected from the application se ...[truncated 190 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not ship a copy-ready active value for a security-sensitive secret. Use a deployment-time environment variable or configuration-generation step, for example: ```yaml server: secret_key: "${SEARXNG_SECRET_KEY}" ``` The installation process should: 1. Generate at least 32 random bytes using a cryptographically secure generator. 2. Insert the generated value without writing it to logs. 3. Reject startup when the value is empty, unchanged, or equal to `CHANGE_ME_TO_A_RANDOM_STRING`. 4. Document secure file permissions for the generated configuration. 5. Clearly separate templates from deployable configuration files. 6. Add an automated deployment check that detects known placeholder values. ]]>

T08 · Insecure Dependencies

Warning
Location
README.md:23
Finding
Mutable and Unpinned Third-Party Dependencies<![CDATA[ ## Vulnerability Details **File Location**: `README.md`, lines 23-52 **Additional Locations**: `SKILL.md:145-147`, `references/REFERENCE.md:27-31,37` **Vulnerability Type**: Unpinned package and container dependencies **Risk Level**: Medium ### Vulnerable Code ```bash npm i -g clawhub clawhub install searxng-web-search ``` ```bash docker run -d --name searxng -p 8080:8080 \ -v "$(pwd)/searxng:/etc/searxng" searxng/searxng:latest ``` ```bash pip install requests ``` The reference deployment also uses a mutable image: ```bash docker run -d --name searxng \ -p 8080:8080 \ -v "$(pwd)/searxng:/etc/searxng" \ --restart unless-stopped \ searxng/searxng:latest ``` ### Technical Analysis The installation instructions do not constrain npm or Python dependencies to reviewed versions, while the SearXNG container uses the mutable `latest` tag. The effective code installed by these commands can therefore change after this Skill has been audited. The named sources appear to be conventional registries and the documented SearXNG image; the audit found no evidence of typosquatting, dependency confusion, or an intentionally malicious package. The risk arises from non-reproducible installation and future upstream compromise or incompatible updates. ### Attack Path 1. A user follows the installation instructions after the project audit. 2. The package registry resolves `clawhub` or `requests` to whatever release is current at that time, or the container registry resolves `latest` to a changed image. 3. A compromised, malicious, or incompatible release is downloaded. 4. Package installation hooks may execute with the invoking user's privileges; a global npm installation may have elevated privileges depending on local configuration. 5. A changed container image executes through Docker with its configured bind mount and network access. This path depends on an upstream compromise or unsafe future release; no currently malicious dependency was identifi ...[truncated 834 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Pin every executable dependency to a reviewed version: ```bash npm install --global clawhub@<reviewed-version> python -m pip install "requests==<reviewed-version>" ``` Pin the container by both version and immutable digest: ```bash docker pull searxng/searxng:<reviewed-version>@sha256:<reviewed-digest> docker run ... searxng/searxng:<reviewed-version>@sha256:<reviewed-digest> ``` Further hardening should include: 1. Add a Python requirements or lock file with hashes. 2. Record the reviewed npm package version and integrity metadata. 3. Use an automated dependency-update process that tests and reviews version changes. 4. Verify container signatures or provenance where supported. 5. Avoid administrative installation privileges unless required. 6. Document a controlled upgrade procedure rather than instructing users to consume `latest`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

External Script Fetching

High
Category
Supply Chain
Content
```bash
# Should return JSON results (not HTML or 403)
curl -s 'http://localhost:8080/search?q=test&format=json' | python3 -m json.tool | head -20
```

If you get 403 Forbidden, JSON format is not enabled in `settings.yml`.
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill clearly requires network access and reads configuration from environment variables, but it does not declare any tool scope, permissions, or allowed-tools boundary in the manifest. That omission weakens least-privilege controls and makes it easier for a hosting agent platform to invoke the skill without clear operator awareness of its external connectivity and env usage.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The description uses very broad triggers such as 'search the web', 'research a topic', and 'gather external context', which can cause overly eager invocation. In an agent setting, this increases the chance that sensitive prompts or user data are sent externally when a local answer would have sufficed.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill documentation does not prominently warn that user queries are transmitted over the network to a SearXNG instance, potentially self-hosted or remote. Without that disclosure, users and operators may unknowingly expose sensitive prompts, search terms, or internal context to external infrastructure and logs.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding
The quick-start command pulls `searxng/searxng:latest`, which is mutable and can change over time. This creates supply-chain and reproducibility risk because users may run an unexpected image version, including one with newly introduced vulnerabilities or malicious compromise if the registry artifact is ever replaced.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The example configuration claims private or localhost-only binding, but sets bind_address to 0.0.0.0, which exposes the SearXNG service on all network interfaces. In the context of an agent-facing search API with rate limiting disabled and JSON API enabled, this increases the chance of unintended external access, abuse, or information leakage if deployed as copied.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The example binds SearXNG to `0.0.0.0`, exposing the service on all network interfaces, and the docs do not warn users that this may make the instance reachable from other hosts. In a self-hosted search service, unintended exposure can enable unauthorized access, metadata leakage, and abuse of the instance as an open proxy-like search endpoint.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

Missing User Warnings

Low
Confidence
93% confidence
Finding
The README describes a web search capability but does not clearly warn that user prompts and search queries are sent over the network to the configured SearXNG instance, and may then be forwarded by that instance to upstream search engines. In an agent context, users may assume local processing, so missing disclosure can cause unintended transmission of sensitive prompts, credentials, proprietary code fragments, or personal data.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The sample settings set `safe_search: 0`, which explicitly turns off search-result filtering, but the document does not warn users that this may return unrestricted or inappropriate content. In markdown guidance, omitting that disclosure can leave users unaware of the behavior change.

Static analysis

No suspicious patterns detected.