Affected Versions
| Affected | not applicable (first-party code) |
| Fixed in | not applicable (first-party code) — see PR for fix commit |
| Ecosystem | npm |
| CVE / GHSA | not assigned |
| CWE | unknown |
The Vulnerability Explained
The Slim CLI's check command performed an unverified fetch against a user-influenced remote endpoint. When users ran the version check, the tool constructed a URL from the local package's repository metadata and fetched package.json directly from raw.githubusercontent.com:
const githubRepo = pkg.repository.url.split("git+https://github.com/")[1].trim().split(".git")[0]
const res = await fetch("https://raw.githubusercontent.com/" + githubRepo + "/main/package.json")
const githubPkg = await res.json()
This pattern had three critical gaps:
-
No input validation on the repository identifier: The
githubRepovalue was extracted via string manipulation without validating it matched expected GitHub repository format (owner/repo). -
No HTTP status verification: The response was parsed as JSON regardless of whether the request succeeded (200 OK) or failed (404, 500, etc.).
-
No response schema validation: The parsed JSON was trusted to contain a valid
versionfield without checking its type or format.
An attacker exploiting this could manipulate the version check output through several vectors:
- Repository hijacking: If the original repository was renamed or the account compromised, GitHub's redirect or attacker-controlled replacement would be trusted.
- DNS spoofing or MITM: Without certificate pinning, an attacker on the network path could serve arbitrary JSON.
- Repository identifier manipulation: If the local
package.jsonrepository URL was somehow attacker-controlled, the constructed fetch URL could be manipulated.
The real impact was subtle but serious: the version check's output influenced user trust in their installation. A manipulated "latest version" response could push users toward downloading malicious updates from attacker-controlled sources.
The Fix
The remediation adds defense-in-depth through three layers of validation:
Repository identifier validation: Before constructing any URL, the extracted repository string is validated against a strict regex:
if(!/^[\w.-]+\/[\w.-]+$/.test(githubRepo)) {
error("Unable to determine a valid GitHub repository for version check")
return
}
This prevents path traversal, unexpected URL structures, or malformed identifiers from reaching the fetch call.
HTTP status checking: The response is now verified to succeed before parsing:
if(!res.ok) {
error(`Version check failed: received HTTP ${res.status} from GitHub`)
return
}
Response schema validation: The parsed JSON is validated to contain a properly formatted semantic version string:
if(typeof githubPkg?.version !== "string" || !/^\d+\.\d+\.\d+/.test(githubPkg.version)) {
error("Version check failed: unexpected response format")
return
}
The complete fixed path now wraps the entire operation in try-catch error handling, ensuring network or parsing failures fail safely rather than leaking stack traces or undefined behavior.
Key Takeaways
-
Never trust DNS or TLS alone for remote metadata: Certificate validation prevents passive eavesdropping but not active attacks against the endpoint itself. Always validate the semantic content of security-relevant responses.
-
Validate identifiers before URL construction: User-influenced or parsed values used in URL building need strict format validation to prevent open redirects, SSRF, or unexpected endpoint targeting.
-
HTTP
okstatus is not implicit: The Fetch API does not throw on 404 or 500 responses. Explicit status checking is required before trusting response bodies. -
JSON parsing success does not imply schema validity: Always verify that parsed objects contain expected types and formats before using them in security-relevant decisions.
-
Version checks are security boundaries: Users rely on version information to decide when to update. Compromising this channel is a viable software supply chain attack vector.
How Orbis AppSec Detected This
Source: The pkg.repository.url property parsed from the local package.json
Sink: The fetch() call to raw.githubusercontent.com with a dynamically constructed URL containing unvalidated path components
Missing control: No validation of the repository identifier format, no verification of HTTP response status, and no schema validation on the parsed JSON response
CWE: unknown — this pattern spans multiple weakness categories including inadequate input validation (CWE-20) and insufficient verification of data authenticity (CWE-345)
Fix: Added regex validation on repository identifiers, explicit HTTP status checking, and strict schema validation requiring semantic version format on the returned version field
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
This vulnerability illustrates how even "simple" version check features can become supply chain attack vectors when they fetch and trust remote content without verification. The Slim CLI's fix demonstrates proper defense-in-depth: validate inputs before use, verify operations succeeded, and confirm outputs match expected schemas before acting on them. For CLI tools that fetch remote metadata, these controls are essential to prevent attackers from manipulating user trust and update decisions.