How Unsafe Package Download Verification Happens in Shell Scripts and How to Fix It
In the l1vm project's install/install-DragonFly.sh script, we discovered a high-severity supply chain vulnerability that could allow attackers to inject malicious code into systems during the installation process. The script downloaded a base package from an external server and immediately extracted and installed it—without verifying that the package hadn't been tampered with or replaced by an attacker.
This is a critical flaw in software supply chain security. Let's examine how it happened, why it's dangerous, and how the fix prevents future exploitation.
Introduction: When Installation Scripts Become Attack Vectors
The install/install-DragonFly.sh file is responsible for bootstrapping a development environment. Like many installation scripts, it downloads a pre-built package (l1vm-base-pkg.tar.bz2) from https://midnight-coding.de/blog/assets/l1vm/ and installs it system-wide.
Here's the problem: the script trusts that whatever is downloaded is legitimate, without any verification.
This creates a dangerous scenario:
- If the server hosting the package is compromised, attackers can replace the legitimate package with malicious code
- If an attacker performs a DNS hijack or BGP hijack, they can redirect downloads to their own server
- Even with HTTPS, a compromised server certificate or certificate authority can serve malicious content
- The script runs with sudo privileges, meaning any injected code executes as root
The vulnerability chain is short but devastating: compromised download server → malicious package downloaded → executed with root privileges → complete system compromise.
The Vulnerability Explained: Missing Checksum Verification
Let's examine the original vulnerable code:
echo "Install base package with includes and programs..."
../scripts/download-pkg.sh https://midnight-coding.de/blog/assets/l1vm/l1vm-base-pkg.tar.bz2 l1vm-base-pkg.tar.bz2
cd ..
The problem: After downloading l1vm-base-pkg.tar.bz2, the script immediately proceeds to extract and install it. There is no verification that:
- The file hasn't been modified in transit (though HTTPS helps here)
- The file hasn't been replaced on the server
- The file matches what the developers intended to distribute
- The file is actually a valid tar.bz2 archive and not malicious content
Attack Scenario: Server Compromise
Imagine an attacker compromises midnight-coding.de:
- The attacker replaces
l1vm-base-pkg.tar.bz2with a malicious archive containing a backdoor - A developer runs the installation script:
bash install/install-DragonFly.sh - The script downloads the malicious package over HTTPS (which protects transport, not content)
- The script extracts and installs the malicious package with
sudoprivileges - The backdoor is now running on the developer's system with root access
The developer has no way to detect the compromise because the script provides no integrity check.
Why HTTPS Isn't Enough
Developers often assume HTTPS provides complete security. It doesn't. HTTPS protects against:
- Network eavesdropping
- Man-in-the-middle attacks on the network path
HTTPS does not protect against:
- Compromised servers (the source of the content)
- Compromised or malicious certificates
- DNS hijacking to a malicious server with a valid certificate for that domain
- Insider threats at the hosting provider
Cryptographic verification of the package itself is essential.
The Fix: Implementing SHA256 Checksum Verification
The fix adds mandatory checksum verification before installation:
echo "Install base package with includes and programs..."
# Known-good SHA256 checksum for l1vm-base-pkg.tar.bz2 - update when the package is updated
EXPECTED_SHA256="PLACEHOLDER_REPLACE_WITH_KNOWN_SHA256_HASH"
../scripts/download-pkg.sh https://midnight-coding.de/blog/assets/l1vm/l1vm-base-pkg.tar.bz2 l1vm-base-pkg.tar.bz2
ACTUAL_SHA256=$(sha256 -q l1vm-base-pkg.tar.bz2 2>/dev/null || openssl dgst -sha256 l1vm-base-pkg.tar.bz2 2>/dev/null | awk '{print $NF}')
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
echo "ERROR: Checksum verification FAILED for l1vm-base-pkg.tar.bz2!"
echo "Expected: $EXPECTED_SHA256"
echo "Actual: $ACTUAL_SHA256"
echo "The download may be corrupted or tampered with. Aborting installation."
rm -f l1vm-base-pkg.tar.bz2
exit 1
fi
echo "Checksum verified OK."
cd ..
What Changed and Why
Line 4-5: Define the expected SHA256 hash as a variable. This hash is the cryptographic fingerprint of the legitimate package. It's hardcoded in the script so it can't be modified by an attacker who compromises the server.
Line 8: Calculate the actual SHA256 hash of the downloaded file. The command tries two approaches:
- sha256 -q (BSD/macOS syntax)
- openssl dgst -sha256 (GNU/Linux fallback)
Lines 9-16: The critical security check. If the calculated hash doesn't match the expected hash, the script:
- Prints a clear error message
- Deletes the suspicious file (preventing accidental installation)
- Exits with error code 1 (preventing further execution)
Line 17: Only if verification succeeds does the script continue.
Why This Specific Approach
- Portable: Works on Linux, BSD, and macOS by trying multiple hash commands
- Fail-safe: If verification fails, the script stops immediately
- Tamper-evident: Prints both expected and actual hashes for debugging
- Self-contained: Doesn't require external tools beyond what's in the base system
- Clear communication: Users see exactly what failed and why
Prevention & Best Practices
For Installation Scripts
- Always verify downloads: Use cryptographic checksums (SHA256 or stronger) before installation
- Store hashes separately: Keep known-good hashes in version control, not on the download server
- Document hash sources: Explain where hashes come from and how they were generated
- Fail securely: If verification fails, abort immediately and clean up partial downloads
- Consider GPG signatures: For maximum security, use GPG signatures in addition to checksums
For Package Maintainers
- Publish checksums: Include SHA256 hashes on your website alongside downloads
- Use signed releases: Create GPG-signed tags in version control
- Automate hash generation: Generate hashes during your build process
- Monitor for tampering: Set up alerts for unexpected file modifications
Detection and Tools
Static analysis can detect this vulnerability:
- Semgrep: Rules can identify download commands not followed by verification
- ShellCheck: Can flag suspicious patterns in shell scripts
- Custom linters: Enforce checksum verification in installation scripts
Runtime monitoring:
- File integrity monitoring: Tools like aide or tripwire can detect unauthorized changes
- Supply chain scanning: Solutions like syft or grype analyze downloaded artifacts
Security Standards
- CWE-494: Download of Code Without Integrity Check
- CWE-295: Improper Certificate Validation
- OWASP A06:2021: Vulnerable and Outdated Components
- NIST SP 800-53 SI-7: Software, Firmware, and Information Integrity
Key Takeaways
- HTTPS is transport security, not content security: Always verify the content itself, not just the connection
- Installation scripts run with elevated privileges: Every download in an installation script is a potential attack vector—verify everything
- Checksum verification is non-negotiable for supply chain security: Without it, a compromised server can inject arbitrary code
- Fail-safe design matters: The script must abort immediately and cleanly if verification fails, not continue with a warning
- Keep hashes in version control: Store known-good hashes alongside your installation script so they can't be modified by a server compromise
How Orbis AppSec Detected This
Source: External URL in install/install-DragonFly.sh:5 — the download destination is controlled by a remote server, making it an untrusted data source
Sink: The download-pkg.sh script call followed immediately by extraction and installation — the downloaded package is executed without verification
Missing control: No integrity verification (checksum or signature) between download and installation
CWE: CWE-494 (Download of Code Without Integrity Check) and CWE-295 (Improper Certificate Validation)
Fix: Added SHA256 checksum verification that compares the downloaded file's hash against a known-good value stored in the installation script before proceeding
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
Supply chain security is one of the most critical—and most overlooked—aspects of secure development. Installation scripts are often the first code that runs on a developer's or user's system, frequently with elevated privileges. This makes them prime targets for attackers.
The vulnerability in install/install-DragonFly.sh demonstrates how a simple omission—failing to verify downloaded packages—can create a critical security risk. By adding SHA256 checksum verification, the fix ensures that only legitimate, unmodified packages are installed.
As you review your own installation scripts, deployment pipelines, and package management processes, remember: never trust a download. Always verify integrity.
References
- CWE-494: Download of Code Without Integrity Check
- CWE-295: Improper Certificate Validation
- OWASP: Vulnerable and Outdated Components
- NIST SP 800-53 SI-7: Software, Firmware, and Information Integrity
- Semgrep: Insecure download patterns
- GitHub PR: fix: the installation scripts download a base packag... in...