T09 · Insecure Skill Coding Practices
- Location
tools/picqer-api.ts:5- Finding
Unvalidated Picqer Subdomain Can Redirect API Credentials to an Attacker-Controlled Host
- Content
View full analysis
Vulnerability Details
File Location:
tools/picqer-api.ts, lines 5–20
Vulnerability Type: Credential disclosure through unvalidated URL construction
Risk Level: HighVulnerable Code
ts const { subdomain, apiKey } = getPicqerConfig(); const url = new URL(`https://${subdomain}.picqer.com/api/v1${path}`); if (searchParams) { Object.entries(searchParams).forEach(([k, v]) => { if (v) url.searchParams.set(k, v); }); } const res = await fetch(url.toString(), { headers: { 'Authorization': `Basic ${Buffer.from(`${apiKey}:`).toString('base64')}`, 'User-Agent': 'FutureFulfillment-Dashboard (internal)' } }); if (!res.ok) {The environment-controlled value originates in
env.ts, lines 4–10:ts const subdomain = process.env.PICQER_SUBDOMAIN; const apiKey = process.env.PICQER_API_KEY; if (!subdomain || !apiKey) { throw new Error('Picqer API not configured. Set PICQER_SUBDOMAIN and PICQER_API_KEY in .env'); } return { subdomain, apiKey };Technical Analysis
PICQER_SUBDOMAINis interpolated directly into an absolute URL without validating that it is a single DNS label. URL delimiters such as/can therefore change which portion of the generated string is interpreted as the hostname.For example, setting the subdomain to
attacker.example/xproduces:text https://attacker.example/x.picqer.com/api/v1/picklistsThe effective hostname is
attacker.example, not a host beneathpicqer.com. The application subsequently attaches the Picqer API key as a Basic Authorization header and sends the request to that effective hostname.Base64 encoding does not protect the credential; it is only an encoding of the API key followed by a colon. TLS protects the request in transit but intentionally delivers it to the attacker-controlled HTTPS endpoint selected by the manipulated URL.
Attack Path
- An attacker gains the ...[truncated 1616 chars]
- Remediation
View remediation
Remediation Suggestions
-
Validate
PICQER_SUBDOMAINas exactly one DNS label before using it:ts const SUBDOMAIN_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/i; if (!SUBDOMAIN_PATTERN.test(subdomain)) { throw new Error('Invalid Picqer subdomain'); } -
Construct and verify the expected hostname separately:
ts const hostname = `${subdomain}.picqer.com`; const url = new URL(`/api/v1${path}`, `https://${hostname}`); if ( url.protocol !== 'https:' || url.hostname !== hostname || url.port !== '' ) { throw new Error('Invalid Picqer API URL'); } -
Prefer an allowlist containing the exact permitted Picqer tenant hostname when the deployment uses a single known tenant.
-
Validate
pathas an internal API path and reject absolute URLs, backslashes, control characters, and unexpected traversal sequences before URL construction. -
Keep outbound network controls in place so the process can connect only to the approved Picqer hostname where practical.
-
If malicious configuration may already have been used, revoke and rotate
PICQER_API_KEY, inspect outbound request logs for unexpected hosts, and review Picqer audit logs for unauthorized API activity.
-
