Back to skill

Security audit

My Searxng

Security checks for vulnerabilities and agentic risk

Overview

This is a real SearXNG search skill, but it needs review because it can route broad search requests through an insecure or non-local endpoint.

Review before installing. Use this only with a SearXNG endpoint you control, prefer HTTPS with proper certificate validation, replace the bundled URL, and narrow the triggers so routine search requests are not silently routed through this skill. Treat all returned titles, URLs, and snippets as untrusted web content.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/searxng.py:94
Finding
Search Queries and Responses Are Exposed to Network Interception<![CDATA[ ## Vulnerability Details **File Location**: `scripts/searxng.py:94-107`; related insecure default in `scripts/searxng.ini:1-3` **Vulnerability Type**: Disabled TLS certificate validation and plaintext transport **Risk Level**: High ### Vulnerable Code ```python # Build final URL with encoded query string full_url = f"{SEARXNG_URL}/search?{urlencode(params)}" # Configure SSL context to ignore certificate verification. # Essential for local instances using self-signed certificates. ctx = ssl.create_default_context() ctx.check_hostname = False ctx.verify_mode = ssl.CERT_NONE try: # Perform the HTTP GET request req = Request(full_url) with urlopen(req, context=ctx, timeout=30) as response: # Decode response body and convert to Python dictionary data = json.loads(response.read().decode("utf-8")) ``` The bundled configuration additionally selects plaintext HTTP: ```ini [searxng] # SearXNG instance URL url = http://192.168.1.20:4000 ``` ### Technical Analysis The script explicitly disables certificate-chain and hostname verification for every HTTPS connection. Consequently, possession of any certificate is sufficient to impersonate the configured SearXNG server. The bundled endpoint uses HTTP rather than HTTPS, so it provides no transport confidentiality, integrity, or server authentication at all. The search terms are encoded in the URL query string. They can therefore be exposed to network observers and may also be retained in proxy, gateway, or server access logs. A network attacker can modify the returned JSON because the client does not establish an authenticated transport channel. ### Attack Path 1. A user or Agent submits a search query, potentially containing sensitive contextual information. 2. The script constructs a GET request whose URL contains the complete query. 3. The request is sent over the bundled plaintext HTTP connection, or over HTTPS without certificate and hostname verification. 4. An attacker con ...[truncated 859 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the global TLS bypass: ```python ctx = ssl.create_default_context() ``` Do not set `check_hostname` to `False` or `verify_mode` to `ssl.CERT_NONE`. 2. Require HTTPS for non-loopback endpoints. Reject plaintext HTTP unless the destination is explicitly limited to a loopback address and the user has knowingly enabled an insecure development mode. 3. For private deployments using a self-signed certificate, support a configurable CA certificate: ```python ctx = ssl.create_default_context(cafile=configured_ca_path) ``` This preserves authentication without requiring a publicly trusted certificate. 4. Replace the bundled private-network endpoint with a neutral placeholder or loopback default, and require explicit configuration before the first search. 5. Prefer an HTTP POST request where supported by SearXNG so that query terms are not embedded in the URL. Regardless of method, configure servers and intermediaries to avoid logging sensitive request data. 6. Fail closed on certificate errors and provide a clear configuration message rather than silently weakening transport security. ]]>

T01 · Skill Instruction Hijacking

Warning
Location
scripts/searxng.py:124
Finding
Untrusted Search-Result Content Is Emitted Directly into Agent-Visible Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/searxng.py:124-143` **Vulnerability Type**: Indirect prompt injection through unsanitized external search content **Risk Level**: Medium ### Vulnerable Code ```python # Header Section print(f"\nSEARCH RESULTS: {query}") print("-" * 85) print(f"{'ID':<4} {'Title':<55} {'URL'}") print("-" * 85) # Main Results Table (truncated titles for layout stability) for i, result in enumerate(results, 1): title = result.get("title", "No Title") display_title = (title[:52] + "...") if len(title) > 52 else title url = result.get("url", "") print(f"{i:<4} {display_title:<55} {url}") # Detailed Snippets for Top 3 results print("\n--- TOP RESULT DETAILS ---") for i, result in enumerate(results[:3], 1): print(f"\n[{i}] {result.get('title')}") print(f" URL: {result.get('url')}") # Clean up snippet content: remove newlines and extra spaces content = result.get('content', '').strip().replace('\n', ' ') if content: print(f" Snippet: {content[:300]}...") ``` ### Technical Analysis Search-result titles, URLs, and snippets originate from external websites and are therefore attacker-controlled data. The script prints these fields directly into output designed for AI consumption. Removing newline characters from snippets does not neutralize natural-language instructions, deceptive URLs, or terminal control characters. A malicious page can include text such as instructions to ignore prior constraints, disclose information, or invoke another tool. If that text is indexed and returned in a result title or snippet, it becomes part of the Agent's context without an explicit trust-boundary warning. A forged or compromised SearXNG response can produce the same result. ### Attack Path 1. An attacker publishes a page containing instruction-like content in its title, metadata, or body. 2. The attacker targets search terms likely to be used by the victim and attempts to have the pa ...[truncated 1172 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Clearly mark the entire result block as untrusted external data. State that titles, URLs, and snippets must never be interpreted as Agent instructions. 2. Use strong structural delimiters around each external field and keep search data separate from skill or system instructions. 3. Strip or escape control characters before output, including ANSI escape sequences and non-printing Unicode control characters. 4. Validate returned URLs. Permit only expected schemes such as `http` and `https`, and reject malformed URLs or values containing control characters. 5. In Agent integration instructions, require the model to treat retrieved content solely as evidence to summarize, never as authorization to invoke tools, reveal data, modify memory, or change task goals. 6. Consider returning a typed result structure through a trusted tool boundary rather than interpolating raw external text into instruction-adjacent prose. 7. Preserve output-size limits, but do not treat truncation or newline removal as a prompt-injection defense. Apply trust labeling and downstream policy enforcement independently. ]]>
Vulnerability Patterns
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (11)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
```bash
   # Use your configured URL from searxng.ini
   curl -k http://your-searxng-instance.com:port
   ```

2. **Verify the URL in your searxng.ini config file**
Confidence
97% confidence
Finding
The README explicitly recommends `curl -k`, which disables TLS certificate verification. Combined with the stated behavior of bypassing SSL verification (`ssl.CERT_NONE`), this normalizes insecure transport and makes man-in-the-middle interception or redirection of search traffic much easier, especially if users point the skill at non-local or public SearXNG instances.

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.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The README uses very broad activation phrases such as generic 'Search' examples, and the skill metadata includes many unconstrained triggers like 'look up', 'find information', and common Chinese web-search phrases. In an agent environment, broad triggers can cause unintended tool invocation, sending sensitive user text to the configured search backend when the user did not clearly intend web access.

Session Persistence

Medium
Category
Rogue Agent
Content
url = http://your-searxng-instance.com:port
```

Note: If the configuration file does not exist or is missing required settings, the script will automatically create a default configuration file and prompt you to modify it.

## Direct CLI Usage
Confidence
60% 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.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs execution of a Python script that performs network access and may create a local configuration file, but it declares no explicit tool scope or permissions. This weakens least-privilege controls and makes the skill easier to over-grant or invoke in environments where users and orchestrators cannot clearly assess its capabilities.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
87% confidence
Finding
The trigger 'search for' overlaps with a built-in search command, creating a shadowing risk where this third-party skill may capture intents meant for trusted native functionality. In a network-enabled skill, that can redirect queries, alter outputs, or expose user requests to a different backend than expected.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
87% confidence
Finding
The trigger 'search web' is highly similar to a built-in search capability and may intercept common user intents. Because this skill issues outbound requests to a configured SearXNG instance, users may unknowingly route searches through an alternate service, changing privacy and trust assumptions.

Shadow Command Trigger

Medium
Category
Trigger Abuse
Confidence
84% confidence
Finding
The trigger 'find information' is broad and conflicts with generic built-in discovery behavior, increasing the chance of unintended interception. In this context, accidental routing to a networked custom skill can lead to unanticipated data exposure and inconsistent results compared with trusted built-ins.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger set includes broad everyday phrases such as 'look up', '帮我查', and '搜一下', which can cause accidental activation in unrelated conversations. Unintended invocation is risky here because the skill can initiate network requests and potentially create local files, expanding the attack surface without deliberate user intent.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
The document includes imperative AI instructions written in Chinese such as "AI 必读" and "AI 约束," directing required behavior without offering a user language choice. This can constitute a language/locale policy issue because the skill embeds mandatory non-user-selected language guidance rather than presenting language preferences as optional.

Description-Behavior Mismatch

Low
Confidence
81% confidence
Finding
The manifest description frames the skill as operating through 'your local SearXNG instance', but the code accepts any URL from searxng.ini and does not enforce localhost or other local-only endpoints. That means the actual behavior can route searches to external SearXNG servers, which is broader than the stated local-instance scope.

Static analysis

No suspicious patterns detected.