hackmyagent 0.11.5 → 0.11.7

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 CHANGED
@@ -1,12 +1,11 @@
1
- > **[OpenA2A](https://github.com/opena2a-org/opena2a)**: [CLI](https://github.com/opena2a-org/opena2a) · [HackMyAgent](https://github.com/opena2a-org/hackmyagent) · [Secretless](https://github.com/opena2a-org/secretless-ai) · [AIM](https://github.com/opena2a-org/agent-identity-management) · [Browser Guard](https://github.com/opena2a-org/AI-BrowserGuard) · [DVAA](https://github.com/opena2a-org/damn-vulnerable-ai-agent) · Registry (April 2026)
2
-
1
+ > **[OpenA2A](https://github.com/opena2a-org/opena2a)**: [CLI](https://github.com/opena2a-org/opena2a) · [HackMyAgent](https://github.com/opena2a-org/hackmyagent) · [Secretless](https://github.com/opena2a-org/secretless-ai) · [AIM](https://github.com/opena2a-org/agent-identity-management) · [Browser Guard](https://github.com/opena2a-org/AI-BrowserGuard) · [DVAA](https://github.com/opena2a-org/damn-vulnerable-ai-agent)
3
2
  # HackMyAgent
4
3
 
5
4
  [![npm version](https://img.shields.io/npm/v/hackmyagent.svg)](https://www.npmjs.com/package/hackmyagent)
6
5
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
- [![Tests](https://img.shields.io/badge/tests-1050%20passing-brightgreen)](https://github.com/opena2a-org/hackmyagent)
6
+ [![Tests](https://img.shields.io/badge/tests-1051%20passing-brightgreen)](https://github.com/opena2a-org/hackmyagent)
8
7
 
9
- **173 security checks for AI agents. Find what can go wrong before an attacker does.**
8
+ **187 security checks for AI agents. Find what can go wrong before an attacker does.**
10
9
 
11
10
  Security scanner and red-team toolkit for Claude Code, Cursor, VS Code, and any MCP server setup.
12
11
 
@@ -30,7 +29,13 @@ npx opena2a-cli review
30
29
 
31
30
  ## What It Finds
32
31
 
33
- **Attack testing (115 payloads across 11 categories):**
32
+ **Attack testing** -- 115 adversarial payloads across 11 categories (prompt injection, data exfiltration, jailbreak, MCP exploitation, supply chain, memory weaponization, A2A protocol attacks, context window attacks).
33
+
34
+ **Static analysis** -- 187 security checks across 39 categories covering credentials, MCP configs, OpenClaw/NemoClaw, Unicode steganography, CVE detection, governance, supply chain, memory poisoning, agent identity, and sandbox escape patterns.
35
+
36
+ <details>
37
+ <summary>Attack testing details (115 payloads)</summary>
38
+
34
39
  - **Prompt injection** -- tests whether agents follow injected instructions from untrusted input
35
40
  - **Data exfiltration** -- checks if agents can be tricked into leaking sensitive data to external endpoints
36
41
  - **Jailbreak and context manipulation** -- probes agent guardrails with adversarial prompts
@@ -41,19 +46,26 @@ npx opena2a-cli review
41
46
  - **A2A protocol attacks** -- identity spoofing, capability escalation in multi-agent communication
42
47
  - **Context window attacks** -- token flooding, attention manipulation, context poisoning
43
48
 
44
- **Static analysis (173 checks across 34 categories):**
45
- - **Unicode steganography** -- invisible codepoints (variation selectors, tag characters), zero-width characters (U+200B-200D), mid-file BOM injection, bidi override attacks (U+202A-202E), homoglyph confusables (Cyrillic/Greek/Fullwidth lookalikes), GlassWorm decoder patterns, and eval-on-invisible-payload detection. Scans JS, TS, Python, Markdown, YAML, JSON, and TOML files. ([real-world: os-info-checker-es6 npm attack, May 2025](https://thehackernews.com/2025/05/malicious-npm-package-leverages-unicode.html))
49
+ </details>
50
+
51
+ <details>
52
+ <summary>Static analysis details (187 checks)</summary>
53
+
54
+ - **Unicode steganography** -- invisible codepoints, zero-width chars, bidi attacks, homoglyph confusables, GlassWorm decoders ([real-world: os-info-checker-es6 npm attack, May 2025](https://thehackernews.com/2025/05/malicious-npm-package-leverages-unicode.html))
46
55
  - **Hardcoded credentials** -- API keys, tokens, and passwords in source or config files
47
56
  - **MCP server misconfigurations** -- open ports, root filesystem access, missing auth
48
- - **AI agent CVE detection** -- scans for CVE-2026-25253 (OpenClaw WebSocket RCE), CVE-2026-25157, CVE-2026-24763, and ClawHavoc IOCs
49
- - **OpenClaw security** -- 34 checks for OpenClaw configurations, skills, gateway, and credential redaction ([6 PRs merged upstream](https://opena2a.org/blogs/securing-openclaw-6-prs-merged))
57
+ - **AI agent CVE detection** -- CVE-2026-25253 (OpenClaw RCE), CVE-2026-25157, CVE-2026-24763, ClawHavoc IOCs
58
+ - **OpenClaw security** -- 34 checks for configurations, skills, gateway, credential redaction ([6 PRs merged upstream](https://opena2a.org/blogs/securing-openclaw-6-prs-merged))
59
+ - **NemoClaw/sandbox patterns** -- curl-pipe without checksum, empty artifact digests, exec() injection, predictable /tmp paths, process.env leakage, TOCTOU races, unsafe deserialization, messaging API egress
50
60
  - **Governance gaps** -- missing SOUL.md, no capability policies, unsigned MCP servers
51
61
  - **Credential scope drift** -- Google Maps keys accessing Gemini, AWS S3 keys reaching Bedrock
52
62
  - **Supply chain risks** -- vulnerable dependencies, unsigned skills, tampered packages
53
63
  - **Memory and RAG poisoning** -- persistent instruction injection, knowledge base contamination
54
64
  - **Agent identity** -- missing cryptographic identity, capability claims without attestation
55
65
 
56
- 173 checks across 34 categories. 115 attack payloads. No flags needed.
66
+ </details>
67
+
68
+ 187 checks across 39 categories. 115 attack payloads. No flags needed.
57
69
 
58
70
  ---
59
71
 
@@ -76,7 +88,7 @@ npm install --save-dev hackmyagent
76
88
  ```
77
89
 
78
90
  ┌──────────────────────────────────────────┐
79
- │ HackMyAgent v0.11.4 — Security Scanner │
91
+ │ HackMyAgent v0.11.5 — Security Scanner │
80
92
  │ Found: 3 critical · 5 high · 12 medium │
81
93
  │ │
82
94
  │ CRED-001 critical Hardcoded API key in .env │
@@ -95,9 +107,10 @@ npm install --save-dev hackmyagent
95
107
 
96
108
  Step-by-step guides for common workflows:
97
109
 
98
- - **[Scan my agent](docs/use-cases/scan-my-agent.md)** -- Run all 173 checks and auto-fix findings (5 min)
110
+ - **[Scan my agent](docs/use-cases/scan-my-agent.md)** -- Run all 187 checks and auto-fix findings (5 min)
99
111
  - **[Red-team MCP servers](docs/use-cases/red-team-mcp.md)** -- Test MCP servers with adversarial payloads (10 min)
100
112
  - **[Secure OpenClaw](docs/use-cases/openclaw-security.md)** -- OpenClaw-specific checks, CVE detection, ClawHavoc IOC scanning (10 min)
113
+ - **Secure NemoClaw** -- Scan NVIDIA NemoClaw sandbox installations for credential exposure, network misconfig, and sandbox escape vectors (5 min)
101
114
  - **[CI/CD pipeline](docs/use-cases/ci-pipeline.md)** -- GitHub Actions with JSON/SARIF output (5 min)
102
115
 
103
116
  ---
@@ -131,7 +144,7 @@ hackmyagent secure --publish # push results to OpenA2A Registry
131
144
 
132
145
 
133
146
  <details>
134
- <summary>All 34 security categories</summary>
147
+ <summary>All 35 security categories</summary>
135
148
 
136
149
  | Category | Checks | What it detects |
137
150
  |----------|--------|-----------------|
@@ -169,6 +182,7 @@ hackmyagent secure --publish # push results to OpenA2A Registry
169
182
  | MEM | 5 | Memory poisoning, context injection |
170
183
  | RAG | 4 | RAG/knowledge base poisoning |
171
184
  | AIM | 3 | Agent identity verification |
185
+ | NEMO | 10 | NemoClaw/sandbox patterns: curl-pipe, digest bypass, exec injection, /tmp races, env leakage |
172
186
 
173
187
  </details>
174
188
 
@@ -264,11 +278,25 @@ hackmyagent harden-soul --dry-run # preview without writing
264
278
  ```
265
279
 
266
280
 
281
+ ---
282
+
283
+ ### `hackmyagent secure-nemoclaw` -- NemoClaw Sandbox Scanner
284
+
285
+ Scan NVIDIA NemoClaw installations for credential exposure, network misconfiguration, blueprint integrity issues, sandbox escape vectors, and inherited OpenClaw vulnerabilities. 28 checks across 6 categories.
286
+
287
+ ```bash
288
+ hackmyagent secure-nemoclaw # scan auto-detected directory
289
+ hackmyagent secure-nemoclaw ~/.nemoclaw # scan specific directory
290
+ hackmyagent secure-nemoclaw --json # JSON output for CI
291
+ hackmyagent secure-nemoclaw --verbose # show all checks including passed
292
+ ```
293
+
294
+
267
295
  ---
268
296
 
269
297
  ### `hackmyagent trust` -- Package Trust Verification
270
298
 
271
- Check trust levels for AI packages before installing them. Queries the [OpenA2A Registry](https://registry.opena2a.org) trust graph.
299
+ Check trust levels for AI packages before installing them. Queries the OpenA2A Registry trust graph (launching April 2026).
272
300
 
273
301
  ```bash
274
302
  hackmyagent trust server-filesystem # MCP shorthand
package/dist/cli.js CHANGED
@@ -43,6 +43,7 @@ const index_1 = require("./index");
43
43
  const resolve_mcp_1 = require("./resolve-mcp");
44
44
  const nemoclaw_scanner_1 = require("./hardening/nemoclaw-scanner");
45
45
  const program = new commander_1.Command();
46
+ program.showHelpAfterError('(run with --help for usage)');
46
47
  // Write JSON to stdout synchronously with retry for pipe backpressure.
47
48
  // process.stdout.write() is async and gets truncated when process.exit()
48
49
  // runs before the stream flushes. fs.writeFileSync(1, ...) can fail with
@@ -104,19 +105,19 @@ program
104
105
  .name('hackmyagent')
105
106
  .description(`Find it. Break it. Fix it.
106
107
 
107
- The hacker's toolkit for AI agents. 147+ security checks, 115 attack
108
+ The hacker's toolkit for AI agents. 187 security checks, 115 attack
108
109
  payloads, auto-fix with rollback, and OASB benchmark compliance.
109
110
 
110
111
  Documentation: https://hackmyagent.com/docs
111
112
 
112
113
  Updates (v${index_1.VERSION}):
113
- - MCP JSON-RPC and A2A protocol attack modes
114
- - SARIF and HTML output for all scan modes
115
- - Semantic engine (structural + LLM analysis)
116
- - OpenA2A Registry integration for trust scoring
114
+ - NemoClaw sandbox scanner (28 installation checks)
115
+ - 10 new static analysis patterns (NEMO series)
116
+ - Community trust contributions
117
+ - 187 checks across 39 categories
117
118
 
118
119
  Examples:
119
- $ hackmyagent secure Find vulnerabilities (147+ checks)
120
+ $ hackmyagent secure Find vulnerabilities (187 checks)
120
121
  $ hackmyagent attack --local Break it with 115 attack payloads
121
122
  $ hackmyagent secure --fix Fix issues automatically
122
123
  $ hackmyagent fix-all Run all security plugins
@@ -125,7 +126,7 @@ Examples:
125
126
  .option('--no-color', 'Disable colored output (also respects NO_COLOR env)');
126
127
  program.addHelpText('beforeAll', `
127
128
  Quick start:
128
- $ hackmyagent secure Scan current directory (147+ checks)
129
+ $ hackmyagent secure Scan current directory (187 checks)
129
130
  $ hackmyagent fix-all --with-aim Auto-fix + create agent identity
130
131
  $ hackmyagent attack Red-team your agent
131
132
  `);
@@ -1621,7 +1622,7 @@ program
1621
1622
  .command('secure')
1622
1623
  .description(`Scan and harden your agent setup
1623
1624
 
1624
- Performs 147 security checks across 30 categories:
1625
+ Performs 187 security checks across 39 categories:
1625
1626
  • Credentials: API key exposure, secrets in configs
1626
1627
  • MCP: Server configs, tool permissions, secrets
1627
1628
  • Network: TLS, interface bindings, CORS
@@ -1679,7 +1680,7 @@ Examples:
1679
1680
  .option('--ci', 'CI mode: suppress interactive prompts, exit non-zero on findings')
1680
1681
  .action(async (directory, options) => {
1681
1682
  try {
1682
- const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
1683
+ const targetDir = require("path").resolve(directory);
1683
1684
  // CI mode: force non-interactive defaults
1684
1685
  if (options.ci) {
1685
1686
  if (!options.format && !options.json)
@@ -1962,8 +1963,12 @@ Examples:
1962
1963
  console.log(`${colors.green}No issues found.${RESET()}\n`);
1963
1964
  }
1964
1965
  else if (issues.length > 0) {
1965
- // Print issues - clean format
1966
- console.log(`${issues.length} issue${issues.length === 1 ? '' : 's'} found:\n`);
1966
+ // Print issues - clean format with fixable count
1967
+ const fixableCount = issues.filter((f) => f.fixable).length;
1968
+ const fixableNote = fixableCount > 0
1969
+ ? ` (${fixableCount} auto-fixable with \`${CLI_PREFIX} secure --fix\`)`
1970
+ : '';
1971
+ console.log(`${issues.length} issue${issues.length === 1 ? '' : 's'} found${fixableNote}:\n`);
1967
1972
  for (const finding of issues) {
1968
1973
  const display = SEVERITY_DISPLAY[finding.severity];
1969
1974
  const location = finding.file
@@ -2022,17 +2027,32 @@ Examples:
2022
2027
  console.log(` No changes were made.\n`);
2023
2028
  }
2024
2029
  }
2025
- // Print fixed findings
2030
+ // Print fixed findings with detailed summary
2026
2031
  if (fixedFindings.length > 0) {
2027
- console.log(`${colors.green}Fixed ${fixedFindings.length} issue${fixedFindings.length === 1 ? '' : 's'}:${RESET()}`);
2032
+ const verifiedCount = fixedFindings.filter((f) => f.fixVerified).length;
2033
+ const unverifiedCount = fixedFindings.filter((f) => f.fixVerified === false).length;
2034
+ console.log(`${colors.green}Fixed ${fixedFindings.length} issue${fixedFindings.length === 1 ? '' : 's'}${verifiedCount > 0 ? ` (${verifiedCount} verified)` : ''}:${RESET()}`);
2028
2035
  for (const finding of fixedFindings) {
2029
- const location = finding.file || '';
2030
- console.log(` ${colors.green}✓${RESET()} ${location} - ${finding.name}`);
2036
+ const location = finding.file ? (finding.line ? `${finding.file}:${finding.line}` : finding.file) : '';
2037
+ const verified = finding.fixVerified;
2038
+ const verifyIcon = verified === true ? `${colors.green}✓✓${RESET()}` : verified === false ? `${colors.yellow}✓?${RESET()}` : `${colors.green}✓${RESET()}`;
2039
+ console.log(` ${verifyIcon} [${finding.checkId}] ${location} - ${finding.name}`);
2040
+ if (finding.fixMessage) {
2041
+ console.log(` ${colors.cyan}→${RESET()} ${finding.fixMessage}`);
2042
+ }
2043
+ }
2044
+ if (unverifiedCount > 0) {
2045
+ console.log(`\n ${colors.yellow}${unverifiedCount} fix${unverifiedCount === 1 ? '' : 'es'} could not be verified. Review these manually.${RESET()}`);
2031
2046
  }
2032
2047
  console.log();
2048
+ // Remaining fixable issues
2049
+ const remainingFixable = issues.filter((f) => f.fixable && !f.fixed);
2050
+ if (remainingFixable.length > 0) {
2051
+ console.log(`${colors.yellow}${remainingFixable.length} more issue${remainingFixable.length === 1 ? '' : 's'} can be auto-fixed.${RESET()} Run \`${CLI_PREFIX} secure --fix\` again.\n`);
2052
+ }
2033
2053
  if (result.backupPath) {
2034
- console.log(`Backup: ${result.backupPath}`);
2035
- console.log(`Undo: ${CLI_PREFIX} rollback ${directory}\n`);
2054
+ console.log(`${colors.yellow}Backup created:${RESET()} ${result.backupPath}`);
2055
+ console.log(`${colors.yellow}Something wrong?${RESET()} Run \`${CLI_PREFIX} rollback ${directory}\` to undo all changes.\n`);
2036
2056
  }
2037
2057
  }
2038
2058
  // Registry reporting: only when explicitly requested via --version-id (CI) or --registry-report
@@ -2644,7 +2664,7 @@ Examples:
2644
2664
  .argument('[directory]', 'Directory to rollback (defaults to current directory)', '.')
2645
2665
  .action(async (directory) => {
2646
2666
  try {
2647
- const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
2667
+ const targetDir = require("path").resolve(directory);
2648
2668
  console.log(`\nRolling back changes in ${targetDir}...\n`);
2649
2669
  const scanner = new index_1.HardeningScanner();
2650
2670
  await scanner.rollback(targetDir);
@@ -4096,7 +4116,7 @@ Examples:
4096
4116
  .option('-t, --tool <name>', 'Force specific tool: claude, cursor, vscode')
4097
4117
  .action(async (directory, options) => {
4098
4118
  try {
4099
- const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
4119
+ const targetDir = require("path").resolve(directory);
4100
4120
  const { initMcp } = await Promise.resolve().then(() => __importStar(require('./init-mcp')));
4101
4121
  const result = initMcp(targetDir, options.tool);
4102
4122
  if (!result.created) {
@@ -4106,7 +4126,7 @@ Examples:
4106
4126
  console.log(`\n Detected: ${result.tool}\n`);
4107
4127
  console.log(` Added HackMyAgent MCP server to ${result.configPath}\n`);
4108
4128
  console.log(` Available tools in ${result.tool}:`);
4109
- console.log(` hackmyagent_scan — 147+ checks + structural analysis`);
4129
+ console.log(` hackmyagent_scan — 187 checks + structural analysis`);
4110
4130
  console.log(` hackmyagent_deep_scan — Full analysis with LLM reasoning`);
4111
4131
  console.log(` hackmyagent_analyze_file — Analyze a single file`);
4112
4132
  console.log(` hackmyagent_benchmark — OASB-1 compliance assessment\n`);
@@ -4201,7 +4221,7 @@ Examples:
4201
4221
  .option('--ci', 'CI mode: suppress interactive prompts, exit non-zero on findings')
4202
4222
  .action(async (directory, options) => {
4203
4223
  try {
4204
- const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
4224
+ const targetDir = require("path").resolve(directory);
4205
4225
  // CI mode: force non-interactive defaults
4206
4226
  if (options.ci) {
4207
4227
  if (options.contribute === undefined)
@@ -4418,7 +4438,7 @@ Examples:
4418
4438
  .option('--json', 'Output as JSON')
4419
4439
  .action(async (directory, options) => {
4420
4440
  try {
4421
- const targetDir = directory.startsWith('/') ? directory : process.cwd() + '/' + directory;
4441
+ const targetDir = require("path").resolve(directory);
4422
4442
  if (!require('fs').existsSync(targetDir)) {
4423
4443
  process.stderr.write(`Error: Directory '${targetDir}' does not exist.\n`);
4424
4444
  process.exit(1);