#!/usr/bin/env node /** * Installs and verifies Trivy binary against checksums lockfile. */ const fs = require('node:fs'); const path = require('node:path'); const os = require('node:os'); const cp = require('node:child_process'); const { mapArch, parseChecksums, verifyFileSha256 } = require('./verifier.js'); function main() { const version = process.env.TRIVY_VERSION || '0.74.0'; const homeDir = os.homedir(); const binDir = path.join(homeDir, '.local', 'bin'); const cacheDir = path.join(homeDir, '.cache', 'trivy-bin'); fs.mkdirSync(binDir, { recursive: true }); fs.mkdirSync(cacheDir, { recursive: true }); // Expose bin directory to GITHUB_PATH if running in Actions runner if (process.env.GITHUB_PATH) { fs.appendFileSync(process.env.GITHUB_PATH, `${binDir}\n`); } const unameArch = os.arch() === 'x64' ? 'x86_64' : (os.arch() === 'arm64' ? 'ARM64' : os.arch()); const tArch = mapArch(unameArch); const tarball = `trivy_${version}_Linux-${tArch}.tar.gz`; const tarballPath = path.join(cacheDir, tarball); const checksumsFile = path.resolve(__dirname, '..', 'checksums.txt'); if (!fs.existsSync(checksumsFile)) { console.error(`::error::Checksums lockfile not found at ${checksumsFile}`); process.exit(1); } const checksums = parseChecksums(fs.readFileSync(checksumsFile, 'utf8')); const expectedHash = checksums.get(tarball); if (!expectedHash) { console.error(`::error::Tarball ${tarball} not found in checksums.txt`); process.exit(1); } if (fs.existsSync(tarballPath) && verifyFileSha256(tarballPath, expectedHash)) { console.log('Cached Trivy archive verified against lockfile.'); } else { console.log('Archive missing or checksum mismatch; downloading...'); const downloadUrl = `https://github.com/aquasecurity/trivy/releases/download/v${version}/${tarball}`; cp.execFileSync('curl', ['-sfLO', downloadUrl, '--output-dir', cacheDir], { stdio: 'inherit' }); if (!verifyFileSha256(tarballPath, expectedHash)) { console.error(`::error::Downloaded archive ${tarball} failed SHA256 checksum verification!`); process.exit(1); } console.log('Downloaded Trivy archive verified successfully.'); } // Extract binary cp.execFileSync('tar', ['-xzf', tarballPath, '-C', binDir, 'trivy'], { stdio: 'inherit' }); const trivyBin = path.join(binDir, 'trivy'); if (fs.existsSync(trivyBin)) { fs.chmodSync(trivyBin, 0o755); console.log(`Trivy ${version} installed and verified successfully at ${trivyBin}`); } else { console.error('::error::Failed to extract trivy binary from tarball.'); process.exit(1); } } if (require.main === module) { main(); } module.exports = { main };