Back to skill

Security audit

SearXNG (XiaoDing)

Security checks for vulnerabilities and agentic risk

Overview

The search client is purpose-aligned, but the package includes unsafe deployment defaults that can create a persistent host-networked Docker service and replace an existing container without clear user control.

Install only if you intend to route searches through a SearXNG instance you trust. Prefer a local or organization-controlled instance, avoid sensitive searches on public instances, and review or replace run-searxng.sh before using it: remove host networking, avoid --restart always unless you want persistence, pin the container image, generate a unique secret, bind only to localhost, and do not let it replace an existing container without confirmation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
run-searxng.sh:48
Finding
Persistent Overprivileged Container Uses a Mutable Image## Vulnerability Details **File Location**: `run-searxng.sh:48` **Vulnerability Type**: Persistent container deployment, excessive network privileges, and mutable dependency reference **Risk Level**: High **Vulnerable Code**: ```sh docker run --restart always --network host --name searxng -d -e GRANIAN_HOST=127.0.0.1 -v "./config/:/etc/searxng:Z" searxng/searxng:latest ``` ### Technical Analysis The launcher deploys the container with three security-sensitive properties: - `--restart always` causes the service to restart across Docker daemon and host restarts, establishing cross-session persistence. - `--network host` removes Docker network isolation and gives the container direct access to the host network namespace. This is broader access than required for a local search service. - `searxng/searxng:latest` is a mutable image reference. The image that users receive may change after the skill has been reviewed, preventing reproducible deployment and increasing supply-chain exposure. The `GRANIAN_HOST=127.0.0.1` setting does not restore container network isolation. Under host networking, the container still shares the host network namespace and may access network services reachable by the host. ### Attack Path 1. A user executes `run-searxng.sh`. 2. Docker runs whichever image is currently resolved or cached for `searxng/searxng:latest`. 3. If that image or its upstream distribution channel has been compromised, attacker-controlled code starts inside the container. 4. The code receives direct host-network access and can probe services bound to loopback or other host interfaces. 5. The `always` restart policy restarts the container after failures, Docker restarts, or host reboots, preserving execution until the deployment is explicitly removed. ### Impact Assessment A compromised container image could obtain persistent execution in a container with broad network reach. It could enumerate or attack host-local netwo ...[truncated 309 chars]
Remediation
## Remediation Suggestions - Pin the container to a reviewed immutable digest, for example: ```sh searxng/searxng@sha256:<reviewed-digest> ``` - Replace host networking with an isolated Docker network and publish only the required port on loopback: ```sh docker run --name searxng -d \ -p 127.0.0.1:8080:8080 \ -v "./config/:/etc/searxng:Z,ro" \ searxng/searxng@sha256:<reviewed-digest> ``` - Make persistence an explicit user option rather than enabling `--restart always` by default. Prefer `--restart no` or `--restart on-failure` for development deployments. - Run with a non-root user where supported and add hardening flags such as `--read-only`, `--cap-drop=ALL`, `--security-opt=no-new-privileges`, and resource limits. - Verify the image signature and document a controlled image-update process.

T09 · Insecure Skill Coding Practices

Warning
Location
run-searxng.sh:4
Finding
Launcher Unconditionally Stops and Deletes an Existing Container## Vulnerability Details **File Location**: `run-searxng.sh:4-5` **Vulnerability Type**: Destructive container lifecycle handling **Risk Level**: Medium **Vulnerable Code**: ```sh docker stop searxng || true docker rm searxng || true ``` ### Technical Analysis The launcher unconditionally stops and removes any Docker container named `searxng`. It does not verify that the container was created by this project, ask for confirmation, inspect labels, or preserve container-local state. The `|| true` clauses also suppress failures, making destructive behavior less visible and allowing execution to continue in an uncertain state. Container names are host-wide within a Docker daemon. Another deployment or administrator may already use the same name, so name matching alone is not adequate ownership validation. ### Attack Path 1. A host already contains an active container named `searxng`. 2. The container may have been created by another project and may contain unpersisted state. 3. A user runs this project's launcher. 4. The script stops the existing service and deletes its container metadata and writable layer. 5. The script then attempts to replace it with this project's deployment. ### Impact Assessment Exploitation or accidental invocation can cause service interruption and destruction of container-local data. The affected scope is any existing container with the shared name on the Docker daemon accessible to the invoking user. Because Docker access is normally highly privileged, the operation can affect system-wide workloads rather than only files in the project directory.
Remediation
## Remediation Suggestions - Use a project-specific container name that is unlikely to collide with unrelated deployments. - Apply Docker labels when creating the container and verify those labels before stopping or removing it. - Refuse to replace an existing container unless the user supplies an explicit flag such as `--replace`. - Display the existing container identity and request confirmation before destructive operations. - Preserve data in explicitly managed volumes and document what will be deleted. - Remove blanket `|| true` error suppression; handle “container not found” separately from permission, daemon, or runtime failures.

