hackmyagent 0.11.12 → 0.11.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -15
- package/dist/arp/engine/correlation.d.ts +27 -0
- package/dist/arp/engine/correlation.d.ts.map +1 -0
- package/dist/arp/engine/correlation.js +95 -0
- package/dist/arp/engine/correlation.js.map +1 -0
- package/dist/arp/engine/event-engine.d.ts +1 -0
- package/dist/arp/engine/event-engine.d.ts.map +1 -1
- package/dist/arp/engine/event-engine.js +16 -0
- package/dist/arp/engine/event-engine.js.map +1 -1
- package/dist/arp/index.d.ts +2 -0
- package/dist/arp/index.d.ts.map +1 -1
- package/dist/arp/index.js +5 -1
- package/dist/arp/index.js.map +1 -1
- package/dist/arp/intelligence/anomaly.d.ts +4 -0
- package/dist/arp/intelligence/anomaly.d.ts.map +1 -1
- package/dist/arp/intelligence/anomaly.js +71 -0
- package/dist/arp/intelligence/anomaly.js.map +1 -1
- package/dist/arp/intelligence/nanomind-l1.d.ts +72 -0
- package/dist/arp/intelligence/nanomind-l1.d.ts.map +1 -0
- package/dist/arp/intelligence/nanomind-l1.js +268 -0
- package/dist/arp/intelligence/nanomind-l1.js.map +1 -0
- package/dist/arp/monitors/network.d.ts +16 -1
- package/dist/arp/monitors/network.d.ts.map +1 -1
- package/dist/arp/monitors/network.js +55 -1
- package/dist/arp/monitors/network.js.map +1 -1
- package/dist/arp/proxy/server.d.ts +7 -0
- package/dist/arp/proxy/server.d.ts.map +1 -1
- package/dist/arp/proxy/server.js +24 -0
- package/dist/arp/proxy/server.js.map +1 -1
- package/dist/attack-engine/feedback-loop.d.ts +36 -0
- package/dist/attack-engine/feedback-loop.d.ts.map +1 -0
- package/dist/attack-engine/feedback-loop.js +261 -0
- package/dist/attack-engine/feedback-loop.js.map +1 -0
- package/dist/attack-engine/index.d.ts +13 -0
- package/dist/attack-engine/index.d.ts.map +1 -0
- package/dist/attack-engine/index.js +21 -0
- package/dist/attack-engine/index.js.map +1 -0
- package/dist/attack-engine/payload-generator.d.ts +21 -0
- package/dist/attack-engine/payload-generator.d.ts.map +1 -0
- package/dist/attack-engine/payload-generator.js +210 -0
- package/dist/attack-engine/payload-generator.js.map +1 -0
- package/dist/attack-engine/target-reader.d.ts +15 -0
- package/dist/attack-engine/target-reader.d.ts.map +1 -0
- package/dist/attack-engine/target-reader.js +152 -0
- package/dist/attack-engine/target-reader.js.map +1 -0
- package/dist/attack-engine/training-pipeline.d.ts +57 -0
- package/dist/attack-engine/training-pipeline.d.ts.map +1 -0
- package/dist/attack-engine/training-pipeline.js +146 -0
- package/dist/attack-engine/training-pipeline.js.map +1 -0
- package/dist/attack-engine/types.d.ts +133 -0
- package/dist/attack-engine/types.d.ts.map +1 -0
- package/dist/attack-engine/types.js +22 -0
- package/dist/attack-engine/types.js.map +1 -0
- package/dist/cli.js +210 -12
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/output/asff.d.ts +37 -0
- package/dist/output/asff.d.ts.map +1 -0
- package/dist/output/asff.js +112 -0
- package/dist/output/asff.js.map +1 -0
- package/dist/semantic/index.d.ts +2 -0
- package/dist/semantic/index.d.ts.map +1 -1
- package/dist/semantic/index.js +9 -1
- package/dist/semantic/index.js.map +1 -1
- package/dist/semantic/nanomind-analyzer.d.ts +77 -0
- package/dist/semantic/nanomind-analyzer.d.ts.map +1 -0
- package/dist/semantic/nanomind-analyzer.js +165 -0
- package/dist/semantic/nanomind-analyzer.js.map +1 -0
- package/dist/simulation/engine.d.ts +69 -0
- package/dist/simulation/engine.d.ts.map +1 -0
- package/dist/simulation/engine.js +297 -0
- package/dist/simulation/engine.js.map +1 -0
- package/dist/simulation/index.d.ts +15 -0
- package/dist/simulation/index.d.ts.map +1 -0
- package/dist/simulation/index.js +31 -0
- package/dist/simulation/index.js.map +1 -0
- package/dist/simulation/llm-executor.d.ts +58 -0
- package/dist/simulation/llm-executor.d.ts.map +1 -0
- package/dist/simulation/llm-executor.js +297 -0
- package/dist/simulation/llm-executor.js.map +1 -0
- package/dist/simulation/mock-tools.d.ts +35 -0
- package/dist/simulation/mock-tools.d.ts.map +1 -0
- package/dist/simulation/mock-tools.js +181 -0
- package/dist/simulation/mock-tools.js.map +1 -0
- package/dist/simulation/probes.d.ts +17 -0
- package/dist/simulation/probes.d.ts.map +1 -0
- package/dist/simulation/probes.js +295 -0
- package/dist/simulation/probes.js.map +1 -0
- package/dist/simulation/types.d.ts +79 -0
- package/dist/simulation/types.d.ts.map +1 -0
- package/dist/simulation/types.js +25 -0
- package/dist/simulation/types.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1734,15 +1734,18 @@ Examples:
|
|
|
1734
1734
|
.option('--dry-run', 'Preview fixes without applying them (use with --fix)')
|
|
1735
1735
|
.option('--ignore <checks>', 'Comma-separated check IDs to skip (e.g., CRED-001,GIT-002)')
|
|
1736
1736
|
.option('--json', 'Output as JSON (deprecated: use --format json)')
|
|
1737
|
-
.option('-f, --format <format>', 'Output format: text, json, sarif, html (default: text)', 'text')
|
|
1737
|
+
.option('-f, --format <format>', 'Output format: text, json, sarif, html, asff (default: text)', 'text')
|
|
1738
|
+
.option('--aws-account-id <id>', 'AWS account ID for ASFF format')
|
|
1739
|
+
.option('--aws-region <region>', 'AWS region for ASFF format')
|
|
1738
1740
|
.option('-o, --output <file>', 'Write output to file instead of stdout')
|
|
1739
1741
|
.option('--fail-below <percent>', 'Exit 1 if compliance below threshold (0-100)')
|
|
1740
1742
|
.option('-v, --verbose', 'Show all checks including passed ones')
|
|
1741
1743
|
.option('-b, --benchmark <name>', 'Run benchmark compliance check (e.g., oasb-1)')
|
|
1742
1744
|
.option('-l, --level <level>', 'Benchmark level: L1 (Essential), L2 (Standard), L3 (Hardened)', 'L1')
|
|
1743
1745
|
.option('-c, --category <name>', 'Filter to specific benchmark category')
|
|
1744
|
-
.option('--deep', '
|
|
1745
|
-
.option('--
|
|
1746
|
+
.option('--deep', 'Maximum analysis: static + NanoMind + behavioral simulation + adaptive attacks (~30s per artifact)')
|
|
1747
|
+
.option('--static-only', 'Disable NanoMind and simulation (static checks only, fast, deterministic)')
|
|
1748
|
+
.option('--scan-depth <depth>', 'CAAT scan depth: quick (config+creds only), standard (default), deep (+ simulation)', 'standard')
|
|
1746
1749
|
.option('--ci-publish', 'Submit scan results to registry CI endpoint (requires CI_SCAN_HMAC_SECRET env)')
|
|
1747
1750
|
.option('--publish', 'Push scan results to the OpenA2A Registry')
|
|
1748
1751
|
.option('--registry-report', 'Post results to OpenA2A Registry')
|
|
@@ -1787,7 +1790,7 @@ Examples:
|
|
|
1787
1790
|
process.exit(1);
|
|
1788
1791
|
}
|
|
1789
1792
|
// Determine output format (--json is deprecated alias for --format json)
|
|
1790
|
-
const validFormats = ['text', 'json', 'sarif', 'html', 'asp'];
|
|
1793
|
+
const validFormats = ['text', 'json', 'sarif', 'html', 'asp', 'asff'];
|
|
1791
1794
|
const format = options.json ? 'json' : (options.format || 'text');
|
|
1792
1795
|
if (!validFormats.includes(format)) {
|
|
1793
1796
|
console.error(`Error: Invalid format '${format}'. Use: ${validFormats.join(', ')}`);
|
|
@@ -1815,17 +1818,41 @@ Examples:
|
|
|
1815
1818
|
console.error(`Error: Invalid scan depth '${options.scanDepth}'. Use: ${validDepths.join(', ')}`);
|
|
1816
1819
|
process.exit(1);
|
|
1817
1820
|
}
|
|
1818
|
-
//
|
|
1821
|
+
// Analysis mode: smart defaults, minimal flags
|
|
1822
|
+
// Default: static + NanoMind (if daemon available)
|
|
1823
|
+
// --deep: everything (static + NanoMind + simulation + adaptive attacks)
|
|
1824
|
+
// --static-only: just static checks (CI/deterministic)
|
|
1825
|
+
// --ci: implies --static-only
|
|
1826
|
+
const isStaticOnly = options.staticOnly ?? false;
|
|
1819
1827
|
const isDeep = options.deep ?? (scanDepth === 'deep');
|
|
1820
|
-
|
|
1828
|
+
// Auto-detect NanoMind daemon
|
|
1829
|
+
let nanomindAvailable = false;
|
|
1830
|
+
if (!isStaticOnly && !options.ci) {
|
|
1831
|
+
try {
|
|
1832
|
+
const { isDaemonAvailable } = await Promise.resolve().then(() => __importStar(require('./semantic/nanomind-analyzer.js')));
|
|
1833
|
+
nanomindAvailable = await isDaemonAvailable();
|
|
1834
|
+
}
|
|
1835
|
+
catch { /* daemon not installed */ }
|
|
1836
|
+
}
|
|
1837
|
+
const onProgress = format === 'text'
|
|
1821
1838
|
? (msg) => process.stdout.write(msg)
|
|
1822
1839
|
: undefined;
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1840
|
+
// Show analysis mode to user
|
|
1841
|
+
if (format === 'text') {
|
|
1842
|
+
if (isStaticOnly || options.ci) {
|
|
1843
|
+
// Static only -- no extra output
|
|
1844
|
+
}
|
|
1845
|
+
else if (nanomindAvailable && isDeep) {
|
|
1846
|
+
console.log(`Analysis: static + NanoMind + behavioral simulation + adaptive attacks\n`);
|
|
1847
|
+
}
|
|
1848
|
+
else if (nanomindAvailable) {
|
|
1849
|
+
console.log(`Analysis: static + NanoMind (enhanced accuracy)\n`);
|
|
1850
|
+
}
|
|
1851
|
+
else if (isDeep) {
|
|
1852
|
+
console.log(`Analysis: static + behavioral simulation\n`);
|
|
1853
|
+
console.log(` Tip: Install NanoMind for even better results: nanomind-daemon start\n`);
|
|
1828
1854
|
}
|
|
1855
|
+
// Default static-only: no message needed, it's the baseline
|
|
1829
1856
|
}
|
|
1830
1857
|
if (scanDepth === 'quick' && format === 'text') {
|
|
1831
1858
|
console.log(`Scan depth: quick (config checks + credential detection only)\n`);
|
|
@@ -1843,6 +1870,53 @@ Examples:
|
|
|
1843
1870
|
onProgress,
|
|
1844
1871
|
});
|
|
1845
1872
|
const scanDurationMs = Date.now() - scanStartMs;
|
|
1873
|
+
// Behavioral simulation: auto-runs on --deep, or when NanoMind detects ambiguity
|
|
1874
|
+
if (isDeep && format === 'text') {
|
|
1875
|
+
try {
|
|
1876
|
+
const { SimulationEngine, parseSkillProfile } = await Promise.resolve().then(() => __importStar(require('./simulation/index.js')));
|
|
1877
|
+
const { readFileSync, readdirSync, statSync } = await Promise.resolve().then(() => __importStar(require('node:fs')));
|
|
1878
|
+
const { join } = await Promise.resolve().then(() => __importStar(require('node:path')));
|
|
1879
|
+
// Find skill files in target directory
|
|
1880
|
+
const skillFiles = [];
|
|
1881
|
+
const findSkills = (dir) => {
|
|
1882
|
+
try {
|
|
1883
|
+
for (const entry of readdirSync(dir)) {
|
|
1884
|
+
const fullPath = join(dir, entry);
|
|
1885
|
+
const stat = statSync(fullPath);
|
|
1886
|
+
if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') {
|
|
1887
|
+
findSkills(fullPath);
|
|
1888
|
+
}
|
|
1889
|
+
else if (entry.endsWith('.md') || entry.endsWith('.yaml') || entry.endsWith('.yml')) {
|
|
1890
|
+
skillFiles.push(fullPath);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
catch { /* skip inaccessible dirs */ }
|
|
1895
|
+
};
|
|
1896
|
+
findSkills(targetDir);
|
|
1897
|
+
if (skillFiles.length === 0) {
|
|
1898
|
+
process.stdout.write(`\n[Simulation] No skill/SOUL/MCP artifacts found. Simulation skipped.\n\n`);
|
|
1899
|
+
}
|
|
1900
|
+
else {
|
|
1901
|
+
process.stdout.write(`\n[Simulation] Running behavioral simulation on ${skillFiles.length} artifact(s)...\n`);
|
|
1902
|
+
const sim = new SimulationEngine({ useLLM: nanomindAvailable });
|
|
1903
|
+
for (const file of skillFiles.slice(0, 10)) { // Cap at 10 files
|
|
1904
|
+
const content = readFileSync(file, 'utf-8');
|
|
1905
|
+
const profile = parseSkillProfile(content, file.split('/').pop() ?? 'unknown');
|
|
1906
|
+
const simResult = await sim.runLayer3(profile);
|
|
1907
|
+
const icon = simResult.verdict === 'CLEAN' ? 'PASS' : simResult.verdict === 'SUSPICIOUS' ? 'WARN' : 'FAIL';
|
|
1908
|
+
process.stdout.write(` [${icon}] ${file.split('/').pop()} — ${simResult.verdict} (${(simResult.confidence * 100).toFixed(0)}% confidence, ${simResult.failedProbes.length}/${simResult.probeCount} probes failed)\n`);
|
|
1909
|
+
// Auto-export training data
|
|
1910
|
+
const { exportSimulationTraining } = await Promise.resolve().then(() => __importStar(require('./attack-engine/training-pipeline.js')));
|
|
1911
|
+
exportSimulationTraining(content, simResult);
|
|
1912
|
+
}
|
|
1913
|
+
process.stdout.write(`[Simulation] Complete.\n\n`);
|
|
1914
|
+
} // end skillFiles.length > 0
|
|
1915
|
+
}
|
|
1916
|
+
catch (err) {
|
|
1917
|
+
process.stdout.write(`[Simulation] Skipped: ${err instanceof Error ? err.message : 'unknown error'}\n\n`);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1846
1920
|
// OASB-2 composite mode: infrastructure (50%) + governance (50%)
|
|
1847
1921
|
if (isOasb2) {
|
|
1848
1922
|
const infraResult = generateBenchmarkReport(result.allFindings || result.findings, level, options.category);
|
|
@@ -2013,6 +2087,26 @@ Examples:
|
|
|
2013
2087
|
process.exit(1);
|
|
2014
2088
|
return;
|
|
2015
2089
|
}
|
|
2090
|
+
if (format === 'asff') {
|
|
2091
|
+
const { toASSF } = await Promise.resolve().then(() => __importStar(require('./output/asff.js')));
|
|
2092
|
+
const output = toASSF(result.findings, {
|
|
2093
|
+
awsAccountId: options.awsAccountId,
|
|
2094
|
+
awsRegion: options.awsRegion,
|
|
2095
|
+
targetDir,
|
|
2096
|
+
});
|
|
2097
|
+
if (options.output) {
|
|
2098
|
+
require('fs').writeFileSync(options.output, output);
|
|
2099
|
+
console.error(`ASFF report written to ${options.output}`);
|
|
2100
|
+
console.error(`Import: aws securityhub batch-import-findings --findings file://${options.output}`);
|
|
2101
|
+
}
|
|
2102
|
+
else {
|
|
2103
|
+
console.log(output);
|
|
2104
|
+
}
|
|
2105
|
+
const critHigh = result.findings.filter((f) => !f.passed && !f.fixed && (f.severity === 'critical' || f.severity === 'high'));
|
|
2106
|
+
if (critHigh.length > 0)
|
|
2107
|
+
process.exit(1);
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2016
2110
|
// Filter to only show failed findings (issues)
|
|
2017
2111
|
const issues = result.findings.filter((f) => !f.passed && !f.fixed);
|
|
2018
2112
|
const fixedFindings = result.findings.filter((f) => f.fixed);
|
|
@@ -4390,7 +4484,8 @@ Examples:
|
|
|
4390
4484
|
.option('--tier <tier>', 'Override agent tier detection (BASIC, TOOL-USING, AGENTIC, MULTI-AGENT)')
|
|
4391
4485
|
.option('--profile <profile>', 'Override agent profile (conversational, code-assistant, tool-agent, autonomous, orchestrator, custom)')
|
|
4392
4486
|
.option('--fail-below <score>', 'Exit 1 if score below threshold (0-100)')
|
|
4393
|
-
.option('--deep', '
|
|
4487
|
+
.option('--deep', 'Maximum analysis: NanoMind + SOUL governance simulation (~15s)')
|
|
4488
|
+
.option('--static-only', 'Disable NanoMind (static governance checks only)')
|
|
4394
4489
|
.option('--publish', 'Push scan results to the OpenA2A Registry')
|
|
4395
4490
|
.option('--registry-url <url>', 'Registry URL (default: REGISTRY_URL env)', validateRegistryUrl(process.env.REGISTRY_URL || 'https://api.oa2a.org'))
|
|
4396
4491
|
.option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
|
|
@@ -5025,6 +5120,109 @@ program
|
|
|
5025
5120
|
writeJsonStdout({ totalChecks: Object.keys(metadata).length, checks: metadata });
|
|
5026
5121
|
});
|
|
5027
5122
|
// Show help and exit 0 when no arguments provided
|
|
5123
|
+
// explain command: NanoMind-powered finding explanation
|
|
5124
|
+
program
|
|
5125
|
+
.command('explain')
|
|
5126
|
+
.argument('<findingId>', 'Finding ID to explain (e.g., SKILL-SEMANTIC-007 or CRED-001)')
|
|
5127
|
+
.description('Explain a security finding in plain English using NanoMind')
|
|
5128
|
+
.action(async (findingId) => {
|
|
5129
|
+
console.log(`Explaining finding: ${findingId}\n`);
|
|
5130
|
+
// Try NanoMind daemon first for dynamic explanation
|
|
5131
|
+
const { isDaemonAvailable, explainFinding } = await Promise.resolve().then(() => __importStar(require('./semantic/nanomind-analyzer.js')));
|
|
5132
|
+
const available = await isDaemonAvailable();
|
|
5133
|
+
if (available) {
|
|
5134
|
+
const explanation = await explainFinding(JSON.stringify({ findingId }));
|
|
5135
|
+
if (explanation) {
|
|
5136
|
+
console.log(explanation);
|
|
5137
|
+
return;
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
5140
|
+
// Fallback: static explanation from check metadata
|
|
5141
|
+
const checkId = findingId.toUpperCase();
|
|
5142
|
+
const staticExplanations = {
|
|
5143
|
+
'CRED-001': 'Hardcoded credential detected. API keys, tokens, or passwords are embedded directly in source code. Replace with environment variable references ($VAR_NAME) and rotate the exposed credential immediately.',
|
|
5144
|
+
'CRED-002': 'OpenAI API key pattern detected (sk-...). Move to environment variable OPENAI_API_KEY.',
|
|
5145
|
+
'CRED-003': 'Anthropic API key pattern detected (sk-ant-...). Move to environment variable ANTHROPIC_API_KEY.',
|
|
5146
|
+
'CRED-004': 'AWS credential pattern detected. Use AWS SDK credential chain or environment variables.',
|
|
5147
|
+
'MCP-001': 'MCP server running without TLS. Agent-to-server communication is unencrypted.',
|
|
5148
|
+
'SKILL-005': 'External endpoint in skill capability declaration. Verify the endpoint is trusted.',
|
|
5149
|
+
};
|
|
5150
|
+
const explanation = staticExplanations[checkId];
|
|
5151
|
+
if (explanation) {
|
|
5152
|
+
console.log(`${checkId}: ${explanation}`);
|
|
5153
|
+
}
|
|
5154
|
+
else {
|
|
5155
|
+
console.log(`No explanation available for ${findingId}.`);
|
|
5156
|
+
if (!available) {
|
|
5157
|
+
console.log(`\nFor dynamic explanations, install NanoMind: npm install -g @nanomind/cli && nanomind-daemon start`);
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
});
|
|
5161
|
+
// red-team command: NanoMind-powered adaptive attack engine
|
|
5162
|
+
program
|
|
5163
|
+
.command('red-team')
|
|
5164
|
+
.argument('<target>', 'Path to artifact to red-team (skill, SOUL.md, MCP config, system prompt)')
|
|
5165
|
+
.description('Run adaptive attack session against an artifact. NanoMind generates target-specific attacks, observes responses, adapts, and maps defenses.')
|
|
5166
|
+
.option('--iterations <n>', 'Max attack iterations per category', '5')
|
|
5167
|
+
.option('--json', 'Output results as JSON')
|
|
5168
|
+
.action(async (target, options) => {
|
|
5169
|
+
const { readFileSync } = await Promise.resolve().then(() => __importStar(require('node:fs')));
|
|
5170
|
+
const { runAttackSession, exportTrainingData } = await Promise.resolve().then(() => __importStar(require('./attack-engine/feedback-loop.js')));
|
|
5171
|
+
const { exportAttackTraining } = await Promise.resolve().then(() => __importStar(require('./attack-engine/training-pipeline.js')));
|
|
5172
|
+
let content;
|
|
5173
|
+
try {
|
|
5174
|
+
content = readFileSync(target, 'utf-8');
|
|
5175
|
+
}
|
|
5176
|
+
catch {
|
|
5177
|
+
console.error(`Cannot read file: ${target}`);
|
|
5178
|
+
process.exit(1);
|
|
5179
|
+
}
|
|
5180
|
+
const artifactType = target.toLowerCase().includes('soul') ? 'soul'
|
|
5181
|
+
: target.toLowerCase().includes('mcp') ? 'mcp_tool'
|
|
5182
|
+
: 'skill';
|
|
5183
|
+
const name = target.split('/').pop() ?? 'unknown';
|
|
5184
|
+
if (!options.json) {
|
|
5185
|
+
console.log(`\nAdaptive Attack Engine`);
|
|
5186
|
+
console.log(`Target: ${name} (${artifactType})`);
|
|
5187
|
+
console.log(`Max iterations: ${options.iterations ?? 5} per category\n`);
|
|
5188
|
+
}
|
|
5189
|
+
const result = await runAttackSession(content, artifactType, name, {
|
|
5190
|
+
maxIterations: parseInt(options.iterations ?? '5', 10),
|
|
5191
|
+
});
|
|
5192
|
+
if (options.json) {
|
|
5193
|
+
console.log(JSON.stringify(result, null, 2));
|
|
5194
|
+
}
|
|
5195
|
+
else {
|
|
5196
|
+
console.log(`Results:`);
|
|
5197
|
+
console.log(` Payloads generated: ${result.totalPayloads}`);
|
|
5198
|
+
console.log(` Successful attacks: ${result.successCount}`);
|
|
5199
|
+
console.log(` Partial successes: ${result.partialCount}`);
|
|
5200
|
+
console.log(` Resilience score: ${(result.defenseMap.resilienceScore * 100).toFixed(0)}%`);
|
|
5201
|
+
console.log(` Duration: ${result.durationMs}ms\n`);
|
|
5202
|
+
if (result.vulnerabilities.length > 0) {
|
|
5203
|
+
console.log(`Vulnerabilities Found:`);
|
|
5204
|
+
for (const vuln of result.vulnerabilities) {
|
|
5205
|
+
console.log(` [${vuln.severity.toUpperCase()}] ${vuln.title}`);
|
|
5206
|
+
console.log(` ${vuln.description}`);
|
|
5207
|
+
console.log(` Fix: ${vuln.remediation}\n`);
|
|
5208
|
+
}
|
|
5209
|
+
}
|
|
5210
|
+
else {
|
|
5211
|
+
console.log(`No vulnerabilities found. All defenses held.\n`);
|
|
5212
|
+
}
|
|
5213
|
+
if (result.defenseMap.strongCategories.length > 0) {
|
|
5214
|
+
console.log(`Strong defenses: ${result.defenseMap.strongCategories.join(', ')}`);
|
|
5215
|
+
}
|
|
5216
|
+
if (result.defenseMap.weakCategories.length > 0) {
|
|
5217
|
+
console.log(`Weak defenses: ${result.defenseMap.weakCategories.join(', ')}`);
|
|
5218
|
+
}
|
|
5219
|
+
}
|
|
5220
|
+
// Auto-export training data
|
|
5221
|
+
const trainingCount = exportAttackTraining(result);
|
|
5222
|
+
if (!options.json && trainingCount > 0) {
|
|
5223
|
+
console.log(`\n${trainingCount} training samples exported to NanoMind corpus.`);
|
|
5224
|
+
}
|
|
5225
|
+
});
|
|
5028
5226
|
if (process.argv.length <= 2) {
|
|
5029
5227
|
program.outputHelp();
|
|
5030
5228
|
process.exit(0);
|