T09 · Insecure Skill Coding Practices
- Location
cli.mjs:55- Finding
Basic Authentication Credentials May Be Transmitted over Plaintext HTTP
- Content
View full analysis
Vulnerability Details
File Location:
cli.mjs:55-58, with credential transmission atcli.mjs:199-206andcli.mjs:215-221
Vulnerability Type: Insecure transport of reusable credentials
Risk Level: HighVulnerable Code
js function buildBaseUrl(domain) { if (!domain) return ''; if (domain.startsWith('http://') || domain.startsWith('https://')) return domain.replace(/\/$/, ''); return `https://${domain.replace(/\/$/, '')}`; }js async function requestJson(baseUrl, username, password, pathAndQuery) { const auth = Buffer.from(`${username}:${password}`).toString('base64'); const url = `${baseUrl}${pathAndQuery}`; const response = await fetch(url, { headers: { 'Accept': 'application/json', 'Authorization': `Basic ${auth}`, }, }); const text = await response.text(); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${text.slice(0, 500)}`); } return text; } async function requestBinary(baseUrl, username, password, pathAndQuery) { const auth = Buffer.from(`${username}:${password}`).toString('base64'); const url = `${baseUrl}${pathAndQuery}`; const response = await fetch(url, { headers: { 'Authorization': `Basic ${auth}`, }, });Technical Analysis
The URL builder explicitly accepts both HTTPS and plaintext HTTP URLs. The request functions then place the configured ServiceNow username and password in an HTTP Basic Authentication header for every request.
Basic Authentication only Base64-encodes the credentials; it does not encrypt them. If the configured domain uses
http://, any party able to observe or modify the network connection can recover the original username and password. This is unnecessary for the declared functionality because ServiceNow API authentication can and should be restricted to HTTPS.The destination is user-configurable. No hidden third-party exfiltration endpoint was found, but the lack of transport enforcement makes the ...[truncated 1235 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the configured base URL with the standard
URLclass and reject every protocol other thanhttps:. - Reject URLs containing embedded usernames or passwords.
- Consider restricting destination hostnames to an organization-managed allowlist or an approved ServiceNow domain suffix.
- Do not silently downgrade or redirect authenticated requests to HTTP. Explicitly verify redirect behavior for credential-bearing requests.
- Prefer scoped, short-lived OAuth tokens over reusable account passwords.
- Require a dedicated ServiceNow account with server-enforced read-only roles; do not rely solely on the CLI’s use of GET.
- Add automated tests proving that
http://URLs, malformed URLs, and redirects to non-HTTPS destinations are rejected before an Authorization header is sent.
A hardened URL builder should follow this pattern:
js function buildBaseUrl(domain) { if (!domain) return ''; const candidate = /^[a-z][a-z0-9+.-]*:\/\//i.test(domain) ? domain : `https://${domain}`; const url = new URL(candidate); if (url.protocol !== 'https:') { throw new Error('Only HTTPS ServiceNow endpoints are allowed'); } if (url.username || url.password) { throw new Error('Credentials must not be embedded in the ServiceNow URL'); } return url.origin; }- Parse the configured base URL with the standard