T09 · Insecure Skill Coding Practices

Error
Location
scripts/searxng.py:59
Finding
TLS Certificate Verification Is Disabled for All Search Endpoints## Vulnerability Details **File Location**: `scripts/searxng.py:59-67` **Vulnerability Type**: Improper certificate validation **Risk Level**: High **Vulnerable Code**: ```python # Disable SSL verification for local self-signed certs response = httpx.get( f"{SEARXNG_URL}/search", params=params, timeout=30, verify=False # For local self-signed certs ) response.raise_for_status() ``` ### Technical Analysis Passing `verify=False` disables server certificate validation for every HTTPS endpoint supplied through `SEARXNG_URL`. The behavior is not restricted to loopback addresses or development environments. Consequently, an attacker who can intercept network traffic can present an arbitrary certificate and impersonate the configured SearXNG server. Search queries are sent in URL query parameters. Without certificate authentication, both those queries and returned search data can be exposed or modified. Suppressing related warnings elsewhere in the script further reduces visibility of the insecure connection. ### Attack Path 1. A user configures `SEARXNG_URL` with a remote HTTPS SearXNG instance. 2. An attacker obtains a network interception position, such as a malicious access point, compromised proxy, DNS redirection point, or upstream network device. 3. The attacker redirects the connection to an attacker-controlled HTTPS server and presents an untrusted certificate. 4. The client accepts the certificate because `verify=False` is unconditional. 5. The attacker reads submitted queries and returns modified JSON results. 6. The manipulated titles, URLs, and content are displayed to the user or passed to downstream automation in JSON mode. ### Impact Assessment An attacker can disclose search queries and manipulate the integrity of search results. Modified JSON output may influence downstream scripts or agent decisions, including directing users toward malicious sites. The vulnerability affects ...[truncated 147 chars]
Remediation
## Remediation Suggestions - Enable certificate verification by default: ```python response = httpx.get( f"{SEARXNG_URL}/search", params=params, timeout=30, verify=True, ) ``` - Support self-signed deployments through an explicit CA bundle path rather than disabling validation: ```python verify = os.getenv("SEARXNG_CA_BUNDLE", True) ``` - If an insecure mode is retained, require an explicit command-line flag, emit a prominent warning, and restrict it to loopback endpoints. - Do not suppress TLS verification warnings globally. - Validate that `SEARXNG_URL` uses an expected scheme and document the security consequences of plain HTTP.

T09 · Insecure Skill Coding Practices

Error
Location
config/settings.yml:12
Finding
SearXNG Configuration Uses a Predictable Secret and Unsafe Exposure Defaults## Vulnerability Details **File Location**: `config/settings.yml:12-17` **Vulnerability Type**: Hardcoded secret, unrestricted binding, and disabled rate limiting **Risk Level**: High **Vulnerable Code**: ```yaml server: # CHANGE THIS in production! secret_key: "temporary-key-please-change-me" bind_address: "0.0.0.0" port: 8080 limiter: false # Disable rate limiting for local use public_instance: false ``` The same configuration is also generated by `run-searxng.sh:20-25`: ```yaml server: # CHANGE THIS in production! secret_key: "temporary-key-please-change-me" bind_address: "0.0.0.0" port: 8080 limiter: false # Disable rate limiting for local use public_instance: false ``` ### Technical Analysis The committed and generated configurations use a publicly known static `secret_key`, bind the service to all interfaces, and disable request limiting. A comment asking users to change the secret is not an effective security control. A predictable application secret can undermine any SearXNG behavior that relies on that value for cryptographic integrity. Binding to `0.0.0.0` makes the service listen on every available interface when ordinary bridge networking or direct host execution is used. Disabling the limiter permits unbounded requests. The `public_instance: false` setting describes deployment intent but does not itself implement firewalling or authentication. Although the current launcher also supplies `GRANIAN_HOST=127.0.0.1`, the unsafe configuration remains reusable independently and the script overwrites the checked-in file with these defaults. ### Attack Path 1. A user launches SearXNG with the supplied settings in an environment where port 8080 is reachable. 2. The service listens beyond loopback because of `bind_address: "0.0.0.0"`. 3. A remote attacker discovers the unauthenticated HTML or JSON search endpoint. 4. The attacker submits a high volume of searches ...[truncated 760 chars]
Remediation
## Remediation Suggestions - Generate a unique cryptographically random secret during installation, for example with Python's `secrets.token_urlsafe(64)`. - Store the secret in a restricted environment file or Docker secret rather than committing it to the repository. - Bind to `127.0.0.1` by default and require explicit configuration for external access. - Enable SearXNG's limiter and configure appropriate request thresholds. - Add authentication or place the service behind an authenticated reverse proxy if remote access is required. - Apply host firewall restrictions so only approved clients can reach the service. - Ensure `run-searxng.sh` does not overwrite a secure existing configuration without confirmation. - Add a startup check that rejects known placeholder secrets.

