Back to skill

Security audit

Chen Tavily Search

Security checks for vulnerabilities and agentic risk

Overview

This Tavily search skill mostly does what it claims, but it publishes a real-looking API key in its documentation and metadata.

Do not install this version as-is. The publisher should revoke and replace the exposed Tavily key, change metadata to require TAVILY_API_KEY, replace examples with placeholders, and add a clear notice that searches and raw-content requests are sent to Tavily.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:5
Finding

Hard-Coded Tavily API Credential Exposed in Skill Documentation and Metadata

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:5, SKILL.md:17, SKILL.md:24, and SKILL.md:29
Vulnerability Type: Hard-coded API credential and incorrect secret configuration
Risk Level: High

Vulnerable Code Snippets

SKILL.md:5

yaml
metadata: {"openclaw":{"emoji":"🔍","requires":{"bins":["node"],"env":["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"]},"primaryEnv":"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"}}

SKILL.md:17

json
        "apiKey": "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"

SKILL.md:24

bash
export TAVILY_API_KEY="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"

SKILL.md:29

bash
node {baseDir}/scripts/search.mjs "query"

The credential itself is exposed on lines 5, 17, and 24. Line 29 begins the documented execution flow that causes the configured credential to be consumed by the search script.

Technical Analysis

A Tavily development API credential is embedded directly in the distributed SKILL.md file. Anyone with access to the Skill package can extract and use this credential independently of the Skill.

The metadata on line 5 also uses the credential value itself as both an environment-variable requirement and the primaryEnv identifier. These fields should contain the variable name TAVILY_API_KEY, not its secret value. This configuration error can interfere with normal secret injection while simultaneously publishing the credential.

When the script runs, scripts/search.mjs:78 reads TAVILY_API_KEY, and scripts/search.mjs:94-102 transmits it to the declared Tavily HTTPS API as a bearer token:

javascript
const apiKey = (process.env.TAVILY_API_KEY ?? "").trim();

const resp = await fetch("https://api.tavily.com/search", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${apiKey}`
...[truncated 1664 chars]
Remediation
View remediation

Remediation Suggestions

  1. Revoke the exposed credential immediately. Treat it as compromised even if unauthorized use has not yet been detected.
  2. Generate a replacement key through Tavily and store it only in an approved secret manager or protected runtime configuration.
  3. Correct the Skill metadata so that it refers to the environment-variable name rather than a credential:
    yaml
    metadata: {"openclaw":{"emoji":"🔍","requires":{"bins":["node"],"env":["TAVILY_API_KEY"]},"primaryEnv":"TAVILY_API_KEY"}}
    
  4. Replace documentation secrets with placeholders, for example:
    json
    {
      "skills": {
        "entries": {
          "tavily-search": {
            "enabled": true,
            "apiKey": "YOUR_TAVILY_API_KEY"
          }
        }
      }
    }
    
    bash
    export TAVILY_API_KEY="YOUR_TAVILY_API_KEY"
    
  5. Inspect repository and package history. Removing the key from the current file does not remove it from prior commits, release archives, caches, or mirrors.
  6. Review provider logs and billing records for requests made using the exposed key, including unusual volume, source addresses, or query patterns.
  7. Add automated secret scanning to pre-commit hooks and CI pipelines to reject credential patterns before publication.
  8. Apply least privilege and usage controls to the replacement key, including quota limits, alerts, rotation schedules, and provider-supported restrictions.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The metadata embeds a concrete Tavily API key-like secret directly in the skill definition, including as the primary environment variable. If valid, anyone with access to the repository or package can reuse the credential for unauthorized API calls, billing abuse, or data access tied to that account.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The authentication examples show a real-looking API key in config JSON and shell commands instead of a placeholder. This directly discloses a reusable credential and encourages users to copy a live secret into files, terminals, logs, and shell history.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill declares capabilities that require environment access and outbound network use, but it does not explicitly scope or declare those permissions. That weakens reviewability and policy enforcement because consumers cannot easily tell what the skill is allowed to access before enabling it.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill sends user queries and, when raw-content is enabled, potentially full fetched page content to an external third-party service, but the documentation does not clearly warn about that data flow. Users may unintentionally transmit sensitive prompts, internal URLs, or proprietary content off-platform, especially because this is a search skill that appears routine and low risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation presents a concrete API key without any warning about secret handling, so users may paste it into config files or terminal commands that get stored in shell history, logs, screenshots, or version control. The danger is amplified because the secret already appears to be real rather than illustrative.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This code performs an outbound POST request to a third-party service and includes user-controlled query data in the request body plus an API credential in the Authorization header. External transmission is expected for a search skill, but in this context it is still a real security/privacy concern because agent users may pass sensitive data that is then disclosed outside the local environment.

Content

Scanner excerpt · scripts/search.mjs (reported line 100)May include surrounding context.

js
if (includeDomains.length > 0) body.include_domains = includeDomains;
if (excludeDomains.length > 0) body.exclude_domains = excludeDomains;

const resp = await fetch("https://api.tavily.com/search", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This code performs an outbound POST request to a third-party service and includes user-controlled query data in the request body plus an API credential in the Authorization header. External transmission is expected for a search skill, but in this context it is still a real security/privacy concern because agent users may pass sensitive data that is then disclosed outside the local environment.

Content

Scanner excerpt · scripts/search.mjs (reported line 100)May include surrounding context.

js
if (includeDomains.length > 0) body.include_domains = includeDomains;
if (excludeDomains.length > 0) body.exclude_domains = excludeDomains;

const resp = await fetch("https://api.tavily.com/search", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script sends user-supplied search queries, and optionally full raw page content, to Tavily’s external API without any explicit disclosure or consent mechanism at execution time. In an agent-skill context, this can cause unintentional exfiltration of sensitive prompts, internal terms, or retrieved content to a third party, especially when callers may assume the tool operates locally.

Content

No source excerpt is available for this finding.