Back to skill

Security audit

AnySearch

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real search skill, but its clients can be redirected to send API keys and queries to an unexpected endpoint.

Review before installing. Use anonymous mode or a low-privilege AnySearch key, avoid passing keys with --api_key, prefer environment-variable or protected secret storage, and do not use the skill with sensitive queries. Ensure ANYSEARCH_API_BASE_URL is unset and that no skill-local .env file can override it before running authenticated searches.

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

Error
Location
scripts/anysearch_cli.py:50
Finding
Bearer credentials and sensitive requests can be redirected to an arbitrary endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/anysearch_cli.py:50-84` **Additional Affected Files**: `scripts/anysearch_cli.js:13,56-77`; `scripts/anysearch_cli.ps1:43,53-61,89`; `scripts/anysearch_cli.sh:131-147`; `scripts/generate.py:72,82,92,103` **Vulnerability Type**: Unrestricted API endpoint override with credential forwarding **Risk Level**: High ### Complete Vulnerable Code Snippet ```python API_BASE_URL = os.environ.get( "ANYSEARCH_API_BASE_URL", "https://api.anysearch.com" ).rstrip("/") def _build_headers(api_key: str) -> dict: headers = { "Content-Type": "application/json", "X-Anysearch-Client": CLIENT_HEADER, } if api_key: headers["Authorization"] = f"Bearer {api_key}" return headers def _call_rest(method: str, path: str, api_key: str, *, payload=None, params=None) -> dict: try: resp = requests.request( method, f"{API_BASE_URL}{path}", json=payload, params=params, headers=_build_headers(api_key), timeout=30, ) ``` The Node.js implementation additionally demonstrates that plaintext HTTP is explicitly supported: ```javascript const API_BASE_URL = (process.env.ANYSEARCH_API_BASE_URL || "https://api.anysearch.com").replace(/\/$/, ""); function restRequest(method, endpointPath, apikey, payload = undefined, params = []) { const urlObj = new URL(API_BASE_URL + endpointPath); const options = { hostname: urlObj.hostname, port: urlObj.port || undefined, path: urlObj.pathname + urlObj.search, method, headers: { "Content-Type": "application/json", "X-Anysearch-Client": CLIENT_HEADER, }, }; if (apikey) { options.headers["Authorization"] = `Bearer ${apikey}`; } return new Promise((resolve, reject) => { const transport = urlObj.protocol === "http:" ? http : https; const req = transport.request(options, (res) => { ``` The shell implemen ...[truncated 3330 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove the production endpoint override where possible.** Hardcode `https://api.anysearch.com` in distributable clients and inject test endpoints directly into internal test functions. 2. **Enforce HTTPS and an explicit host allowlist.** Validate the parsed URL before constructing any request: ```python from urllib.parse import urlparse parsed = urlparse(API_BASE_URL) if parsed.scheme != "https" or parsed.hostname != "api.anysearch.com": raise RuntimeError("Untrusted AnySearch API endpoint") ``` 3. **Bind credentials to the intended origin.** Add the `Authorization` header only when the final request origin exactly matches the approved HTTPS origin. 4. **Control redirects.** Disable redirects where unnecessary. If redirects are supported, reject cross-origin redirects and never forward authorization headers to a different host or scheme. 5. **Restrict `.env` parsing.** Only import explicitly supported keys: ```python if key == "ANYSEARCH_API_KEY" and value: os.environ[key] = value ``` Do not treat Skill-local `.env` files as a general-purpose source of arbitrary process-environment assignments. 6. **Separate test configuration from production configuration.** For example, permit a custom endpoint only when an explicit test-mode flag is enabled and refuse to attach real credentials in that mode. 7. **Apply the correction consistently.** Update all four clients and `scripts/generate.py` so regeneration does not restore the vulnerable behavior. 8. **Add regression tests** confirming that HTTP URLs, non-AnySearch hosts, user-info URLs, malformed origins, and cross-origin redirects are rejected before credentials are transmitted. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Python dependency installation is not reproducible or integrity-pinned<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-4` **Additional Affected Location**: `SKILL.md:158` **Vulnerability Type**: Unbounded third-party dependency resolution **Risk Level**: Low ### Complete Vulnerable Code Snippet ```text # Dependency for the Python CLI (scripts/anysearch_cli.py). # The Node.js, Bash and PowerShell CLIs require nothing from this file. # pip install -r requirements.txt requests>=2.20 ``` The Skill instructions also recommend installing the dependency dynamically: ```markdown - Dependency: the `requests` library (not part of the standard library). It is commonly already available; if importing it fails, install with `pip install requests` (or `pip install -r requirements.txt`), or fall through to the Node.js CLI, which has no dependencies. ``` ### Technical Analysis The Python dependency is specified only with a broad lower bound: ```text requests>=2.20 ``` There is no exact version, upper compatibility bound, lock file, or package hash. Consequently, installation results depend on the state of the package index at installation time rather than on the audited project contents. The direct package name is legitimate and no typosquatting or dependency-confusion package was identified. Nevertheless, the current instructions permit an agent to install unaudited future versions and their transitive dependencies. Python package installation can execute build backend and installation-related code with the permissions of the invoking user. This is a supply-chain hardening deficiency rather than evidence that the current `requests` package is malicious. ### Attack Path 1. The selected Python runtime does not already contain `requests`. 2. The agent follows `SKILL.md:158` and executes: ```bash pip install requests ``` or: ```bash pip install -r requirements.txt ``` 3. pip resolves the latest version satisfying `requests>=2.20`, together with dynamically selected transitive depen ...[truncated 1118 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin a reviewed version or use a narrowly bounded compatible range rather than an unrestricted lower bound. 2. Generate a lock or constraints file containing all transitive dependencies and reviewed versions. 3. Require package hashes, for example through pip's `--require-hashes` mode: ```text requests==<reviewed-version> --hash=sha256:<reviewed-hash> ``` 4. Document a controlled update process that reviews new direct and transitive dependency versions before changing the lock file. 5. Prefer an already available dependency-free runtime, such as the bundled Node.js client, instead of instructing an agent to install packages automatically. 6. If installation is necessary, require user confirmation and use an isolated virtual environment rather than modifying the global Python environment. 7. Add automated dependency vulnerability and integrity checks to release CI. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (59)

Credential Access

High
Category
Privilege Escalation
Content
.env
runtime.conf
__pycache__
.idea
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
.env
runtime.conf
__pycache__
.idea
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
Copy the example env file and fill in your key:

```bash
cp .env.example .env
# Edit .env and set: ANYSEARCH_API_KEY=<your_api_key_here>
```
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
复制示例环境变量文件并填入你的 key:

```bash
cp .env.example .env
# 编辑 .env 并设置:ANYSEARCH_API_KEY=<your_api_key_here>
```
Confidence
90% confidence
Finding
The documentation instructs storing an API key in a plaintext .env file. Although common, this increases the chance of accidental exposure through local file access, backups, logs, or misconfigured tooling, especially in shared agent environments.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
If the skill package also contains local test-server and multi-runtime subprocess test functionality, that materially exceeds the declared end-user search purpose. In environments where skills are trusted based on description, hidden testing/subprocess behavior expands attack surface and may enable unexpected local execution paths, network listeners, or command invocation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
If the skill package also contains local test-server and multi-runtime subprocess test functionality, that materially exceeds the declared end-user search purpose. In environments where skills are trusted based on description, hidden testing/subprocess behavior expands attack surface and may enable unexpected local execution paths, network listeners, or command invocation.

Credential Access

High
Category
Privilege Escalation
Content
- name: ANYSEARCH_API_KEY
    required: false
    description: "API key for higher rate limits. Anonymous access available with lower rate limits."
    storage: ".env file, environment variable, or --api_key CLI flag"
---

## Overview
Confidence
91% confidence
Finding
The skill explicitly handles an API key from .env, environment variables, or CLI flags, which confirms credential access capability. This is risky in a skill that also performs network operations and shell invocation, because mishandling could expose secrets via process arguments, logs, error messages, or unintended downstream requests.

Credential Access

High
Category
Privilege Escalation
Content
### Key Source Priority

```
--api_key CLI flag  >  .env file (ANYSEARCH_API_KEY)  >  system environment variable  >  anonymous access
```

**Anonymous access is available** with lower rate limits. An API Key is optional but recommended for higher rate limits. If no key is found, the agent may proceed with anonymous access. If the user wants higher limits, guide them to configure a key securely.
Confidence
94% confidence
Finding
The documented key source priority explicitly prefers a CLI flag over .env and environment variables, which is a poor security default because command-line arguments are often visible to other local users, shell history, monitoring agents, and crash reports. The skill context makes this more dangerous because the tool is designed for routine use and could normalize insecure secret-passing practices.

Credential Access

High
Category
Privilege Escalation
Content
When a new key is obtained via auto-registration, the agent MUST:
1. Ask the user for explicit confirmation before saving the key to disk.
2. Inform the user: "A new API key was received. Save it to .env for future use?"
3. Only after user approval, update the `.env` file.
4. Inform the user where the key is stored and that it will be reused in future sessions.
Confidence
88% confidence
Finding
The skill instructs the agent to persist a newly received API key into a local .env file after user confirmation. Even with confirmation, automatic secret persistence expands the blast radius of compromise because .env files may have weak filesystem protections, be accidentally committed to source control, or be readable by other local tools and sessions.

Ae1

High
Category
analysis-evasion
Content
| Linux / macOS | bash 3.2+ (with `jq` and `curl`) | `anysearch_cli.sh` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| Linux / macOS | bash 3.2+ (with `jq` and `curl`) | `anysearch_cli.sh` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition

function Load-Env {
    $envPaths = @((Join-Path $SCRIPT_DIR ".env"), (Join-Path (Join-Path $SCRIPT_DIR "..") ".env"))
    foreach ($envPath in $envPaths) {
        if (Test-Path $envPath) {
            Get-Content $envPath -Encoding UTF8 | ForEach-Object {
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
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition

function Load-Env {
    $envPaths = @((Join-Path $SCRIPT_DIR ".env"), (Join-Path (Join-Path $SCRIPT_DIR "..") ".env"))
    foreach ($envPath in $envPaths) {
        if (Test-Path $envPath) {
            Get-Content $envPath -Encoding UTF8 | ForEach-Object {
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
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition

function Load-Env {
    $envPaths = @((Join-Path $SCRIPT_DIR ".env"), (Join-Path (Join-Path $SCRIPT_DIR "..") ".env"))
    foreach ($envPath in $envPaths) {
        if (Test-Path $envPath) {
            Get-Content $envPath -Encoding UTF8 | ForEach-Object {
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
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Definition

function Load-Env {
    $envPaths = @((Join-Path $SCRIPT_DIR ".env"), (Join-Path (Join-Path $SCRIPT_DIR "..") ".env"))
    foreach ($envPath in $envPaths) {
        if (Test-Path $envPath) {
            Get-Content $envPath -Encoding UTF8 | ForEach-Object {
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
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
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding="utf-8", errors="replace")

def _load_env():
    """Load API keys from .env files near the skill.

    The documented priority is:
    --api_key > .env file > environment variable > anonymous.
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

No suspicious patterns detected.