T09 · Insecure Skill Coding Practices
- Location
scripts/search.mjs:90- Finding
Overbroad Reading of User Credential Files
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real Tavily search helper, but it automatically reads a generic home `.env` credential file if no API key is set.
Review this before installing if you keep unrelated secrets in `~/.env`. Prefer setting `TAVILY_API_KEY` explicitly in the environment and avoid using this skill with sensitive or proprietary search queries unless sending them to Tavily is acceptable.
scripts/search.mjs:90Overbroad Reading of User Credential Files
The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The skill uses 'network' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.
The credential-access pattern is real because the script intentionally attempts to source secrets from local .env files if the environment variable is absent. Even though it targets TAVILY_API_KEY, scanning general-purpose .env locations can unintentionally access unrelated sensitive material and exceeds least privilege for a search helper.
let apiKey = (process.env.TAVILY_API_KEY ?? '').trim();
if (!apiKey) {
// Fallback: read from ~/.openclaw/.env or ~/.env
for (const envPath of [
path.join(homedir(), '.openclaw', '.env'),
path.join(homedir(), '.env'),
Referencing ~/.openclaw/.env as a fallback still constitutes direct credential retrieval from disk and increases the blast radius if the skill is run in a broader user environment. While less severe than reading arbitrary files, it still bypasses explicit secret injection and can surprise users about what local data the skill consumes.
if (!apiKey) {
// Fallback: read from ~/.openclaw/.env or ~/.env
for (const envPath of [
path.join(homedir(), '.openclaw', '.env'),
path.join(homedir(), '.env'),
]) {
try {
Reading ~/.env is especially risky because that file often stores multiple unrelated secrets for other tools and services. A web-search skill has no strong need to inspect a user's generic home-directory secret file, so this behavior meaningfully increases the chance of overcollection and credential exposure.
// Fallback: read from ~/.openclaw/.env or ~/.env
for (const envPath of [
path.join(homedir(), '.openclaw', '.env'),
path.join(homedir(), '.env'),
]) {
try {
const content = await readFile(envPath, 'utf-8');
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
}
if (!apiKey) {
console.error('Missing TAVILY_API_KEY. Set env var or add to ~/.openclaw/.env');
process.exit(1);
}
This markdown contains core usage guidance, option descriptions, and examples in Chinese, while the rest of the file is in English. That effectively imposes a language/locale on users without stating that the skill is intended only for Chinese-speaking or China-specific workflows, and no opt-in or alternative language is provided.
The script falls back to reading secrets from ~/.openclaw/.env and ~/.env, which broadens its access beyond the minimum needed for a web-search skill. Accessing arbitrary home-directory env files creates unnecessary exposure to local secrets and normalizes secret harvesting behavior, especially since ~/.env may contain unrelated credentials.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// ── Execute search ─────────────────────────────────────────────────────
const resp = await fetch('https://api.tavily.com/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// ── Execute search ─────────────────────────────────────────────────────
const resp = await fetch('https://api.tavily.com/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
The skill transmits user-supplied queries and may request raw page content handling through a third-party API without any explicit in-code notice or consent boundary. This can expose sensitive prompts, investigations, or proprietary research terms to an external provider when users may assume the tool is only performing local orchestration.