hackmyagent 0.11.13 → 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/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 +186 -10
- 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.map +1 -1
- package/dist/output/asff.js +2 -1
- package/dist/output/asff.js.map +1 -1
- 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
|
@@ -1743,8 +1743,9 @@ Examples:
|
|
|
1743
1743
|
.option('-b, --benchmark <name>', 'Run benchmark compliance check (e.g., oasb-1)')
|
|
1744
1744
|
.option('-l, --level <level>', 'Benchmark level: L1 (Essential), L2 (Standard), L3 (Hardened)', 'L1')
|
|
1745
1745
|
.option('-c, --category <name>', 'Filter to specific benchmark category')
|
|
1746
|
-
.option('--deep', '
|
|
1747
|
-
.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')
|
|
1748
1749
|
.option('--ci-publish', 'Submit scan results to registry CI endpoint (requires CI_SCAN_HMAC_SECRET env)')
|
|
1749
1750
|
.option('--publish', 'Push scan results to the OpenA2A Registry')
|
|
1750
1751
|
.option('--registry-report', 'Post results to OpenA2A Registry')
|
|
@@ -1817,17 +1818,41 @@ Examples:
|
|
|
1817
1818
|
console.error(`Error: Invalid scan depth '${options.scanDepth}'. Use: ${validDepths.join(', ')}`);
|
|
1818
1819
|
process.exit(1);
|
|
1819
1820
|
}
|
|
1820
|
-
//
|
|
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;
|
|
1821
1827
|
const isDeep = options.deep ?? (scanDepth === 'deep');
|
|
1822
|
-
|
|
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'
|
|
1823
1838
|
? (msg) => process.stdout.write(msg)
|
|
1824
1839
|
: undefined;
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
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`);
|
|
1830
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`);
|
|
1854
|
+
}
|
|
1855
|
+
// Default static-only: no message needed, it's the baseline
|
|
1831
1856
|
}
|
|
1832
1857
|
if (scanDepth === 'quick' && format === 'text') {
|
|
1833
1858
|
console.log(`Scan depth: quick (config checks + credential detection only)\n`);
|
|
@@ -1845,6 +1870,53 @@ Examples:
|
|
|
1845
1870
|
onProgress,
|
|
1846
1871
|
});
|
|
1847
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
|
+
}
|
|
1848
1920
|
// OASB-2 composite mode: infrastructure (50%) + governance (50%)
|
|
1849
1921
|
if (isOasb2) {
|
|
1850
1922
|
const infraResult = generateBenchmarkReport(result.allFindings || result.findings, level, options.category);
|
|
@@ -4412,7 +4484,8 @@ Examples:
|
|
|
4412
4484
|
.option('--tier <tier>', 'Override agent tier detection (BASIC, TOOL-USING, AGENTIC, MULTI-AGENT)')
|
|
4413
4485
|
.option('--profile <profile>', 'Override agent profile (conversational, code-assistant, tool-agent, autonomous, orchestrator, custom)')
|
|
4414
4486
|
.option('--fail-below <score>', 'Exit 1 if score below threshold (0-100)')
|
|
4415
|
-
.option('--deep', '
|
|
4487
|
+
.option('--deep', 'Maximum analysis: NanoMind + SOUL governance simulation (~15s)')
|
|
4488
|
+
.option('--static-only', 'Disable NanoMind (static governance checks only)')
|
|
4416
4489
|
.option('--publish', 'Push scan results to the OpenA2A Registry')
|
|
4417
4490
|
.option('--registry-url <url>', 'Registry URL (default: REGISTRY_URL env)', validateRegistryUrl(process.env.REGISTRY_URL || 'https://api.oa2a.org'))
|
|
4418
4491
|
.option('--contribute', 'Share anonymized scan findings with OpenA2A Registry (overrides config)')
|
|
@@ -5047,6 +5120,109 @@ program
|
|
|
5047
5120
|
writeJsonStdout({ totalChecks: Object.keys(metadata).length, checks: metadata });
|
|
5048
5121
|
});
|
|
5049
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
|
+
});
|
|
5050
5226
|
if (process.argv.length <= 2) {
|
|
5051
5227
|
program.outputHelp();
|
|
5052
5228
|
process.exit(0);
|