ktg-plugin-marketplace/plugins/llm-security/bin/llm-security.mjs
Kjell Tore Guttormsen 2c33e9cc64 feat(ci): add CI/CD integration — --fail-on, --compact, pipeline templates
Add threshold-based exit codes (--fail-on <severity>) and compact
output mode (--compact) to scan-orchestrator and CLI. Pipeline
templates for GitHub Actions, Azure DevOps, GitLab CI with SARIF
upload. CI/CD guide with Schrems II/NSM compliance documentation.
npm publish preparation (files whitelist, .npmignore). Policy ci
section for distributable CI defaults. Version 6.1.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 14:59:05 +02:00

78 lines
2.4 KiB
JavaScript
Executable file

#!/usr/bin/env node
// llm-security CLI — standalone entry point for llm-security scanners.
// Usage: llm-security <subcommand> [args]
// Works without Claude Code. Zero dependencies.
import { spawn } from 'node:child_process';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(__dirname, '..');
const PKG = JSON.parse(readFileSync(resolve(ROOT, 'package.json'), 'utf8'));
const USAGE = `llm-security v${PKG.version} — AI security scanning for Claude Code projects
Usage: llm-security <command> [options]
Commands:
scan <target> [--fail-on <critical|high|medium|low>] [--compact]
[--format sarif] [--output-file <path>] [--baseline] [--save-baseline]
Run deterministic deep-scan (10 scanners)
deep-scan <target>
Alias for scan
posture <target>
Quick security posture assessment (16 categories)
audit-bom <target> [--output-file <path>]
Generate AI Bill of Materials (CycloneDX 1.6)
benchmark [--adaptive] [--category <name>]
Run attack simulation benchmark
Options:
--help Show this help
--version Show version
`;
const [subcommand, ...rest] = process.argv.slice(2);
if (!subcommand || subcommand === '--help' || subcommand === '-h') {
process.stdout.write(USAGE);
process.exit(0);
}
if (subcommand === '--version' || subcommand === '-v') {
process.stdout.write(`${PKG.version}\n`);
process.exit(0);
}
// Map subcommands to scanner scripts and their arguments
const COMMANDS = {
scan: { script: 'scanners/scan-orchestrator.mjs' },
'deep-scan': { script: 'scanners/scan-orchestrator.mjs' },
posture: { script: 'scanners/posture-scanner.mjs' },
'audit-bom': { script: 'scanners/ai-bom-generator.mjs' },
benchmark: { script: 'scanners/attack-simulator.mjs', prependArgs: ['--benchmark', '--json'] },
};
const cmd = COMMANDS[subcommand];
if (!cmd) {
process.stderr.write(`Unknown command: ${subcommand}\n\n`);
process.stderr.write(USAGE);
process.exit(1);
}
const scriptPath = resolve(ROOT, cmd.script);
const args = [...(cmd.prependArgs || []), ...rest];
const child = spawn('node', [scriptPath, ...args], {
cwd: process.cwd(),
stdio: ['ignore', 'pipe', 'pipe'],
});
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
child.on('close', (code) => {
process.exitCode = code ?? 1;
});