Back to skill

Security audit

Tavily Web Search

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Tavily API toolkit with disclosed network, API-key, logging, and cache behavior, but users should handle credentials and cached results carefully.

Install only if you are comfortable giving the skill a Tavily API key and letting it send your queries, URLs, and requested research tasks to Tavily. Prefer a protected environment variable over plaintext ~/.openclaw/.env, avoid printing real keys in terminal output, use --no-cache for confidential searches or extracted pages, and review any cron-based update check before enabling it.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/search.py:96
Finding

Plaintext caching of potentially sensitive API results without explicit restrictive permissions

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:58
Finding

API-key setup and troubleshooting instructions do not enforce secure storage and may expose the secret on screen

Content
View full analysis
> ~/.openclaw/.env # Method 2: Environment variable export TAVILY_API_KEY="tvly-your-key-here" ``` The troubleshooting instructions recommend printing the matching line, including the complete credential: ```bash # Check configuration cat ~/.openclaw/.env | grep TAVILY # Or set an environment variable export TAVILY_API_KEY="tvly-xxx" ``` ### Technical Analysis The documented `echo ... >> ~/.openclaw/.env` command does not securely create the parent directory, establish owner-only permissions, or correct permissions on an existing file. The API key is a long-lived credential that can consume Tavily credits and retrieve account usage information, so it should not be stored in a file whose security depends solely on the user's current umask. The troubleshooting command prints the complete `TAVILY_API_KEY` assignment to the terminal. This can expose the key through terminal scrollback, screen sharing, session recording, copied diagnostics, or command output captured by an automation system. The scripts only extract `TAVILY_API_KEY` from the file and do not enumerate or transmit unrelated credentials. Reading this specific key is necessary for the declared functionality; the issue is the unsafe setup and display guidance rather than unauthorized credential access. ### Attack Path 1. A user follows the documented setup command. 2. The `.env` file is created or reused without verification of ownership or restrictive permissions. 3. A local user or process with filesystem access reads the API key from the file. Alternatively: 1. A user encounters a missing-key error ...[truncated 768 chars]
Remediation
View remediation
> ~/.openclaw/.env chmod 600 ~/.openclaw/.env ``` 3. Warn users not to paste real credentials into recorded terminals, shared shells, issue reports, or chat sessions. 4. Replace the troubleshooting command with a presence check that does not print the value, such as: ```bash grep -q '^TAVILY_API_KEY=' ~/.openclaw/.env \ && echo 'TAVILY_API_KEY is configured' \ || echo 'TAVILY_API_KEY is missing' ``` 5. Have the scripts reject insecure ownership or permissions where practical, or at least emit a warning when the credential file is readable by group or other users. 6. Document credential rotation and revocation procedures for keys that may have been displayed or disclosed. ]]>
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (62)

Tainted flow: 'req' from os.environ.get (line 152, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/extract.py (reported line 159)May include surrounding context.

python
method="POST",
    )

    with urllib.request.urlopen(req, timeout=60) as resp:
        body = resp.read().decode("utf-8", errors="replace")

    try:

Tainted flow: 'req' from os.environ.get (line 160, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/crawl.py (reported line 169)May include surrounding context.

python
# Map can take time
            timeout = params.get("timeout", 60)
            with urllib.request.urlopen(req, timeout=timeout) as resp:
                body = resp.read().decode("utf-8", errors="replace")

            try:

Tainted flow: 'req' from os.environ.get (line 160, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/map.py (reported line 169)May include surrounding context.

python
# Map can take time
            timeout = params.get("timeout", 60)
            with urllib.request.urlopen(req, timeout=timeout) as resp:
                body = resp.read().decode("utf-8", errors="replace")

            try:

Tainted flow: 'req' from os.environ.get (line 172, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/research.py (reported line 181)May include surrounding context.

python
# Research can take a long time
            timeout = params.get("timeout", 300)
            with urllib.request.urlopen(req, timeout=timeout) as resp:
                body = resp.read().decode("utf-8", errors="replace")

            try:

Tainted flow: 'req' from os.environ.get (line 172, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/research.py (reported line 245)May include surrounding context.

python
method="GET",
        )

        with urllib.request.urlopen(req, timeout=60) as resp:
            body = resp.read().decode("utf-8", errors="replace")

        return json.loads(body)

Tainted flow: 'req' from os.environ.get (line 160, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/search.py (reported line 167)May include surrounding context.

python
method="POST",
    )

    with urllib.request.urlopen(req, timeout=60) as resp:
        body = resp.read().decode("utf-8", errors="replace")

    try:

Tainted flow: 'req' from os.environ.get (line 84, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/usage.py (reported line 93)May include surrounding context.

python
method="GET",
        )
        
        with urllib.request.urlopen(req, timeout=10) as resp:
            body = resp.read().decode("utf-8", errors="replace")
        
        data = json.loads(body)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The command uses rm -rf with a wildcard to delete files recursively, which is inherently dangerous if copied incorrectly, variables expand unexpectedly, or the path is modified. In this skill context it is limited to a cache directory, so the impact is lower than a generic wipe, but it still exposes users to unintended local deletion.

Content

Scanner excerpt · SKILL.md (reported line 467)May include surrounding context.

清除缓存

bash
rm -rf ~/.openclaw/cache/tavily/*

禁用缓存

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

The command uses rm -rf with a wildcard to delete files recursively, which is inherently dangerous if copied incorrectly, variables expand unexpectedly, or the path is modified. In this skill context it is limited to a cache directory, so the impact is lower than a generic wipe, but it still exposes users to unintended local deletion.

Content

Scanner excerpt · SKILL.md (reported line 467)May include surrounding context.

清除缓存

bash
rm -rf ~/.openclaw/cache/tavily/*

禁用缓存

Credential Access

High
Category
Privilege Escalation
Confidence
74% confidence
Finding

Loading a secret from a plaintext ~/.openclaw/.env file is a weaker secret-management practice because it encourages long-lived local credential storage outside OS-backed secret stores. On multi-user systems, misconfigured permissions, backups, or other local access paths could expose the API key.

Content

Scanner excerpt · scripts/extract.py (reported line 117)May include surrounding context.

python
if key:
        return key.strip()

    env_path = pathlib.Path.home() / ".openclaw" / ".env"
    if env_path.exists():
        try:
            txt = env_path.read_text(encoding="utf-8", errors="ignore")

Credential Access

High
Category
Privilege Escalation
Confidence
79% confidence
Finding

Loading secrets from a plaintext ~/.openclaw/.env file increases the chance of credential exposure through weak filesystem permissions, backups, or accidental disclosure. While common in developer tooling, it is less secure than dedicated secret stores and the code does not verify permissions before use.

Content

Scanner excerpt · scripts/research.py (reported line 135)May include surrounding context.

python
if key:
        return key.strip()

    env_path = pathlib.Path.home() / ".openclaw" / ".env"
    if env_path.exists():
        try:
            txt = env_path.read_text(encoding="utf-8", errors="ignore")

Credential Access

High
Category
Privilege Escalation
Confidence
76% confidence
Finding

The script embeds the loaded API key into the outbound request payload to a third-party service. Although this is functionally necessary, it still represents sensitive credential transmission and increases risk if users are not clearly informed, if logs/proxies capture requests, or if the service endpoint trust assumptions are wrong.

Content

Scanner excerpt · scripts/research.py (reported line 160)May include surrounding context.

python
if not key:
        log("Missing API key", "ERROR")
        raise SystemExit(
            "Missing TAVILY_API_KEY. Set env var TAVILY_API_KEY or add it to ~/.openclaw/.env"
        )

    payload = {"api_key": key, **params}

Self-Modification

High
Category
Rogue Agent
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.

Content

Scanner excerpt · scripts/update.py (reported line 262)May include surrounding context.

python
def update_skill(force: bool = False) -> bool:
    """Update skill if needed"""
    log("Checking if skill update is needed...")
    
    check_result = check_for_updates()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 58)May include surrounding context.

md
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 59)May include surrounding context.

md
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 417)May include surrounding context.

md
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 454)May include surrounding context.

md
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/crawl.py (reported line 118)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/extract.py (reported line 112)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/map.py (reported line 118)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/research.py (reported line 130)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/search.py (reported line 121)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/usage.py (reported line 47)May include surrounding context.

python
# ============================================================================

def load_key() -> str:
    """Load API key from environment or .env file"""
    key = os.environ.get("TAVILY_API_KEY")
    if key:
        return key.strip()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/crawl.py (reported line 123)May include surrounding context.

python
if key:
        return key.strip()

    env_path = pathlib.Path.home() / ".openclaw" / ".env"
    if env_path.exists():
        try:
            txt = env_path.read_text(encoding="utf-8", errors="ignore")

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/crawl.py (reported line 148)May include surrounding context.

python
if key:
        return key.strip()

    env_path = pathlib.Path.home() / ".openclaw" / ".env"
    if env_path.exists():
        try:
            txt = env_path.read_text(encoding="utf-8", errors="ignore")