hackmyagent 0.17.1 → 0.17.2
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/.integrity-manifest.json +1 -1
- package/dist/checker/skill-identifier.d.ts.map +1 -1
- package/dist/checker/skill-identifier.js +4 -3
- package/dist/checker/skill-identifier.js.map +1 -1
- package/dist/cli.js +112 -12
- package/dist/cli.js.map +1 -1
- package/dist/nanomind-core/index.d.ts +2 -0
- package/dist/nanomind-core/index.d.ts.map +1 -1
- package/dist/nanomind-core/index.js +12 -2
- package/dist/nanomind-core/index.js.map +1 -1
- package/dist/nanomind-core/inference/analm-infer.py +104 -0
- package/dist/nanomind-core/inference/security-analyst.d.ts +95 -0
- package/dist/nanomind-core/inference/security-analyst.d.ts.map +1 -0
- package/dist/nanomind-core/inference/security-analyst.js +372 -0
- package/dist/nanomind-core/inference/security-analyst.js.map +1 -0
- package/dist/nanomind-core/orchestrate.d.ts +7 -0
- package/dist/nanomind-core/orchestrate.d.ts.map +1 -1
- package/dist/nanomind-core/orchestrate.js +68 -2
- package/dist/nanomind-core/orchestrate.js.map +1 -1
- package/dist/registry/client.d.ts +5 -0
- package/dist/registry/client.d.ts.map +1 -1
- package/dist/registry/client.js +10 -1
- package/dist/registry/client.js.map +1 -1
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -2268,6 +2268,7 @@ Examples:
|
|
|
2268
2268
|
.option('-l, --level <level>', 'Benchmark level: L1 (Essential), L2 (Standard), L3 (Hardened)', 'L1')
|
|
2269
2269
|
.option('-c, --category <name>', 'Filter to specific benchmark category')
|
|
2270
2270
|
.option('--deep', 'Maximum analysis: static + semantic + behavioral simulation + adaptive attacks (~30s per file)')
|
|
2271
|
+
.option('--analm', 'AI-powered threat analysis using AnaLM (requires analm setup)')
|
|
2271
2272
|
.option('--static-only', 'Disable semantic analysis and simulation (static checks only, fast, deterministic)')
|
|
2272
2273
|
.option('--scan-depth <depth>', 'CAAT scan depth: quick (config+creds only), standard (default), deep (+ simulation)', 'standard')
|
|
2273
2274
|
.option('--ci-publish', 'Submit scan results to registry CI endpoint (requires CI_SCAN_HMAC_SECRET env)')
|
|
@@ -2360,7 +2361,7 @@ Examples:
|
|
|
2360
2361
|
catch { /* daemon not installed */ }
|
|
2361
2362
|
}
|
|
2362
2363
|
const onProgress = format === 'text'
|
|
2363
|
-
? (msg) => process.stdout.write(msg)
|
|
2364
|
+
? (msg) => process.stdout.write(msg.endsWith('\n') ? msg : msg + '\n')
|
|
2364
2365
|
: undefined;
|
|
2365
2366
|
// Show analysis mode to user
|
|
2366
2367
|
if (format === 'text') {
|
|
@@ -2396,15 +2397,16 @@ Examples:
|
|
|
2396
2397
|
const scanDurationMs = Date.now() - scanStartMs;
|
|
2397
2398
|
// NanoMind Semantic Compiler: AST-based analysis runs alongside static checks
|
|
2398
2399
|
// Defense-in-depth: static findings can NEVER be suppressed, only upgraded
|
|
2400
|
+
const { orchestrateNanoMind } = await Promise.resolve().then(() => __importStar(require('./nanomind-core/orchestrate.js')));
|
|
2401
|
+
const existingFindings = result.allFindings || result.findings || [];
|
|
2402
|
+
const nmResult = await orchestrateNanoMind(targetDir, existingFindings, {
|
|
2403
|
+
staticOnly: isStaticOnly,
|
|
2404
|
+
ci: options.ci,
|
|
2405
|
+
deep: isDeep,
|
|
2406
|
+
analm: options.analm,
|
|
2407
|
+
silent: format !== 'text',
|
|
2408
|
+
});
|
|
2399
2409
|
{
|
|
2400
|
-
const { orchestrateNanoMind } = await Promise.resolve().then(() => __importStar(require('./nanomind-core/orchestrate.js')));
|
|
2401
|
-
const existingFindings = result.allFindings || result.findings || [];
|
|
2402
|
-
const nmResult = await orchestrateNanoMind(targetDir, existingFindings, {
|
|
2403
|
-
staticOnly: isStaticOnly,
|
|
2404
|
-
ci: options.ci,
|
|
2405
|
-
deep: isDeep,
|
|
2406
|
-
silent: format !== 'text',
|
|
2407
|
-
});
|
|
2408
2410
|
// Re-apply all filters after NanoMind merge (merge uses allFindings which is unfiltered)
|
|
2409
2411
|
const refiltered = await scanner.reapplyIgnoreFilters(nmResult.mergedFindings, targetDir);
|
|
2410
2412
|
if (result.allFindings) {
|
|
@@ -2593,7 +2595,10 @@ Examples:
|
|
|
2593
2595
|
publishStatus = { success: false, error: msg };
|
|
2594
2596
|
}
|
|
2595
2597
|
}
|
|
2596
|
-
const
|
|
2598
|
+
const jsonBase = nmResult.analystFindings?.length
|
|
2599
|
+
? { ...result, analystFindings: nmResult.analystFindings }
|
|
2600
|
+
: result;
|
|
2601
|
+
const jsonOutput = publishStatus ? { ...jsonBase, publish: publishStatus } : jsonBase;
|
|
2597
2602
|
if (options.output) {
|
|
2598
2603
|
require('fs').writeFileSync(options.output, JSON.stringify(jsonOutput, null, 2) + '\n');
|
|
2599
2604
|
console.error(`Report written to ${options.output}`);
|
|
@@ -2748,6 +2753,42 @@ Examples:
|
|
|
2748
2753
|
if (summaryParts.length > 0) {
|
|
2749
2754
|
console.log(`${summaryParts.join(' | ')}\n`);
|
|
2750
2755
|
}
|
|
2756
|
+
// Analyst findings (--analyze)
|
|
2757
|
+
if (nmResult.analystFindings && nmResult.analystFindings.length > 0) {
|
|
2758
|
+
console.log(`${colors.cyan}--- AnaLM Analysis ---${RESET()}\n`);
|
|
2759
|
+
for (const af of nmResult.analystFindings) {
|
|
2760
|
+
const r = af.result;
|
|
2761
|
+
if (af.taskType === 'threatAnalysis') {
|
|
2762
|
+
const level = String(r.threatLevel ?? 'unknown').toUpperCase();
|
|
2763
|
+
const levelColor = level === 'CRITICAL' || level === 'HIGH' ? colors.red : level === 'MEDIUM' ? colors.yellow : colors.dim;
|
|
2764
|
+
console.log(` ${levelColor}${level}${RESET()} ${r.attackVector ?? ''}`);
|
|
2765
|
+
if (r.description)
|
|
2766
|
+
console.log(` ${r.description}`);
|
|
2767
|
+
if (Array.isArray(r.mitigations) && r.mitigations.length > 0) {
|
|
2768
|
+
for (const m of r.mitigations) {
|
|
2769
|
+
console.log(` ${colors.cyan}Fix:${RESET()} ${m}`);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
else if (af.taskType === 'credentialContextClassification') {
|
|
2774
|
+
const cls = String(r.classification ?? 'unknown');
|
|
2775
|
+
const clsColor = cls === 'real' ? colors.red : cls === 'test' || cls === 'example' ? colors.green : colors.yellow;
|
|
2776
|
+
console.log(` Credential: ${clsColor}${cls}${RESET()}`);
|
|
2777
|
+
if (r.reasoning)
|
|
2778
|
+
console.log(` ${r.reasoning}`);
|
|
2779
|
+
}
|
|
2780
|
+
else {
|
|
2781
|
+
// Generic display for other task types
|
|
2782
|
+
console.log(` ${af.taskType}: ${JSON.stringify(r)}`);
|
|
2783
|
+
}
|
|
2784
|
+
console.log(` ${colors.dim}Confidence: ${Math.round(af.confidence * 100)}% | ${af.modelVersion} (${af.durationMs}ms)${RESET()}`);
|
|
2785
|
+
console.log();
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
// Analyst hint (shown when model is available but --analyze not used)
|
|
2789
|
+
if (nmResult.analystHint && issues.length > 0) {
|
|
2790
|
+
console.log(`${colors.dim}Tip: ${nmResult.analystHint}${RESET()}\n`);
|
|
2791
|
+
}
|
|
2751
2792
|
// Dry-run summary
|
|
2752
2793
|
if (result.dryRun) {
|
|
2753
2794
|
const wouldFixCount = issues.filter((f) => f.wouldFix).length;
|
|
@@ -2798,7 +2839,8 @@ Examples:
|
|
|
2798
2839
|
console.error('Error: --registry-key or REGISTRY_API_KEY env is required when using --version-id');
|
|
2799
2840
|
process.exit(1);
|
|
2800
2841
|
}
|
|
2801
|
-
const
|
|
2842
|
+
const atcToken = process.env.ATC_TOKEN;
|
|
2843
|
+
const client = new core.RegistryClient({ registryUrl, apiKey: registryKey, atcToken });
|
|
2802
2844
|
const payload = core.buildScanReport(options.versionId, result.findings);
|
|
2803
2845
|
await client.reportScanResult(payload);
|
|
2804
2846
|
console.log(`Registry: scan results reported for version ${options.versionId}`);
|
|
@@ -3568,7 +3610,8 @@ Examples:
|
|
|
3568
3610
|
console.error('Error: --registry-key or REGISTRY_API_KEY env is required when using --version-id');
|
|
3569
3611
|
process.exit(1);
|
|
3570
3612
|
}
|
|
3571
|
-
const
|
|
3613
|
+
const atcToken = process.env.ATC_TOKEN;
|
|
3614
|
+
const client = new core.RegistryClient({ registryUrl, apiKey: registryKey, atcToken });
|
|
3572
3615
|
const payload = core.buildAttackReport(options.versionId, report);
|
|
3573
3616
|
await client.reportScanResult(payload);
|
|
3574
3617
|
console.log(`Registry: attack results reported for version ${options.versionId}`);
|
|
@@ -6118,6 +6161,63 @@ program
|
|
|
6118
6161
|
}
|
|
6119
6162
|
console.log(`\nYour skill is ready. Verify security with: hackmyagent secure ${outputDir}/`);
|
|
6120
6163
|
});
|
|
6164
|
+
// analm: manage the AnaLM generative model
|
|
6165
|
+
const analmCmd = program
|
|
6166
|
+
.command('analm')
|
|
6167
|
+
.description('Manage the AnaLM model for AI-powered security analysis');
|
|
6168
|
+
analmCmd
|
|
6169
|
+
.command('setup')
|
|
6170
|
+
.description('Download the AnaLM model')
|
|
6171
|
+
.action(async () => {
|
|
6172
|
+
const { getAnalystStatus, setupAnalystModel } = await Promise.resolve().then(() => __importStar(require('./nanomind-core/inference/security-analyst.js')));
|
|
6173
|
+
const status = await getAnalystStatus();
|
|
6174
|
+
console.log('AnaLM (NanoMind Security Analyst)');
|
|
6175
|
+
console.log(` Platform: ${status.platform}`);
|
|
6176
|
+
console.log(` Backend: ${status.backend === 'none' ? 'not available' : status.backend}`);
|
|
6177
|
+
console.log(` Model: ${status.modelCached ? 'cached' : 'not downloaded'}`);
|
|
6178
|
+
console.log('');
|
|
6179
|
+
if (status.backend === 'none') {
|
|
6180
|
+
console.log('No supported inference backend found.');
|
|
6181
|
+
if (process.platform !== 'darwin') {
|
|
6182
|
+
console.log('Currently requires Apple Silicon Mac with MLX.');
|
|
6183
|
+
console.log('Cross-platform support (llama.cpp/GGUF) coming soon.');
|
|
6184
|
+
}
|
|
6185
|
+
else {
|
|
6186
|
+
console.log('Install uv: curl -LsSf https://astral.sh/uv/install.sh | sh');
|
|
6187
|
+
}
|
|
6188
|
+
process.exit(1);
|
|
6189
|
+
}
|
|
6190
|
+
if (status.modelCached) {
|
|
6191
|
+
console.log('Model already downloaded. Use --analm with any scan command.');
|
|
6192
|
+
return;
|
|
6193
|
+
}
|
|
6194
|
+
const ok = await setupAnalystModel(false);
|
|
6195
|
+
if (!ok)
|
|
6196
|
+
process.exit(1);
|
|
6197
|
+
});
|
|
6198
|
+
analmCmd
|
|
6199
|
+
.command('status')
|
|
6200
|
+
.description('Check the status of AnaLM model and runtime')
|
|
6201
|
+
.action(async () => {
|
|
6202
|
+
const { getAnalystStatus } = await Promise.resolve().then(() => __importStar(require('./nanomind-core/inference/security-analyst.js')));
|
|
6203
|
+
const status = await getAnalystStatus();
|
|
6204
|
+
console.log('AnaLM (NanoMind Security Analyst)');
|
|
6205
|
+
console.log(` Platform: ${status.platform}`);
|
|
6206
|
+
console.log(` Backend: ${status.backend === 'none' ? `${colors.red}not available${RESET()}` : `${colors.green}${status.backend}${RESET()}`}`);
|
|
6207
|
+
console.log(` Model: ${status.modelCached ? `${colors.green}cached${RESET()}` : `${colors.yellow}not downloaded${RESET()}`}`);
|
|
6208
|
+
console.log(` Ready: ${status.available ? `${colors.green}yes${RESET()}` : `${colors.yellow}no${RESET()}`}`);
|
|
6209
|
+
console.log('');
|
|
6210
|
+
if (status.available) {
|
|
6211
|
+
console.log('Use --analm with any scan command for AI-powered analysis.');
|
|
6212
|
+
console.log(` Example: hackmyagent secure ./my-agent --analm`);
|
|
6213
|
+
}
|
|
6214
|
+
else if (status.backend !== 'none') {
|
|
6215
|
+
console.log(`Run: hackmyagent analm setup`);
|
|
6216
|
+
}
|
|
6217
|
+
else if (process.platform !== 'darwin') {
|
|
6218
|
+
console.log('Cross-platform support (llama.cpp/GGUF) coming soon.');
|
|
6219
|
+
}
|
|
6220
|
+
});
|
|
6121
6221
|
// ============================================================================
|
|
6122
6222
|
// npm package scanning helpers (used by `check <package>`)
|
|
6123
6223
|
// ============================================================================
|