T08 · Insecure Dependencies

Warning
Location
scripts/searxng.py:2
Finding
Python Runtime Dependencies Are Not Version-Pinned## Vulnerability Details **File Location**: `scripts/searxng.py:2-5` **Vulnerability Type**: Unrestricted runtime dependency resolution **Risk Level**: Medium **Vulnerable Code**: ```python # /// script # requires-python = ">=3.11" # dependencies = ["httpx", "rich"] # /// ``` ### Technical Analysis The PEP 723 dependency declarations specify package names without exact versions or integrity hashes. When the documented `uv run` command resolves an environment, it may install dependency releases that did not exist when the skill was audited. This prevents reproducible execution and expands the supply-chain trust boundary to all future releases accepted by the resolver. The package names are legitimate and there is no evidence in the reviewed project that either dependency is currently malicious. The vulnerability is the absence of version and integrity constraints, which permits silently changed dependency code to run in the skill's process. ### Attack Path 1. A future dependency release is compromised, maliciously published, or contains a newly introduced vulnerability. 2. A user executes the skill through `uv run`. 3. The resolver selects the affected release because no exact version is specified. 4. The package is installed and imported by `scripts/searxng.py`. 5. Package initialization code executes with the permissions of the user running the skill. ### Impact Assessment A compromised dependency could execute arbitrary Python code with the invoking user's privileges, access files and environment variables available to that user, alter search results, or make arbitrary network connections. The practical likelihood depends on package-index and upstream compromise, but the impact of successful exploitation could extend to the full user account.
Remediation
## Remediation Suggestions - Pin dependencies to exact reviewed versions: ```python # dependencies = [ # "httpx==<reviewed-version>", # "rich==<reviewed-version>", # ] ``` - Use a committed lockfile with cryptographic hashes when supported by the execution workflow. - Review transitive dependencies and update them through a controlled dependency-update process. - Run automated vulnerability scanning against the resolved dependency graph. - Configure the installer to use the expected official package index and avoid untrusted extra indexes. - Test pinned updates before publishing a new skill version.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
Findings (23)

Tainted flow: 'SEARXNG_URL' from os.getenv (line 23, credential/environment) → httpx.get (network output)

