T09 · Insecure Skill Coding Practices
- Location
scripts/tavily-pro.mjs:320- Finding
Plaintext Search Queries and Extraction URLs Are Logged by Default
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a disclosed Tavily web research helper whose network use, API key use, local cache, logs, and cache deletion are coherent with its purpose.
Install only if you are comfortable sending approved queries and URLs to Tavily with your TAVILY_API_KEY. Use --no-log --no-cache for sensitive or client/private research, use separate OS profiles when Tavily account isolation matters, and only run cache clear when you intentionally want to delete this skill's cached response files.
scripts/tavily-pro.mjs:320Plaintext Search Queries and Extraction URLs Are Logged by Default
scripts/tavily-pro.mjs:773Documented Approval Gate for Cache Deletion Is Not Enforced by the CLI
Referenced artifact was not completely inspected
Script: `scripts/tavily-pro.mjs`
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
function run(name, args, { env = {}, expectCode = 0, stderrIncludes, stdoutIncludes, stderrExcludes, stdoutExcludes } = {}) {
const result = spawnSync(process.execPath, [cli, ...args], {
env: { ...baseEnv, ...env },
encoding: "utf8",
});
const stdout = result.stdout || "";
The skill declares access to environment variables and performs outbound network calls, but it does not define an explicit tool scope such as permissions or allowed-tools. In an agent ecosystem, missing capability declarations weaken policy enforcement and user visibility, increasing the chance that a skill with external transmission behavior is invoked without appropriate guardrails.
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.
- Usage logs may contain plaintext search queries/URLs; use `--no-log` for approved sensitive external calls.
- Local/private URL refusal is a guardrail for obvious mistaken extract targets, not a complete SSRF boundary; Tavily performs extraction from Tavily infrastructure, not this machine.
- Does not read local files outside its documented cache/log state, and does not read non-Tavily secrets. User-supplied search queries and accepted extract URLs are sent to Tavily; `TAVILY_API_KEY` is sent only to Tavily for authentication. Credential-bearing and local/private extract URLs are rejected before API key load/Tavily transmission, and those error paths do not echo the supplied URL.
- Does not modify system configuration or auto-update. The only destructive local action is the documented, approval-gated `cache clear` deletion of expected regular cached response JSON files after cache-path containment checks.
- Public-registry static-analysis `potential_exfiltration` warnings are expected because this tool combines env credentials, local cache/log file access, and Tavily network calls.
## When to use
The contract explicitly documents that cached Tavily responses are not scoped to the API account and may be shared when multiple Tavily accounts use the same OS user/home directory. This can expose prior search/extract results across account boundaries, which is a confidentiality and session-persistence issue, especially because the skill handles research queries and extracted web content that may be sensitive.
`cache` with no subcommand defaults to `cache info`. Routine cache reads/writes and usage-log reads/writes perform persistent-state containment checks and refuse symlink-indirected directories/files instead of following them outside `~/.openclaw/cache/tavily-search-pro-native-node/`. `cache clear` accepts no extra arguments, requires explicit approval, rejects symlink-indirected cache paths, deletes only expected hash-named regular cached response JSON files under the skill-specific cache directory, skips non-cache entries, and does not delete `usage.log`. It reports partial deletion failures with the number already deleted instead of returning a false zero.
Responses are cached under `~/.openclaw/cache/tavily-search-pro-native-node/cache/` keyed by a SHA-256-derived hash of request body + kind. Request-body-affecting options such as topic, depth, max results, include/exclude domains, raw-content, URL list, and extract depth create different cache entries; output/control flags such as `--json`, `--ttl`, `--no-log`, and `--no-retry` do not. Cache entries are not API-account-scoped; if multiple Tavily accounts share the same OS user/home directory, they may share cached results for identical requests. Use separate profiles or `--no-cache` when account isolation matters.
Default TTLs:
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import { homedir } from "node:os";
import { join, relative, resolve } from "node:path";
const SEARCH_ENDPOINT = "https://api.tavily.com/search";
const EXTRACT_ENDPOINT = "https://api.tavily.com/extract";
const SKILL_DIR_NAME = "tavily-search-pro-native-node";
const BASE_DIR = join(homedir(), ".openclaw", "cache", SKILL_DIR_NAME);
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import { homedir } from "node:os";
import { join, relative, resolve } from "node:path";
const SEARCH_ENDPOINT = "https://api.tavily.com/search";
const EXTRACT_ENDPOINT = "https://api.tavily.com/extract";
const SKILL_DIR_NAME = "tavily-search-pro-native-node";
const BASE_DIR = join(homedir(), ".openclaw", "cache", SKILL_DIR_NAME);
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import { homedir } from "node:os";
import { join, relative, resolve } from "node:path";
const SEARCH_ENDPOINT = "https://api.tavily.com/search";
const EXTRACT_ENDPOINT = "https://api.tavily.com/extract";
const SKILL_DIR_NAME = "tavily-search-pro-native-node";
const BASE_DIR = join(homedir(), ".openclaw", "cache", SKILL_DIR_NAME);
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import { homedir } from "node:os";
import { join, relative, resolve } from "node:path";
const SEARCH_ENDPOINT = "https://api.tavily.com/search";
const EXTRACT_ENDPOINT = "https://api.tavily.com/extract";
const SKILL_DIR_NAME = "tavily-search-pro-native-node";
const BASE_DIR = join(homedir(), ".openclaw", "cache", SKILL_DIR_NAME);
Detected: suspicious.dangerous_exec, suspicious.env_credential_access