Back to skill

Security audit

Tavilysearch 1.0.4

Security checks for vulnerabilities and agentic risk

Overview

This Tavily search skill mostly matches its stated purpose, but it deserves review because it sends queries and URLs to a third-party service and crawl mode allows cross-domain crawling by default without clear user control.

Install only if you are comfortable sending search terms, submitted URLs, crawl instructions, and research prompts to Tavily. Avoid using it with secrets, private/internal URLs, regulated data, or proprietary research topics unless approved. Store the Tavily key outside shared source trees where possible, restrict its permissions and quota, and review crawl use carefully because external-domain crawling is enabled by default.

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
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Allow Uncontrolled Package Updates

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-2; installation instruction at SKILL.md:16
Vulnerability Type: Unpinned dependencies without integrity verification
Risk Level: Medium

Vulnerable code:

text
requests>=2.31.0
urllib3>=2.0.0

Related installation instruction:

bash
pip install -r requirements.txt

Technical Analysis

Both dependencies use open-ended minimum-version constraints. Consequently, installation can resolve to any future release of requests or urllib3. The project provides neither a lock file nor cryptographic hashes to verify the precise artifacts being installed.

Although no malicious dependency is currently identified, this configuration makes installations non-reproducible and extends trust to package versions that were not part of this audit. If a future release, package distribution account, package index, or resolution path is compromised, attacker-controlled code could be installed and later executed when scripts/search.py imports the affected package.

Attack Path

  1. An attacker compromises a permitted future release, its publisher account, or the dependency resolution channel.
  2. The user follows the documented pip install -r requirements.txt instruction.
  3. pip resolves the open-ended constraint to the compromised release.
  4. Malicious package behavior executes during installation or when scripts/search.py imports the package.
  5. The payload operates with the permissions of the user or automation account running the installation or Skill.

Impact Assessment

Successful exploitation could provide arbitrary code execution with the privileges of the account installing or running the Skill. This may expose files, environment variables, API credentials, and network access available to that account. The vulnerability does not independently elevate operating-system privileges, but its scope can be substantial if ...[truncated 92 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to a reviewed exact version, for example:
    text
    requests==<reviewed-version>
    urllib3==<reviewed-version>
    
  2. Generate a lock file that also fixes all transitive dependency versions.
  3. Record SHA-256 hashes and install with pip --require-hashes.
  4. Configure installation to use an explicitly trusted package index.
  5. Run automated dependency vulnerability and provenance checks before upgrades.
  6. Test and review each dependency update before changing the lock file.
  7. Install dependencies inside an isolated virtual environment under a non-privileged account.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/search.py:13
Finding

API Credential Is Stored in a Plaintext Project-Local File

Content
View full analysis

Vulnerability Details

File Location: scripts/search.py:13-20; setup instruction at SKILL.md:16-20
Vulnerability Type: Insecure plaintext secret storage
Risk Level: Low

Vulnerable code:

python
with open(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env"), "r") as f:
    for line in f:
        line = line.strip()
        if line and not line.startswith("#") and "=" in line:
            key, value = line.split("=", 1)
            key = key.strip()
            if key == "TAVILY_API_KEY":
                os.environ[key] = value.strip()

Related setup instruction:

text
3. Create a `.env` file and enter the API key:
   TAVILY_API_KEY=tvly-your-actual-api-key
4. The program automatically reads the `.env` file in the Skill directory.

Technical Analysis

The documented setup places the Tavily API key in a plaintext .env file inside the project directory. The package does not include source-control exclusion guidance, restrictive file-permission enforcement, or integration with an external secret manager.

The implementation limits parsing to TAVILY_API_KEY, which prevents broad environment-file harvesting. Network use is also restricted to the fixed HTTPS origin https://api.tavily.com, so the audit found no unauthorized credential exfiltration. Nevertheless, project-local plaintext storage increases the risk that the credential will be committed, packaged, backed up, copied, or read by another local account.

Attack Path

  1. The user follows the setup instructions and writes the Tavily key to the project-local .env file.
  2. The project directory is committed to source control, included in an artifact or backup, shared with another party, or left readable by other local users.
  3. An attacker obtains the plaintext .env file.
  4. The attacker extracts TAVILY_API_KEY.
  5. The attacker authenticates to Tavily using the stolen key ...[truncated 650 chars]
Remediation
View remediation

Remediation Suggestions

  1. Prefer receiving TAVILY_API_KEY from the process environment or an operating-system, CI/CD, or cloud secret manager.
  2. Do not require credentials to be stored inside the Skill directory.
  3. If .env support is retained:
    • Add .env to .gitignore.
    • Ship only a credential-free .env.example.
    • Require restrictive permissions such as mode 0600 on Unix-like systems.
    • Refuse to use a file with unsafe ownership or permissions where practical.
    • Warn users never to commit, package, or share the file.
  4. Preserve the current fixed HTTPS API origin and avoid following redirects when transmitting the Authorization header.
  5. Use narrowly scoped keys and account spending or quota limits where Tavily supports them.
  6. Document immediate key revocation and rotation procedures for suspected disclosure.
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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (27)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The top-level description frames the skill as a search integration, but the document also describes broader capabilities including full-site crawling, research task creation/polling, usage inspection, and local .env reading. This mismatch can cause users or orchestrators to approve the skill for low-risk search while unintentionally granting higher-risk data collection and local secret access behaviors.

Content

No source excerpt is available for this finding.

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 13)May include surrounding context.

python
from typing import Optional, List, Dict, Any

# 只读取TAVILY_API_KEY环境变量
with open(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), ".env"), "r") as f:
    for line in f:
        line = line.strip()
        if line and not line.startswith("#") and "=" in line:

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 26)May include surrounding context.

