// Runtime require hook for StellaOps Scanner runtime evidence // Usage: node -r ./runtime-require-hook.js app.js const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); const outPath = process.env.SCANNER_NODE_RUNTIME_OUT || path.join(process.cwd(), 'node-runtime-evidence.ndjson'); const root = process.env.SCANNER_NODE_ROOT || process.cwd(); function hashLoaderId(value) { return crypto.createHash('sha256').update(value || '').digest('hex'); } function scrub(p) { if (!p) return p; try { const rel = path.relative(root, p); return rel.startsWith('..') ? p : rel.split(path.sep).join('/'); } catch { return p; } } function emit(record) { try { fs.appendFileSync(outPath, JSON.stringify(record) + '\n'); } catch { // best-effort: ignore write failures } } const originalLoad = module.constructor._load; module.constructor._load = function (request, parent, isMain) { const from = parent && parent.filename ? scrub(parent.filename) : undefined; const to = scrub(request); const loaderId = hashLoaderId(__filename); emit({ type: 'edge', from, to, reason: 'runtime-require', loaderId, isMain: !!isMain }); return originalLoad.apply(this, arguments); };