up
This commit is contained in:
61
plugins/scanner/node/runtime-hooks/runtime-esm-loader.mjs
Normal file
61
plugins/scanner/node/runtime-hooks/runtime-esm-loader.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
// Runtime ESM loader for StellaOps Scanner runtime evidence
|
||||
// Usage: node --experimental-loader=./runtime-esm-loader.mjs app.mjs
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import crypto from 'crypto';
|
||||
import { fileURLToPath, pathToFileURL } from 'url';
|
||||
|
||||
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();
|
||||
const loaderId = hashLoaderId(import.meta.url);
|
||||
|
||||
function hashLoaderId(value) {
|
||||
return crypto.createHash('sha256').update(value || '').digest('hex');
|
||||
}
|
||||
|
||||
function scrub(p) {
|
||||
if (!p) return p;
|
||||
try {
|
||||
const absolute = p.startsWith('file:') ? fileURLToPath(p) : p;
|
||||
const rel = path.relative(root, absolute);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolve(specifier, context, next) {
|
||||
const parent = context.parentURL ? scrub(context.parentURL) : undefined;
|
||||
const target = scrub(specifier);
|
||||
|
||||
emit({
|
||||
type: 'edge',
|
||||
from: parent,
|
||||
to: target,
|
||||
reason: 'runtime-import',
|
||||
loaderId
|
||||
});
|
||||
|
||||
return next(specifier, context, next);
|
||||
}
|
||||
|
||||
export async function load(url, context, next) {
|
||||
const pathOrUrl = scrub(url);
|
||||
emit({
|
||||
type: 'component',
|
||||
path: pathOrUrl,
|
||||
reason: 'runtime-load',
|
||||
loaderId
|
||||
});
|
||||
|
||||
return next(url, context, next);
|
||||
}
|
||||
49
plugins/scanner/node/runtime-hooks/runtime-require-hook.js
Normal file
49
plugins/scanner/node/runtime-hooks/runtime-require-hook.js
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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);
|
||||
};
|
||||
Reference in New Issue
Block a user