Critical
Category
Data Flow
Content
try:
        # Disable SSL verification for local self-signed certs
        response = httpx.get(
            f"{SEARXNG_URL}/search",
            params=params,
            timeout=30,
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Self-Modification

High
Category
Rogue Agent
Content
1. **Review all files** - Make sure everything is polished
2. **Test one more time** - Fresh installation test
3. **Version bump if needed** - Update SKILL.md, metadata.json, CHANGELOG.md
4. **Git commit** - Clean commit message
5. **Submit to ClawdHub** - Follow ClawdHub submission process
6. **Monitor feedback** - Be ready to address issues
Confidence
85% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
1. **Check your SearXNG instance is running:**
   ```bash
   curl -k $SEARXNG_URL
   # Or: curl -k http://localhost:8080 (default)
   ```
Confidence
60% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The code does not implement a search action itself; it provisions and runs a local SearXNG service via Docker. That is adjacent to the declared purpose, but materially different in primary behavior because it is deployment/infrastructure setup rather than an end-user search skill triggered by phrases like 'search for' or 'look up'. Additionally, the description emphasizes privacy-respecting metasearch without external API dependencies, while the configuration explicitly enables Bing, an external search provider, which weakens that claim and uses external resources. The host-networked Docker service setup is also an undeclared operational capability. Therefore the description does not accurately represent what this code chunk actually does.

Privileged Container / Container Escape

High
Category
Privilege Escalation
Content
EOF


docker run --restart always --network host --name searxng -d -e GRANIAN_HOST=127.0.0.1 -v "./config/:/etc/searxng:Z" searxng/searxng:latest
Confidence
80% confidence
Finding
Potential security issue detected. Manual review is recommended.

Session Persistence

Medium
Category
Rogue Agent
Content
If you make changes later:

1. Update version in SKILL.md and metadata.json
2. Add entry to CHANGELOG.md
3. Run: `clawdhub publish skills/searxng`

### Manage Your Skill
Confidence
80% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

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

Medium
Confidence
93% confidence
Finding
The README mentions public SearXNG instances as an option but does not clearly warn that search queries may be exposed to third-party operators and could reduce the privacy guarantees emphasized elsewhere in the document. In a privacy-focused search skill, this omission is security-relevant because users may assume all usage is private when it is not.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
## SSL/TLS Notes

The skill is configured to work with self-signed certificates (common for local SearXNG instances). If you need strict SSL verification, edit the script and change `verify=False` to `verify=True` in the httpx request.

## Troubleshooting
Confidence
95% confidence
Finding
The README states the skill is configured with `verify=False`, meaning TLS certificates are not validated for requests to the configured SearXNG instance. This enables man-in-the-middle interception or modification of search traffic and results, which is especially dangerous for a privacy-oriented search tool because it undermines confidentiality and trust in returned content.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares executable behavior that uses environment configuration and network access, but it does not explicitly declare tool scope such as permissions or allowed tools. This weakens reviewability and policy enforcement, because a user or platform may not realize the skill can transmit queries to a network endpoint defined by environment state.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
87% confidence
Finding
The trigger 'search for' overlaps with a built-in search-style command, creating shadowing risk. This can divert user requests into this skill unexpectedly, causing unintended network transmission of search content and reducing predictability of command routing.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
87% confidence
Finding
The trigger 'search web' is generic and likely to conflict with native search functionality. In a search skill, that makes accidental invocation more dangerous because common browsing requests may be silently redirected to the configured external endpoint.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
84% confidence
Finding
The trigger 'find information' is broad and overlaps with ordinary assistant behavior and built-in 'find' semantics. This increases the chance that unrelated requests are captured by the skill, leading to unintended query forwarding and confusing behavior.

Vague Triggers

Medium
Confidence
97% confidence
Finding
The trigger phrases are broad, natural-language patterns likely to match ordinary user requests, which can cause the skill to activate unexpectedly. In this context, accidental activation can send sensitive user queries to the configured SearXNG instance or override safer built-in handling.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The description emphasizes privacy but does not warn that user queries are transmitted to the configured SearXNG instance. If that instance is remote or third-party, users may disclose sensitive search terms under a misleading privacy assumption.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The comment states Bing is "critical for Chinese queries," which imposes a language/locale-specific behavior in natural language without indicating user opt-in or an explicit regional/compliance justification. This can violate language or locale policy because it steers the skill toward a specific provider based on language context alone.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script unconditionally stops and removes a container named `searxng` and overwrites `config/settings.yml` without prompting the user. This is not an exploit primitive by itself, but it can destroy existing state or replace user configuration unexpectedly, which is unsafe behavior for an installation script.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding
The script pulls and runs `searxng/searxng:latest` without pinning a specific tag or digest, making deployments non-reproducible and exposing users to unexpected upstream changes or a compromised image. In a bootstrap script that automatically launches a service, this creates a real supply-chain risk rather than a purely operational concern.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
Using `--network host` gives the container direct access to the host network namespace, which is broader access than needed for a local metasearch web service. If the container is compromised, this increases the ability to interact with host-only services, bypass Docker network isolation, and expand lateral movement opportunities.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script launches a long-running Dockerized web service without explicit disclosure that it is creating a networked service on the host. Even though `GRANIAN_HOST=127.0.0.1` narrows exposure, the combination with host networking and automatic startup means the user may unknowingly run a persistent service with network reachability and resource impact.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
f"{SEARXNG_URL}/search",
            params=params,
            timeout=30,
            verify=False  # For local self-signed certs
        )
        response.raise_for_status()
Confidence
98% confidence
Finding
Disabling TLS certificate verification allows man-in-the-middle interception and tampering of search traffic whenever HTTPS is used, especially if SEARXNG_URL is changed from localhost to a remote host. In this skill, the query contents and returned results could be observed or modified by an attacker, undermining both privacy and integrity.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
The only language example shown uses `--language en`, which can imply an English-default workflow without any accompanying note that other languages are supported or user-selectable. While subtle, this is a natural-language locale signal that would be clearer if the documentation explicitly stated that language is configurable.

Missing User Warnings

Low
Confidence
83% confidence
Finding
This code sends the user-provided query to the configured SearXNG instance over HTTP(S), which is a network operation involving user data. While the tool is clearly a search client, there is no explicit user-facing warning in code comments, prompts, or output that the query is transmitted to a local or configured server instance.

Static analysis

No suspicious patterns detected.