Affected Versions
| Affected | not applicable (first-party code) |
| Fixed in | not applicable (first-party code) — see PR for fix commit |
| Ecosystem | JavaScript (Node.js/Electron) |
| CVE / GHSA | not assigned |
| CWE | CWE-494: Download of Code Without Integrity Check |
The Vulnerability Explained
The parseUpdate function in the Updater component accepted server responses containing arbitrary downloadUrl and infoUrl values without any cryptographic verification. The original implementation extracted these URLs directly from the JSON response:
return {
updateUrl: sortedReleases[0].downloadUrl,
infoUrl: sortedReleases[0].infoUrl,
version: sortedReleases[0].semver,
updateAvailable:
semverCompare(currentVersion, sortedReleases[0].semver) < 0,
};
The vulnerability lies in the complete absence of integrity verification. An attacker who compromised the update server, poisoned DNS, or positioned themselves as a man-in-the-middle could return a response pointing downloadUrl to https://evil.com/malware.exe. The application would then download and potentially execute this payload during the auto-update flow.
The regression test demonstrates the attack precisely: payloads like { updateUrl: 'https://evil.com/malware.exe', infoUrl: 'https://evil.com', version: '9.9.9' } would have been accepted and processed. Even a payload with a checksum field or empty signature passed through without verification—the code simply never checked these fields.
The Fix
The remediation adds an isTrustedUrl helper that validates both protocol and hostname before accepting any URL from the server response:
const isTrustedUrl = (url) => {
try {
const parsed = new URL(url);
return (
parsed.protocol === 'https:' && parsed.hostname === 'codedead.com'
);
} catch {
return false;
}
};
if (!isTrustedUrl(downloadUrl) || !isTrustedUrl(infoUrl)) {
throw new Error('Update metadata contains an untrusted URL');
}
This change transforms the function from passive extraction to active validation. The destructured downloadUrl and infoUrl from sortedReleases[0] now undergo mandatory scrutiny. The fix addresses the root cause by ensuring that even if an attacker compromises the transport layer or the update server itself, the application will only accept updates from the explicitly trusted origin.
Note that this is a partial fix—true supply chain security requires cryptographic signature verification of the downloaded executable itself, not just transport-layer and origin validation. However, this change eliminates the trivial MITM and server compromise vectors.
Key Takeaways
-
Destructured values from remote responses are attacker-controlled until proven otherwise: The pattern
const { downloadUrl, infoUrl } = sortedReleases[0]assumes trust in data that crossed a network boundary. Always validate before use. -
new URL()parsing with protocol and hostname checks prevents origin confusion: TheisTrustedUrlimplementation uses the WHATWG URL standard to parse, then validates both scheme and host. This is more robust than string prefix matching which can be bypassed withhttps://attacker.com@codedead.comor similar tricks. -
Auto-update mechanisms are critical security boundaries requiring defense in depth: Transport security (TLS) alone is insufficient. This fix layers origin validation on top of HTTPS, reducing the attack surface even if certificates are compromised.
-
Empty or present-but-unverified integrity fields provide no security: The original code likely had
checksumorsignaturefields in the response schema, but since they were never verified, their presence created false confidence. Either verify cryptographically or reject.
How Orbis AppSec Detected This
Source: The downloadUrl and infoUrl fields from the remote server response in the Updater's parseUpdate function
Sink: The return statement that passes these URLs to the caller for subsequent download and execution
Missing control: No cryptographic signature verification, checksum validation, or URL origin restrictions on attacker-controlled update metadata
CWE: CWE-494 — Download of Code Without Integrity Check
Fix: Added isTrustedUrl validation requiring HTTPS protocol and codedead.com hostname before accepting any update metadata
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
The parseUpdate vulnerability illustrates how auto-update mechanisms become critical supply chain attack vectors when they trust remote metadata without verification. The fix demonstrates practical defense in depth: combining transport security with explicit origin allowlisting. Developers implementing similar functionality should consider this a minimum bar—full cryptographic verification of downloaded binaries remains essential for complete protection.