hackmyagent 0.14.1 → 0.15.0
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/arp/engine/event-engine.d.ts.map +1 -1
- package/dist/arp/engine/event-engine.js +8 -6
- package/dist/arp/engine/event-engine.js.map +1 -1
- package/dist/arp/intelligence/coordinator.d.ts.map +1 -1
- package/dist/arp/intelligence/coordinator.js +17 -12
- package/dist/arp/intelligence/coordinator.js.map +1 -1
- package/dist/arp/intelligence/nanomind-l1.js +2 -2
- package/dist/arp/intelligence/nanomind-l1.js.map +1 -1
- package/dist/arp/interceptors/process.d.ts.map +1 -1
- package/dist/arp/interceptors/process.js +40 -5
- package/dist/arp/interceptors/process.js.map +1 -1
- package/dist/arp/proxy/server.d.ts +6 -0
- package/dist/arp/proxy/server.d.ts.map +1 -1
- package/dist/arp/proxy/server.js +40 -14
- package/dist/arp/proxy/server.js.map +1 -1
- package/dist/arp/telemetry/gtin.d.ts +1 -1
- package/dist/arp/telemetry/gtin.d.ts.map +1 -1
- package/dist/arp/telemetry/gtin.js +4 -0
- package/dist/arp/telemetry/gtin.js.map +1 -1
- package/dist/attack/payloads/index.d.ts +2 -1
- package/dist/attack/payloads/index.d.ts.map +1 -1
- package/dist/attack/payloads/index.js +5 -1
- package/dist/attack/payloads/index.js.map +1 -1
- package/dist/attack/payloads/policy-enforcement-integrity.d.ts +13 -0
- package/dist/attack/payloads/policy-enforcement-integrity.d.ts.map +1 -0
- package/dist/attack/payloads/policy-enforcement-integrity.js +217 -0
- package/dist/attack/payloads/policy-enforcement-integrity.js.map +1 -0
- package/dist/attack/scanner.d.ts.map +1 -1
- package/dist/attack/scanner.js +1 -0
- package/dist/attack/scanner.js.map +1 -1
- package/dist/attack/types.d.ts +1 -1
- package/dist/attack/types.d.ts.map +1 -1
- package/dist/attack/types.js +5 -0
- package/dist/attack/types.js.map +1 -1
- package/dist/attack-engine/types.d.ts +1 -1
- package/dist/attack-engine/types.d.ts.map +1 -1
- package/dist/attack-engine/types.js.map +1 -1
- package/dist/cli.js +279 -20
- package/dist/cli.js.map +1 -1
- package/dist/hardening/scanner.d.ts +18 -4
- package/dist/hardening/scanner.d.ts.map +1 -1
- package/dist/hardening/scanner.js +76 -18
- package/dist/hardening/scanner.js.map +1 -1
- package/dist/nanomind-core/inference/tme-classifier.d.ts.map +1 -1
- package/dist/nanomind-core/inference/tme-classifier.js +0 -1
- package/dist/nanomind-core/inference/tme-classifier.js.map +1 -1
- package/dist/nanomind-core/scanner-bridge.d.ts.map +1 -1
- package/dist/nanomind-core/scanner-bridge.js +8 -0
- package/dist/nanomind-core/scanner-bridge.js.map +1 -1
- package/package.json +1 -1
- package/dist/abgr/controls.d.ts +0 -35
- package/dist/abgr/controls.d.ts.map +0 -1
- package/dist/abgr/controls.js +0 -1058
- package/dist/abgr/controls.js.map +0 -1
- package/dist/abgr/detector.d.ts +0 -45
- package/dist/abgr/detector.d.ts.map +0 -1
- package/dist/abgr/detector.js +0 -175
- package/dist/abgr/detector.js.map +0 -1
- package/dist/abgr/index.d.ts +0 -24
- package/dist/abgr/index.d.ts.map +0 -1
- package/dist/abgr/index.js +0 -50
- package/dist/abgr/index.js.map +0 -1
- package/dist/abgr/scorer.d.ts +0 -36
- package/dist/abgr/scorer.d.ts.map +0 -1
- package/dist/abgr/scorer.js +0 -205
- package/dist/abgr/scorer.js.map +0 -1
- package/dist/abgr/templates.d.ts +0 -35
- package/dist/abgr/templates.d.ts.map +0 -1
- package/dist/abgr/templates.js +0 -668
- package/dist/abgr/templates.js.map +0 -1
- package/dist/abgr/tier.d.ts +0 -27
- package/dist/abgr/tier.d.ts.map +0 -1
- package/dist/abgr/tier.js +0 -115
- package/dist/abgr/tier.js.map +0 -1
- package/dist/abgr/types.d.ts +0 -59
- package/dist/abgr/types.d.ts.map +0 -1
- package/dist/abgr/types.js +0 -10
- package/dist/abgr/types.js.map +0 -1
- package/dist/agent-scan/checks.d.ts +0 -6
- package/dist/agent-scan/checks.d.ts.map +0 -1
- package/dist/agent-scan/checks.js +0 -93
- package/dist/agent-scan/checks.js.map +0 -1
- package/dist/agent-scan/index.d.ts +0 -10
- package/dist/agent-scan/index.d.ts.map +0 -1
- package/dist/agent-scan/index.js +0 -16
- package/dist/agent-scan/index.js.map +0 -1
- package/dist/agent-scan/scanner.d.ts +0 -31
- package/dist/agent-scan/scanner.d.ts.map +0 -1
- package/dist/agent-scan/scanner.js +0 -484
- package/dist/agent-scan/scanner.js.map +0 -1
- package/dist/agent-scan/types.d.ts +0 -63
- package/dist/agent-scan/types.d.ts.map +0 -1
- package/dist/agent-scan/types.js +0 -10
- package/dist/agent-scan/types.js.map +0 -1
- package/dist/hardening/llm-checks.d.ts +0 -18
- package/dist/hardening/llm-checks.d.ts.map +0 -1
- package/dist/hardening/llm-checks.js +0 -434
- package/dist/hardening/llm-checks.js.map +0 -1
- package/dist/hardening/mcp-tool-enum.d.ts +0 -45
- package/dist/hardening/mcp-tool-enum.d.ts.map +0 -1
- package/dist/hardening/mcp-tool-enum.js +0 -315
- package/dist/hardening/mcp-tool-enum.js.map +0 -1
- package/dist/hardening/shell-checks.d.ts +0 -21
- package/dist/hardening/shell-checks.d.ts.map +0 -1
- package/dist/hardening/shell-checks.js +0 -236
- package/dist/hardening/shell-checks.js.map +0 -1
- package/dist/nanomind-core/telemetry/auto-update.d.ts +0 -27
- package/dist/nanomind-core/telemetry/auto-update.d.ts.map +0 -1
- package/dist/nanomind-core/telemetry/auto-update.js +0 -129
- package/dist/nanomind-core/telemetry/auto-update.js.map +0 -1
- package/dist/nanomind-core/telemetry/client.d.ts +0 -66
- package/dist/nanomind-core/telemetry/client.d.ts.map +0 -1
- package/dist/nanomind-core/telemetry/client.js +0 -123
- package/dist/nanomind-core/telemetry/client.js.map +0 -1
- package/dist/nanomind-core/telemetry/config.d.ts +0 -33
- package/dist/nanomind-core/telemetry/config.d.ts.map +0 -1
- package/dist/nanomind-core/telemetry/config.js +0 -119
- package/dist/nanomind-core/telemetry/config.js.map +0 -1
- package/dist/nanomind-core/telemetry/index.d.ts +0 -15
- package/dist/nanomind-core/telemetry/index.d.ts.map +0 -1
- package/dist/nanomind-core/telemetry/index.js +0 -27
- package/dist/nanomind-core/telemetry/index.js.map +0 -1
- package/dist/registry/contribution.d.ts +0 -178
- package/dist/registry/contribution.d.ts.map +0 -1
- package/dist/registry/contribution.js +0 -272
- package/dist/registry/contribution.js.map +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Hardening Scanner
|
|
3
3
|
* Scans for security issues and optionally auto-fixes them
|
|
4
4
|
*/
|
|
5
|
-
import type { ScanResult } from './security-check';
|
|
5
|
+
import type { ScanResult, SecurityFinding, ProjectType } from './security-check';
|
|
6
6
|
/** Scan depth for CAAT tiered scanning */
|
|
7
7
|
export type ScanDepth = 'quick' | 'standard' | 'deep';
|
|
8
8
|
export interface ScanOptions {
|
|
@@ -36,9 +36,20 @@ export declare class HardeningScanner {
|
|
|
36
36
|
*/
|
|
37
37
|
private isPathWithinDirectory;
|
|
38
38
|
/**
|
|
39
|
-
* Load .hmaignore file from target directory.
|
|
39
|
+
* Load .hmaignore file from target directory.
|
|
40
|
+
* Returns path patterns (plain lines) and check ID suppression patterns (lines starting with !).
|
|
40
41
|
*/
|
|
41
42
|
private loadHmaIgnore;
|
|
43
|
+
/**
|
|
44
|
+
* Check if a check ID matches any suppression pattern from .hmaignore.
|
|
45
|
+
* Supports exact match and wildcard (*) at the end (e.g. SANDBOX-* matches SANDBOX-001).
|
|
46
|
+
*/
|
|
47
|
+
private isCheckIdSuppressed;
|
|
48
|
+
/**
|
|
49
|
+
* Re-apply .hmaignore filters to a set of findings.
|
|
50
|
+
* Call this after NanoMind merge overwrites result.findings with unfiltered data.
|
|
51
|
+
*/
|
|
52
|
+
reapplyIgnoreFilters(findings: SecurityFinding[], targetDir: string, additionalIgnorePaths?: string[]): Promise<SecurityFinding[]>;
|
|
42
53
|
/**
|
|
43
54
|
* Check if a file path matches any .hmaignore pattern.
|
|
44
55
|
*/
|
|
@@ -52,7 +63,7 @@ export declare class HardeningScanner {
|
|
|
52
63
|
/**
|
|
53
64
|
* Check if a finding applies to the given project type
|
|
54
65
|
*/
|
|
55
|
-
|
|
66
|
+
findingAppliesTo(finding: SecurityFinding, projectType: ProjectType): boolean;
|
|
56
67
|
private checkCredentialExposure;
|
|
57
68
|
private checkClaudeMd;
|
|
58
69
|
private checkMcpConfig;
|
|
@@ -108,7 +119,10 @@ export declare class HardeningScanner {
|
|
|
108
119
|
* MCP tool permission boundary checks
|
|
109
120
|
*/
|
|
110
121
|
private checkToolBoundaries;
|
|
111
|
-
|
|
122
|
+
calculateScore(findings: SecurityFinding[]): {
|
|
123
|
+
score: number;
|
|
124
|
+
maxScore: number;
|
|
125
|
+
};
|
|
112
126
|
/**
|
|
113
127
|
* Create a backup of files that may be modified during auto-fix
|
|
114
128
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/hardening/scanner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../src/hardening/scanner.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAY,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA4G3F,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,oDAAoD;IACpD,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoID,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAAiB;IAEhC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CA2BlC;IAEF;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAM7B;;;OAGG;YACW,aAAa;IAwB3B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAa3B;;;OAGG;IACG,oBAAoB,CACxB,QAAQ,EAAE,eAAe,EAAE,EAC3B,SAAS,EAAE,MAAM,EACjB,qBAAqB,CAAC,EAAE,MAAM,EAAE,GAC/B,OAAO,CAAC,eAAe,EAAE,CAAC;IAgB7B;;OAEG;IACH,OAAO,CAAC,aAAa;IASf,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;YA+ZvC,cAAc;IAwE5B;;OAEG;YACW,iBAAiB;IA+F/B;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO;YAe/D,uBAAuB;YA4GvB,aAAa;YAiDb,cAAc;YAiGd,oBAAoB;YAyDpB,gBAAgB;YAgJhB,oBAAoB;YAkFpB,gBAAgB;YA8IhB,mBAAmB;YA8EnB,iBAAiB;YA0CjB,iBAAiB;YAiEjB,wBAAwB;YA6FxB,wBAAwB;YAqExB,wBAAwB;YAyHxB,oBAAoB;YAmHpB,uBAAuB;YA4IvB,iBAAiB;YAkHjB,oBAAoB;YA0HpB,mBAAmB;YAqGnB,gBAAgB;YAwIhB,oBAAoB;YAwIpB,gBAAgB;YA6HhB,qBAAqB;YAmHrB,eAAe;IAqI7B;;OAEG;YACW,mBAAmB;IAkHjC;;OAEG;YACW,oBAAoB;IAqKlC;;OAEG;YACW,iBAAiB;IAgJ/B;;OAEG;YACW,oBAAoB;IA4IlC;;OAEG;YACW,eAAe;IAyJ7B;;OAEG;YACW,eAAe;IA2I7B;;OAEG;YACW,eAAe;IA6G7B;;OAEG;YACW,mBAAmB;IAuHjC,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG;QAC3C,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB;IAmBD;;OAEG;YACW,YAAY;IAmE1B;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6DhD;;;OAGG;YACW,cAAc;IAgD5B;;OAEG;YACW,mBAAmB;IA6pBjC;;;OAGG;YACW,kBAAkB;IAgDhC;;OAEG;YACW,sBAAsB;IAkMpC;;OAEG;YACW,sBAAsB;IA+BpC;;OAEG;YACW,oBAAoB;IAgWlC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;OAEG;YACW,iBAAiB;IA8D/B;;OAEG;YACW,mBAAmB;IAsXjC;;OAEG;YACW,wBAAwB;IAqPtC;;OAEG;YACW,gBAAgB;IAoK9B;;;OAGG;YACW,eAAe;IAoD7B;;;OAGG;YACW,aAAa;IAwC3B;;;OAGG;YACW,oBAAoB;IAoKlC;;;OAGG;YACW,iBAAiB;IAiI/B;;;OAGG;YACW,kBAAkB;IAkFhC;;;OAGG;YACW,aAAa;IA0F3B;;OAEG;YACW,gBAAgB;IAiE9B;;;;OAIG;YACW,yBAAyB;IA0WvC;;;;;OAKG;YACW,qBAAqB;IAqnBnC;;;;OAIG;YACW,gBAAgB;IA2G9B;;;;OAIG;YACW,mBAAmB;IAmKjC;;;;OAIG;YACW,gBAAgB;IAkF9B;;;OAGG;YACW,iBAAiB;IA+C/B;;;;OAIG;YACW,yBAAyB;IA6FvC;;;OAGG;YACW,kBAAkB;IA8ChC;;;OAGG;YACW,mBAAmB;IA4CjC;;;OAGG;YACW,6BAA6B;IAiD3C;;;OAGG;YACW,oBAAoB;IA4ClC;;;OAGG;YACW,WAAW;IA4DzB;;;OAGG;YACW,aAAa;IAgD3B;;;OAGG;YACW,oBAAoB;IA6ClC;;;OAGG;YACW,YAAY;IAmD1B;;;OAGG;YACW,qBAAqB;IA+DnC;;;;OAIG;YACW,oBAAoB;IAyHlC;;;OAGG;YACW,iBAAiB;IA+F/B;;;OAGG;YACW,4BAA4B;IAqD1C;;;OAGG;YACW,8BAA8B;IAgE5C;;;;OAIG;YACW,qBAAqB;IAgBnC,+DAA+D;YACjD,YAAY;CA+B3B"}
|
|
@@ -71,12 +71,12 @@ const CHECK_PROJECT_TYPES = {
|
|
|
71
71
|
'SESSION-': ['webapp', 'api'], // Session management
|
|
72
72
|
'NET-': ['webapp', 'api'], // Network security (HTTPS, etc.)
|
|
73
73
|
'IO-': ['webapp', 'api'], // Input/output (XSS, etc.)
|
|
74
|
-
//
|
|
75
|
-
'SKILL-': ['
|
|
76
|
-
'HEARTBEAT-': ['
|
|
74
|
+
// Skill/config checks - apply to all because if these files exist, they matter
|
|
75
|
+
'SKILL-': ['all'], // Skill file security (fires only when skill files exist)
|
|
76
|
+
'HEARTBEAT-': ['all'], // Heartbeat/periodic task security (fires only when HEARTBEAT.md exists)
|
|
77
77
|
'GATEWAY-': ['openclaw'], // Gateway configuration security
|
|
78
|
-
'CONFIG-': ['
|
|
79
|
-
'SUPPLY-': ['
|
|
78
|
+
'CONFIG-': ['all'], // Configuration file security (fires only when config files exist)
|
|
79
|
+
'SUPPLY-': ['all'], // Supply chain security (fires only when skill files exist)
|
|
80
80
|
'CVE-': ['openclaw'], // CVE-specific detection
|
|
81
81
|
'API-': ['api'], // API security headers
|
|
82
82
|
'RATE-': ['webapp', 'api'], // Rate limiting
|
|
@@ -259,21 +259,70 @@ class HardeningScanner {
|
|
|
259
259
|
return normalizedFile.startsWith(normalizedDir + path.sep) || normalizedFile === normalizedDir;
|
|
260
260
|
}
|
|
261
261
|
/**
|
|
262
|
-
* Load .hmaignore file from target directory.
|
|
262
|
+
* Load .hmaignore file from target directory.
|
|
263
|
+
* Returns path patterns (plain lines) and check ID suppression patterns (lines starting with !).
|
|
263
264
|
*/
|
|
264
265
|
async loadHmaIgnore(targetDir) {
|
|
265
266
|
const ignorePath = path.join(targetDir, '.hmaignore');
|
|
266
267
|
try {
|
|
267
268
|
const content = await fs.readFile(ignorePath, 'utf-8');
|
|
268
|
-
|
|
269
|
+
const lines = content
|
|
269
270
|
.split('\n')
|
|
270
271
|
.map(line => line.trim())
|
|
271
272
|
.filter(line => line && !line.startsWith('#'));
|
|
273
|
+
const paths = [];
|
|
274
|
+
const checkIds = [];
|
|
275
|
+
for (const line of lines) {
|
|
276
|
+
if (line.startsWith('!')) {
|
|
277
|
+
// Check ID suppression pattern: strip the ! prefix, store uppercase
|
|
278
|
+
checkIds.push(line.slice(1).toUpperCase());
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
paths.push(line);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return { paths, checkIds };
|
|
272
285
|
}
|
|
273
286
|
catch {
|
|
274
|
-
return [];
|
|
287
|
+
return { paths: [], checkIds: [] };
|
|
275
288
|
}
|
|
276
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Check if a check ID matches any suppression pattern from .hmaignore.
|
|
292
|
+
* Supports exact match and wildcard (*) at the end (e.g. SANDBOX-* matches SANDBOX-001).
|
|
293
|
+
*/
|
|
294
|
+
isCheckIdSuppressed(checkId, patterns) {
|
|
295
|
+
if (patterns.length === 0)
|
|
296
|
+
return false;
|
|
297
|
+
const upper = checkId.toUpperCase();
|
|
298
|
+
return patterns.some(pattern => {
|
|
299
|
+
if (pattern.includes('*')) {
|
|
300
|
+
// Convert glob pattern to regex: escape special chars, replace * with .*
|
|
301
|
+
const regexStr = '^' + pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*') + '$';
|
|
302
|
+
return new RegExp(regexStr).test(upper);
|
|
303
|
+
}
|
|
304
|
+
return upper === pattern;
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Re-apply .hmaignore filters to a set of findings.
|
|
309
|
+
* Call this after NanoMind merge overwrites result.findings with unfiltered data.
|
|
310
|
+
*/
|
|
311
|
+
async reapplyIgnoreFilters(findings, targetDir, additionalIgnorePaths) {
|
|
312
|
+
const hmaIgnore = await this.loadHmaIgnore(targetDir);
|
|
313
|
+
const allIgnoredPaths = [...hmaIgnore.paths, ...(additionalIgnorePaths || [])];
|
|
314
|
+
const suppressedCheckPatterns = hmaIgnore.checkIds;
|
|
315
|
+
if (allIgnoredPaths.length === 0 && suppressedCheckPatterns.length === 0) {
|
|
316
|
+
return findings;
|
|
317
|
+
}
|
|
318
|
+
return findings.filter(f => {
|
|
319
|
+
if (this.isCheckIdSuppressed(f.checkId, suppressedCheckPatterns))
|
|
320
|
+
return false;
|
|
321
|
+
if (f.file && this.isPathIgnored(f.file, allIgnoredPaths))
|
|
322
|
+
return false;
|
|
323
|
+
return true;
|
|
324
|
+
});
|
|
325
|
+
}
|
|
277
326
|
/**
|
|
278
327
|
* Check if a file path matches any .hmaignore pattern.
|
|
279
328
|
*/
|
|
@@ -293,10 +342,12 @@ class HardeningScanner {
|
|
|
293
342
|
const scanDepth = options.scanDepth || (options.deep ? 'deep' : 'standard');
|
|
294
343
|
const isQuick = scanDepth === 'quick';
|
|
295
344
|
const isDeepScan = scanDepth === 'deep';
|
|
296
|
-
// Load .hmaignore for path-based exclusions
|
|
297
|
-
const
|
|
345
|
+
// Load .hmaignore for path-based exclusions and check ID suppressions
|
|
346
|
+
const hmaIgnore = await this.loadHmaIgnore(targetDir);
|
|
298
347
|
// Merge with any programmatic ignorePaths
|
|
299
|
-
const allIgnoredPaths = [...
|
|
348
|
+
const allIgnoredPaths = [...hmaIgnore.paths, ...(options.ignorePaths || [])];
|
|
349
|
+
// Check ID suppression patterns from .hmaignore (supports wildcards)
|
|
350
|
+
const suppressedCheckPatterns = hmaIgnore.checkIds;
|
|
300
351
|
// Normalize ignore list to uppercase for case-insensitive matching
|
|
301
352
|
const ignoredChecks = new Set(ignore.map((id) => id.toUpperCase()));
|
|
302
353
|
// In dry-run mode, we detect what would be fixed but don't modify anything
|
|
@@ -558,7 +609,8 @@ class HardeningScanner {
|
|
|
558
609
|
// Filter findings to only show real, actionable issues:
|
|
559
610
|
// 1. Only failed checks (passed: false)
|
|
560
611
|
// 2. Only checks with a file path (concrete findings, not generic advice)
|
|
561
|
-
// 3.
|
|
612
|
+
// 3. Only checks that apply to this project type (e.g., no SQL checks on MCP servers)
|
|
613
|
+
// 4. Filter out ignored checks
|
|
562
614
|
let filteredFindings = findings.filter((f) => {
|
|
563
615
|
// Keep fixed findings (so users can see what was fixed)
|
|
564
616
|
// Otherwise, only show failed checks
|
|
@@ -567,9 +619,15 @@ class HardeningScanner {
|
|
|
567
619
|
// Only show concrete findings (has a file path)
|
|
568
620
|
if (!f.file)
|
|
569
621
|
return false;
|
|
570
|
-
//
|
|
622
|
+
// Only show checks relevant to this project type
|
|
623
|
+
if (!this.findingAppliesTo(f, projectType))
|
|
624
|
+
return false;
|
|
625
|
+
// Filter out ignored checks (from --ignore flag)
|
|
571
626
|
if (ignoredChecks.has(f.checkId.toUpperCase()))
|
|
572
627
|
return false;
|
|
628
|
+
// Filter out check IDs suppressed via .hmaignore (supports wildcards)
|
|
629
|
+
if (this.isCheckIdSuppressed(f.checkId, suppressedCheckPatterns))
|
|
630
|
+
return false;
|
|
573
631
|
// Filter out paths matching .hmaignore
|
|
574
632
|
if (f.file && this.isPathIgnored(f.file, allIgnoredPaths))
|
|
575
633
|
return false;
|
|
@@ -702,21 +760,21 @@ class HardeningScanner {
|
|
|
702
760
|
const pkgPath = path.join(targetDir, 'package.json');
|
|
703
761
|
const content = await fs.readFile(pkgPath, 'utf-8');
|
|
704
762
|
const pkg = JSON.parse(content);
|
|
705
|
-
// Check if it's a CLI tool (has bin field)
|
|
706
|
-
if (pkg.bin) {
|
|
707
|
-
return 'cli';
|
|
708
|
-
}
|
|
709
763
|
// Check dependencies for framework detection
|
|
710
764
|
const allDeps = {
|
|
711
765
|
...pkg.dependencies,
|
|
712
766
|
...pkg.devDependencies,
|
|
713
767
|
};
|
|
714
|
-
// Check for MCP server
|
|
768
|
+
// Check for MCP server BEFORE cli -- MCP servers often have bin fields
|
|
715
769
|
if (allDeps['@modelcontextprotocol/sdk'] ||
|
|
716
770
|
allDeps['mcp'] ||
|
|
717
771
|
pkg.name?.includes('mcp')) {
|
|
718
772
|
return 'mcp';
|
|
719
773
|
}
|
|
774
|
+
// Check if it's a CLI tool (has bin field)
|
|
775
|
+
if (pkg.bin) {
|
|
776
|
+
return 'cli';
|
|
777
|
+
}
|
|
720
778
|
// Check for web frameworks
|
|
721
779
|
if (allDeps['react'] ||
|
|
722
780
|
allDeps['vue'] ||
|