T09 · Insecure Skill Coding Practices
- Location
people-enrichment.mjs:35- Finding
Unrestricted API Base URL Can Exfiltrate Credentials and Lookup Identifiers
- Content
View full analysis
Vulnerability Details
File Location:
people-enrichment.mjs:35-39, 68-73
Vulnerability Type: Unvalidated network destination for authenticated requests
Risk Level: HighVulnerable Code
js const apiKey = process.env.OPENMERCH_API_KEY; if (!apiKey) throw new Error("OPENMERCH_API_KEY is not set. Get a key from the Developer page in the OpenMerch app."); const baseUrl = (process.env.OPENMERCH_BASE_URL || "https://api.openmerch.dev").replace(/\/+$/, "");js async function call(method, path, body) { const headers = { "X-OpenMerch-Key": apiKey }; if (body !== undefined) headers["Content-Type"] = "application/json"; const res = await fetchFn(`${baseUrl}${path}`, { method, headers, body: body !== undefined ? JSON.stringify(body) : undefined, });Technical Analysis
The implementation accepts
OPENMERCH_BASE_URLwithout validating its protocol, hostname, port, embedded credentials, or trust status. Thecallhelper subsequently attaches the sensitiveX-OpenMerch-Keyauthentication header to every request sent to this configured destination.Consequently, any party capable of influencing the Skill's environment can redirect authenticated requests to an attacker-controlled server. The override can also specify plain HTTP, exposing the API key, Apollo person ID, job data, and returned personal information to network interception.
Although a configurable staging endpoint is documented, forwarding a production credential to any environment-selected host exceeds the minimum privilege required for the declared production enrichment functionality. The default destination is the documented OpenMerch API, but the code does not enforce that security boundary.
The malicious endpoint can return a crafted successful plan response with a positive price, causing the Skill to continue to
/v1/execute. It can then return manipulated job results or ...[truncated 2236 chars]- Remediation
View remediation
Remediation Suggestions
-
Pin production requests to the expected origin:
js const DEFAULT_ORIGIN = "https://api.openmerch.dev"; -
If endpoint overrides are not essential to ordinary users, remove
OPENMERCH_BASE_URLfrom the production Skill entirely. -
If staging support is required, parse the value with
new URL()and enforce:- The
https:protocol. - An explicit hostname allowlist.
- Approved ports only.
- No embedded username or password.
- No fragments or unexpected path prefix.
- The
-
Use separate, restricted non-production credentials for staging. Never forward a production key to a staging or developer-selected endpoint.
-
Fail closed when URL validation fails and avoid including the API key in diagnostic output.
-
Add automated tests verifying that the implementation rejects:
- Plain HTTP URLs.
- Unapproved domains and subdomains.
- Loopback, link-local, and private-network destinations.
- URLs containing embedded credentials.
- Unexpected ports and malformed URLs.
-
Where supported by OpenMerch, restrict API keys by environment, scope, budget, expiration, or source identity to reduce the impact of disclosure.
-
Preserve the existing data minimization in
normalize, which avoids emitting the complete upstream provider response.
-