python
def __init__(self, api_key: Optional[str] = None):
        self.api_key = api_key or os.getenv("TAVILY_API_KEY")
        if not self.api_key:
            raise ValueError("TAVILY_API_KEY 未配置,请在 .env 文件中设置")
        self.base_url = "https://api.tavily.com"
    
    def search(

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares access to an API key and performs network operations, but does not declare an explicit tool scope such as permissions or allowed-tools. This weakens least-privilege controls and makes it harder for a host platform or reviewer to understand and constrain what the skill can access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description does not clearly warn that user queries, URLs, and possibly extracted content are transmitted to the Tavily service. Without a privacy and data-transfer notice, users may provide sensitive prompts, internal URLs, or proprietary targets under the false assumption that processing is local.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

The referenced Tavily API endpoint indicates the skill depends on external network communication. In isolation this is not malicious, but it is security-relevant because it enables off-host data transfer and should be transparently declared and constrained.

Content

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

md
python scripts/search.py search "搜索关键词" [选项]

# 最简调用
curl -X POST https://api.tavily.com/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -d '{"query": "搜索关键词", "include_answer": true}'

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

The referenced Tavily API endpoint indicates the skill depends on external network communication. In isolation this is not malicious, but it is security-relevant because it enables off-host data transfer and should be transparently declared and constrained.

Content

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

md
python scripts/search.py search "搜索关键词" [选项]

# 最简调用
curl -X POST https://api.tavily.com/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -d '{"query": "搜索关键词", "include_answer": true}'

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The crawl/extract documentation omits an explicit warning that the skill may retrieve and process content from third-party sites, including across domains when external crawling is allowed. In this context, that can expand data collection scope beyond what a user intended and increase privacy, legal, and safety risks from broad crawling.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

This explicit reference to the Tavily API endpoint further confirms external communications from the skill. The danger is contextual rather than inherently malicious: users may unknowingly send confidential search content to a third party if the skill does not clearly disclose this behavior.

Content

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

使用示例

搜索最新新闻

bash
curl -X POST https://api.tavily.com/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

This explicit reference to the Tavily API endpoint further confirms external communications from the skill. The danger is contextual rather than inherently malicious: users may unknowingly send confidential search content to a third party if the skill does not clearly disclose this behavior.

Content

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

使用示例

搜索最新新闻

bash
curl -X POST https://api.tavily.com/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -d '{

External Transmission

Medium
Category
Data Exfiltration
Confidence
85% confidence
Finding

The professional-search example also sends queries and potentially raw-content retrieval requests to the Tavily API. Because this mode may request more source content, it can increase the amount of third-party processed data and the chance of transmitting proprietary research topics or URLs.

Content

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

专业资料搜索

bash
curl -X POST https://api.tavily.com/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TAVILY_API_KEY" \
  -d '{

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

该 API 文档全文以中文编写,并在内容中未提供多语言选项、用户选择机制,或说明该文档为何必须限定为中文。根据语言/区域政策,若技能内容强制特定语言而没有用户选择或明确合理性说明,属于自然语言策略违规。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Throughout the file, CLI help text, status messages, errors, and output formatting are presented only in Chinese, with no option for users to choose another language. This is a natural-language locale policy issue because the skill enforces a specific language rather than offering a language/locale choice or documenting a justified region-specific constraint.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The search method transmits user-provided search terms and options to api.tavily.com, which is expected for functionality but still constitutes external data exfiltration if not disclosed and controlled. In an agent skill, this becomes security-relevant because user prompts may contain sensitive business or personal information not intended for a third party.

Content

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

python
"Authorization": f"Bearer {self.api_key}"
        }
        
        response = requests.post(f"{self.base_url}/search", json=payload, headers=headers)
        response.raise_for_status()
        return response.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

