Back to Blog
critical SEVERITY4 min read

Slim CLI Unverified Remote Fetch in Version Check

The Slim CLI's version check command fetched remote package metadata without integrity verification, enabling attackers to serve malicious responses through repository hijacking or man-in-the-middle attacks. The fix adds input validation, HTTP status checking, and response schema verification to ensure only legitimate version data is processed.

O
By Orbis AppSec
•Technically reviewed by Anupam Mediratta•Published September 30, 2026•Reviewed October 1, 2026

Answer Summary

The Slim CLI's `check` command in versions prior to the fix fetched package.json from raw.githubusercontent.com using a dynamically constructed URL without integrity verification, certificate pinning, or signature validation. An attacker who compromised the GitHub repository, performed DNS spoofing, or positioned as a man-in-the-middle could serve a malicious package.json response that would be parsed and trusted by the CLI. The fix introduces regex validation on the repository identifier, HTTP response status checking, and strict schema validation on the returned version field. CWE status is unknown.

Vulnerability at a Glance

cweN/A
fixAdded input validation, status checking, and schema validation on remote response
riskRepository hijacking or MITM leading to trusted injection of malicious metadata
languageJavaScript (Node.js)
root causefetch() to raw.githubusercontent.com without integrity verification or response validation
vulnerabilityUnverified remote resource fetch

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:

  1. No input validation on the repository identifier: The githubRepo value was extracted via string manipulation without validating it matched expected GitHub repository format (owner/repo).

  2. No HTTP status verification: The response was parsed as JSON regardless of whether the request succeeded (200 OK) or failed (404, 500, etc.).

  3. No response schema validation: The parsed JSON was trusted to contain a valid version field 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.json repository 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 ok status 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.

Prevention and further reading

Frequently Asked Questions

Does the Slim CLI still fetch from raw.githubusercontent.com after the fix, or was the remote check removed entirely?

The remote check is preserved, but now validates the repository identifier format with `/^[\w.-]+\/[\w.-]+$/` before constructing the URL, verifies the HTTP response status, and validates that the returned version is a string matching semantic versioning format.

What specific validation prevents a malicious package.json with a crafted version field from being accepted?

The fix requires `typeof githubPkg?.version === "string"` and validates against `/^\d+\.\d+\.\d+/`, rejecting any response where the version is not a properly formatted semantic version string.

If an attacker returns a 200 OK response with a valid-looking version but malicious other fields, can they still influence downstream behavior?

The fix only validates the version field format, so other fields in the response could still be processed. However, the original code only accessed `githubPkg.version`, limiting the attack surface to version string manipulation rather than arbitrary code execution.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #6

Related Articles

critical

Lampa Desktop Auto-Update Heuristic Bypass: Execution of Unverified

Lampa Desktop's auto-update mechanism downloaded JavaScript and CSS from `raw.githubusercontent.com` using only heuristic validation—file size thresholds and string pattern matching—that attackers could trivially satisfy. The fix introduces cryptographic integrity verification by cross-referencing Git blob hashes from the GitHub Contents API, ensuring downloaded code matches the repository's authoritative state before execution.

high

adm-zip 0.6.0 Preserves SUID Bits From ZIPs: CVE-2026-102282

The `adm-zip` dependency resolved to 0.6.0 in this project's dependency tree, a version affected by CVE-2026-102282: during extraction it applies the Unix permission bits stored in each ZIP entry's external file attributes verbatim, including the setuid (`04000`), setgid (`02000`), and sticky bits. An attacker who controls an archive passed to `extractAllTo()` or `extractEntryTo()` can therefore have the extractor create a setuid binary owned by whatever user the extraction process runs as. The

high

requestInput() Type Confusion: NaN and Object Bypass in JavaScript

The `requestInput()` utility function lacked validation on its `type` parameter and failed to handle `NaN` results from float conversions, creating a type confusion weakness. An attacker could supply malformed inputs that propagate unhandled `NaN` values or unexpected object types through the type system. The fix adds explicit guards against `NaN` type parameters and rejects non-primitive type values.

critical

No Rate Limit on /api/uploads/presign Enables DoS

The `/api/uploads/presign` endpoint accepted unlimited concurrent requests to generate storage presigned URLs, giving an attacker a free lever to exhaust storage-provider quotas and server resources. The fix adds an `express-rate-limit` middleware capping each client to 30 requests per minute on that route.

high

CVE-2026-54673: builder-util-runtime Leaks Auth Headers on Redirect

electron-updater and electron-builder rely on builder-util-runtime to fetch update manifests and artifacts over HTTP. A flaw in that shared HTTP executor allowed credential headers attached to the original update-feed request to be re-sent after a redirect, exposing them to any host the redirect pointed to. The project fixes this by upgrading builder-util-runtime to 9.7.0 and collapsing a duplicate, older copy of the package that electron-updater had pinned on its own.

high

image-size 1.2.1 DoS: Zero-Valued Dimensions in Image Buffer Parser

A high-severity denial-of-service vulnerability in image-size 1.2.1 allows attackers to crash Node.js services using malicious image buffers with zero-valued dimensions. The fix removes the vulnerable `queue` dependency and tightens dimension validation in version 2.0.3.