Back to skill

Security audit

NewsAPI Search

Security checks for vulnerabilities and agentic risk

Overview

This is a straightforward NewsAPI search skill with no hidden execution or persistence, though its credential handling is broader than ideal.

Before installing, keep ~/.openclaw/.env limited to the NewsAPI key or avoid storing unrelated secrets there. Be aware that NewsAPI request URLs may contain the API key, so avoid running this through tooling that logs full URLs unless those logs redact sensitive query parameters.

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.js:7
Finding
Overbroad Loading of Credentials from a Shared Environment File<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search.js:7-16`; `scripts/sources.js:7-16` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Medium ### Vulnerable Code The following code appears in both affected files: ```javascript // Load environment variables function loadEnv() { const envPath = path.join(process.env.HOME, '.openclaw', '.env'); if (fs.existsSync(envPath)) { const envContent = fs.readFileSync(envPath, 'utf-8'); envContent.split('\n').forEach(line => { const match = line.match(/^([^#=]+)=(.*)$/); if (match) { process.env[match[1].trim()] = match[2].trim(); } }); } } ``` ### Technical Analysis The Skill requires only `NEWSAPI_KEY`, but both scripts read the complete shared `~/.openclaw/.env` file and copy every matching `KEY=value` entry into `process.env`. This behavior exceeds the minimum access necessary for the declared NewsAPI functionality. If the shared file contains credentials for other services, those unrelated secrets become accessible to all code executing in the Node.js process. The loader also overwrites existing environment variables without checking whether they were already defined, which can unexpectedly alter trusted process configuration. The reviewed code does not transmit unrelated environment variables. The risk arises from unnecessarily broad secret access and the resulting exposure to future code changes, injected code, or compromised runtime components. ### Attack Path 1. A user stores `NEWSAPI_KEY` and unrelated service credentials in `~/.openclaw/.env`. 2. The user invokes `scripts/search.js` or `scripts/sources.js`. 3. The script reads the entire shared credential file rather than retrieving only `NEWSAPI_KEY`. 4. Every parsed entry is copied into `process.env`. 5. Any subsequently executed or compromised code in the same process can read those unrelated credentials through `process.env`. 6. The exposed credentials could t ...[truncated 808 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer requiring `NEWSAPI_KEY` to be supplied directly through the process environment rather than automatically reading a shared credential file. 2. If file-based loading is necessary, parse and retrieve only the exact `NEWSAPI_KEY` entry. 3. Do not overwrite an existing `process.env.NEWSAPI_KEY` value. 4. Avoid copying unrelated file entries into `process.env`. 5. Validate that `HOME` is defined before constructing the path. 6. Restrict the credential file to owner-only permissions, such as mode `0600`. 7. Consider using a dedicated NewsAPI credential file or a platform-provided secret manager rather than a shared multi-service `.env` file. A minimal approach would be: ```javascript function loadNewsApiKey() { if (process.env.NEWSAPI_KEY) { return process.env.NEWSAPI_KEY; } const envPath = path.join(process.env.HOME, '.openclaw', '.env'); if (!fs.existsSync(envPath)) { return undefined; } const line = fs.readFileSync(envPath, 'utf8') .split(/\r?\n/) .find(entry => entry.startsWith('NEWSAPI_KEY=')); return line ? line.slice('NEWSAPI_KEY='.length).trim() : undefined; } const API_KEY = loadNewsApiKey(); ``` ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/search.js:200
Finding
NewsAPI Credential Included in Request URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search.js:200-205`, `scripts/search.js:292-296`, `scripts/sources.js:110-112` **Vulnerability Type**: T09: Insecure Skill Coding Practices **Risk Level**: Low ### Vulnerable Code In `scripts/search.js:200-205`, the API key is added to the Everything endpoint query string: ```javascript const params = new URLSearchParams({ pageSize: options.limit?.toString() || '10', page: options.page?.toString() || '1', sortBy: options.sort || 'relevancy', apiKey: API_KEY }); ``` In `scripts/search.js:292-296`, the same pattern is used for the Top Headlines endpoint: ```javascript const params = new URLSearchParams({ pageSize: options.limit?.toString() || '10', page: options.page?.toString() || '1', apiKey: API_KEY }); ``` In `scripts/sources.js:110-112`, the key is included in the Sources endpoint query string: ```javascript const params = new URLSearchParams({ apiKey: API_KEY }); ``` The resulting URLs are sent to hard-coded NewsAPI endpoints, for example: ```javascript const url = `https://newsapi.org/v2/top-headlines/sources?${params.toString()}`; ``` ### Technical Analysis The API key is embedded in the URL query string. Although requests use HTTPS and target the declared official `newsapi.org` service, URL-based credentials are more likely than header credentials to be retained in diagnostic output, application traces, proxy logs, monitoring systems, or debugging instrumentation. This is not evidence of malicious exfiltration: authentication is necessary for the declared functionality, and the reviewed code sends the key only to NewsAPI. The weakness is the choice of credential transport mechanism. HTTPS protects the request in transit but does not prevent local software, endpoint monitoring, or trusted intermediaries from recording the request target after TLS termination. ### Attack Path 1. A user configures a valid `NEWSAPI_KEY` and invokes a search or source-listing operation ...[truncated 1197 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `apiKey` from every `URLSearchParams` object. 2. Send the credential using NewsAPI's supported `X-Api-Key` request header. 3. Ensure error messages and diagnostic logging never serialize authentication headers. 4. Rotate the existing key if complete request URLs may already have been retained by proxies or monitoring systems. 5. Configure proxies, observability platforms, and HTTP tracing tools to redact authentication headers and sensitive query parameters. For example, update the request helper to accept the key through a header: ```javascript function makeRequest(url) { return new Promise((resolve, reject) => { const options = new URL(url); const requestOptions = { hostname: options.hostname, path: options.pathname + options.search, method: 'GET', headers: { 'User-Agent': 'NewsAPISearch/1.0 (Research Tool)', 'X-Api-Key': API_KEY } }; const req = https.request(requestOptions, (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { resolve(JSON.parse(data)); } catch (error) { reject(new Error('Invalid JSON response')); } }); }); req.on('error', reject); req.setTimeout(30000, () => { req.destroy(); reject(new Error('Request timeout')); }); req.end(); }); } ``` Construct request parameters without the credential: ```javascript const params = new URLSearchParams({ pageSize: options.limit?.toString() || '10', page: options.page?.toString() || '1', sortBy: options.sort || 'relevancy' }); ``` ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The description says the skill searches news articles and supports article-oriented filters such as time windows, sources, domains, and languages. The code instead calls NewsAPI's sources endpoint to retrieve source metadata, not articles. Its implemented filters are country, category, and language, with no support for time windows, domains, or article source filtering in the described sense. This is a material purpose mismatch, not just an implementation detail.

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/search.js "technology" --days 7
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/sources.js --country us --category general
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

No suspicious patterns detected.