User-supplied queries, URLs, crawl instructions, and research prompts are sent to an external service without any user-facing disclosure or consent flow. In this skill context, that matters because users may provide sensitive terms or internal URLs while expecting only local processing, resulting in unintended third-party data exposure.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The extract method sends user-supplied URLs and optional query context to an external API for retrieval and processing. This can expose internal-only URLs, sensitive targets, or investigative intent to the third party if the user is not warned.

Content

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

python
"Authorization": f"Bearer {self.api_key}"
        }
        
        response = requests.post(f"{self.base_url}/extract", json=payload, headers=headers)
        response.raise_for_status()
        return response.json()

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

清单描述强调的是 Tavily 搜索引擎集成、web 搜索、内容提取和实时新闻查询等检索类功能。这里额外实现了 /research 任务创建与结果获取,属于更强的异步研究报告生成功能,而不是描述中直接声明的搜索或提取能力。

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The research endpoint transmits potentially lengthy user inputs, which may include confidential strategy, analysis questions, or proprietary text, to an external provider. Because the feature is broader than the stated skill scope, the risk of unexpected sensitive-data disclosure is higher.

Content

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

python
"Authorization": f"Bearer {self.api_key}"
        }
        
        response = requests.post(f"{self.base_url}/research", json=payload, headers=headers)
        response.raise_for_status()
        return response.json()

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The crawl capability materially exceeds the described search/extract use case and can cause broad third-party data collection through the external Tavily service. In the context of an agent skill, undisclosed whole-site crawling increases the risk of collecting and transmitting far more content than a user expects, especially when paired with permissive defaults.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

allow_external defaults to True, so a crawl rooted at one site may follow and transmit content from unrelated external domains without explicit approval. In an agent setting this is dangerous because a seemingly narrow request can expand into unexpected cross-site collection, increasing privacy, compliance, and data-minimization risks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
97% confidence
Finding

The crawl endpoint can transmit a root URL plus broad crawl parameters to a third-party service, which may cause large-scale collection of site content and linked external content. Given the default cross-site behavior and expanded scope, this has higher impact than simple search because it can unintentionally expose more data and collect far more material than the user intended.

Content

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

python
"Authorization": f"Bearer {self.api_key}"
        }
        
        response = requests.post(f"{self.base_url}/crawl", json=payload, headers=headers)
        response.raise_for_status()
        return response.json()

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with a lower bound only, so builds may resolve to different versions over time. This weakens supply-chain reproducibility and can allow deployment of unexpectedly vulnerable or incompatible releases if the package index changes.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.31.0
urllib3>=2.0.0

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
90% confidence
Finding

Because requests is not pinned, it is impossible to verify from this manifest whether the installed version includes fixes for known advisories. In a search integration that performs outbound HTTP requests, leaving the effective version ambiguous increases the chance that a vulnerable resolver-selected version is used in production.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

Using an unpinned urllib3 version makes installations non-deterministic and can pull in future releases with security regressions or unresolved advisories. This is a software supply-chain hygiene issue rather than an immediate exploitable flaw by itself, but it increases risk.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
requests>=2.31.0
urllib3>=2.0.0

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
90% confidence
Finding

The manifest does not let reviewers determine whether the resolved urllib3 release is patched against known issues. Since this skill likely makes network requests to external services, uncertainty around the exact HTTP client version raises supply-chain and runtime exposure, though the manifest alone does not prove an actively exploitable state.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.