T09 · Insecure Skill Coding Practices
- Location
scripts/plai-meta.js:11- Finding
Environment-Controlled API Endpoint Enables Credential and Advertising Data Exfiltration
- Content
View full analysis
Vulnerability Details
File Location:
scripts/plai-meta.js, lines 11–35
Vulnerability Type: Unvalidated destination for sensitive network requests
Risk Level: HighVulnerable Code
js const BASE_URL = process.env.PLAI_BASE_URL || "https://public.plai.io"; const API_KEY = process.env.PLAI_API_KEY; const USER_ID = process.env.PLAI_USER_ID; async function plai(endpoint, body = {}) { const url = `${BASE_URL}${endpoint}`; const res = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": API_KEY, "x-request-source": "clawhub-meta-ads-skill", }, body: JSON.stringify({ ...body, userId: USER_ID }), });Technical Analysis
The API destination is taken from the environment variable
PLAI_BASE_URLwithout validating its scheme, hostname, port, or trust level. Every API operation then sends the Plai API key in thex-api-keyheader and the Plai user ID in the request body to that destination.Depending on the invoked command, the request body may also contain campaign details, audience identifiers, pixel IDs, lead-form metadata, media identifiers, product catalog information, URLs, targeting criteria, and OAuth connection parameters.
The network communication itself is necessary for the Skill's declared advertising-management functionality when the destination is the default Plai endpoint. However, allowing an unrestricted environment variable to redirect credential-bearing requests exceeds the minimum privilege needed for that functionality. The override can also specify a plaintext HTTP endpoint, exposing credentials and request data to network interception.
Exploitation requires an attacker, compromised launcher, malicious wrapper, or unsafe runtime configuration to influence the process environment before the CLI is invoked.
Attack Path
- The attacker gains the ability to influence the environ ...[truncated 1527 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove the runtime override and pin production requests to the expected endpoint:
js const BASE_URL = "https://public.plai.io"; -
If custom endpoints are required for development or testing, parse the value with
URLand enforce:- The
https:scheme. - An explicit hostname allowlist.
- Approved ports only.
- No embedded username or password.
- No fragments or unexpected path prefixes.
- The
-
Use a clearly development-specific opt-in, such as
PLAI_ALLOW_CUSTOM_BASE_URL=true, and reject custom destinations in normal production execution. -
Keep development and production credentials separate. Test endpoints must never receive production API keys or user identifiers.
-
Fail closed when URL validation fails rather than falling back to or attempting an untrusted destination.
-
Document the endpoint trust boundary and warn operators that environment configuration controls where sensitive account data is transmitted.
-
Consider server-side credential scoping and rotation so that exposed keys have only the minimum permissions and can be revoked promptly.
-
