hackmyagent 0.9.7 → 0.9.9
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 +158 -178
- package/dist/arp/patterns/ai-threats.js +3 -3
- package/dist/arp/patterns/ai-threats.js.map +1 -1
- package/dist/arp/proxy/server.d.ts.map +1 -1
- package/dist/arp/proxy/server.js +23 -4
- package/dist/arp/proxy/server.js.map +1 -1
- package/dist/cli.js +25 -8
- package/dist/cli.js.map +1 -1
- package/dist/hardening/scanner.d.ts +3 -0
- package/dist/hardening/scanner.d.ts.map +1 -1
- package/dist/hardening/scanner.js +16 -12
- package/dist/hardening/scanner.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
> **[OpenA2A](https://github.com/opena2a-org)**: [CLI](https://github.com/opena2a-org/opena2a) · [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) ·
|
|
1
|
+
> **[OpenA2A](https://github.com/opena2a-org/opena2a)**: [CLI](https://github.com/opena2a-org/opena2a) · [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 (coming soon)
|
|
2
2
|
|
|
3
3
|
# HackMyAgent
|
|
4
4
|
|
|
@@ -6,54 +6,62 @@
|
|
|
6
6
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
7
|
[](https://github.com/opena2a-org/hackmyagent)
|
|
8
8
|
|
|
9
|
-
**
|
|
9
|
+
**AI agents run code with your permissions. Find what can go wrong before an attacker does.**
|
|
10
10
|
|
|
11
|
-
AI agents
|
|
11
|
+
Security scanner and red-team toolkit for AI agents — 147 checks, 55 adversarial payloads, auto-fix with rollback, runtime protection, and OASB compliance benchmarking.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Scans Claude Code, Cursor, VS Code, and any MCP server setup.
|
|
13
|
+
Works with Claude Code, Cursor, VS Code, and any MCP server setup.
|
|
16
14
|
|
|
17
15
|
[Website](https://hackmyagent.com) | [Security Checks Reference](docs/SECURITY_CHECKS.md) | [OpenA2A CLI](https://github.com/opena2a-org/opena2a)
|
|
18
16
|
|
|
19
17
|
---
|
|
20
18
|
|
|
21
|
-
##
|
|
19
|
+
## Get Started in 30 Seconds
|
|
20
|
+
|
|
21
|
+
> **The recommended way to use HackMyAgent is through [`opena2a-cli`](https://github.com/opena2a-org/opena2a)** — the unified CLI for all OpenA2A security tools. It runs HackMyAgent under the hood along with credential scanning, config integrity, and more.
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
|
|
25
|
-
npx
|
|
26
|
-
npx hackmyagent attack --local # red-team with 55 adversarial payloads
|
|
27
|
-
npx hackmyagent secure -b oasb-1 # OASB-1 compliance benchmark
|
|
28
|
-
```
|
|
24
|
+
# Recommended: full security review via opena2a-cli
|
|
25
|
+
npx opena2a-cli review
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
# Or use HackMyAgent directly
|
|
28
|
+
npx hackmyagent secure
|
|
29
|
+
```
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
That's it. No config files, no setup, no flags needed.
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
### What happens when you run it?
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
| **Cursor** | .cursor/ rules, MCP server configs, overly permissive settings |
|
|
40
|
-
| **VS Code** | .vscode/mcp.json configurations, extension risks |
|
|
41
|
-
| **Any MCP setup** | Transport security, tool boundaries, auth weaknesses |
|
|
35
|
+
1. **Scans** your project for 147 security issues across 30 categories
|
|
36
|
+
2. **Shows** a prioritized list of findings with severity and fix guidance
|
|
37
|
+
3. **Fixes** issues automatically when you add `--fix` (backups created)
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
```
|
|
40
|
+
┌──────────────────────────────────────────────────┐
|
|
41
|
+
│ HackMyAgent v0.9.8 — Security Scanner │
|
|
42
|
+
│ Found: 3 critical · 5 high · 12 medium │
|
|
43
|
+
│ │
|
|
44
|
+
│ CRED-001 critical Hardcoded API key in .env │
|
|
45
|
+
│ MCP-003 high MCP server on 0.0.0.0 │
|
|
46
|
+
│ NET-001 high Open port exposed │
|
|
47
|
+
│ ... │
|
|
48
|
+
│ │
|
|
49
|
+
│ Run with --fix to auto-remediate 8 issues │
|
|
50
|
+
└──────────────────────────────────────────────────┘
|
|
51
|
+
```
|
|
44
52
|
|
|
45
53
|
---
|
|
46
54
|
|
|
47
55
|
## Installation
|
|
48
56
|
|
|
49
57
|
```bash
|
|
50
|
-
# Run
|
|
58
|
+
# Run without installing (recommended to start)
|
|
51
59
|
npx hackmyagent secure
|
|
52
60
|
|
|
53
61
|
# Install globally
|
|
54
62
|
npm install -g hackmyagent
|
|
55
63
|
|
|
56
|
-
# Add to
|
|
64
|
+
# Add to your project
|
|
57
65
|
npm install --save-dev hackmyagent
|
|
58
66
|
```
|
|
59
67
|
|
|
@@ -61,11 +69,32 @@ npm install --save-dev hackmyagent
|
|
|
61
69
|
|
|
62
70
|
---
|
|
63
71
|
|
|
72
|
+
## Using with opena2a-cli (Recommended)
|
|
73
|
+
|
|
74
|
+
[`opena2a-cli`](https://github.com/opena2a-org/opena2a) is the main CLI that unifies all OpenA2A security tools. HackMyAgent powers the scanning and benchmarking commands:
|
|
75
|
+
|
|
76
|
+
| opena2a-cli command | What it runs | Description |
|
|
77
|
+
|---------------------|-------------|-------------|
|
|
78
|
+
| `opena2a review` | HackMyAgent + all tools | Full security dashboard (HTML) |
|
|
79
|
+
| `opena2a init` | HackMyAgent | Security posture assessment with trust score |
|
|
80
|
+
| `opena2a protect` | HackMyAgent + Secretless | Auto-fix findings + credential protection |
|
|
81
|
+
| `opena2a scan` | HackMyAgent | 147-check security scan |
|
|
82
|
+
| `opena2a benchmark` | HackMyAgent | OASB-1 + OASB-2 compliance |
|
|
83
|
+
| `opena2a scan-soul` | HackMyAgent | Behavioral governance (SOUL.md) |
|
|
84
|
+
| `opena2a shield init` | All tools | Full security setup in one command |
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm install -g opena2a-cli
|
|
88
|
+
opena2a review # best place to start
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
64
93
|
## Commands
|
|
65
94
|
|
|
66
|
-
### `hackmyagent secure`
|
|
95
|
+
### `hackmyagent secure` — Security Scan
|
|
67
96
|
|
|
68
|
-
|
|
97
|
+
The primary command. Runs 147 checks across 30 categories.
|
|
69
98
|
|
|
70
99
|
```bash
|
|
71
100
|
hackmyagent secure # scan current directory
|
|
@@ -137,9 +166,9 @@ Use `--dry-run` to preview changes. Backups are created in `.hackmyagent-backup/
|
|
|
137
166
|
|
|
138
167
|
---
|
|
139
168
|
|
|
140
|
-
### `hackmyagent attack`
|
|
169
|
+
### `hackmyagent attack` — Red Team
|
|
141
170
|
|
|
142
|
-
|
|
171
|
+
Test your AI agent with 55 adversarial payloads across 5 attack categories.
|
|
143
172
|
|
|
144
173
|
```bash
|
|
145
174
|
hackmyagent attack --local # local simulation
|
|
@@ -194,7 +223,7 @@ Only `id` and `payload` are required.
|
|
|
194
223
|
|
|
195
224
|
---
|
|
196
225
|
|
|
197
|
-
### `hackmyagent secure -b oasb-1`
|
|
226
|
+
### `hackmyagent secure -b oasb-1` — OASB-1 Benchmark
|
|
198
227
|
|
|
199
228
|
Run the [OASB-1](https://oasb.ai/oasb-1) (Open Agent Security Benchmark) — 46 controls across 10 categories with three maturity levels.
|
|
200
229
|
|
|
@@ -233,9 +262,9 @@ Output formats: `text`, `json`, `sarif`, `html`, `asp` (Agent Security Profile).
|
|
|
233
262
|
|
|
234
263
|
---
|
|
235
264
|
|
|
236
|
-
### `hackmyagent secure -b oasb-2`
|
|
265
|
+
### `hackmyagent secure -b oasb-2` — OASB-2 Composite
|
|
237
266
|
|
|
238
|
-
|
|
267
|
+
Infrastructure security (OASB-1, 50%) + behavioral governance (scan-soul, 50%) = unified score.
|
|
239
268
|
|
|
240
269
|
```bash
|
|
241
270
|
hackmyagent secure -b oasb-2 # full composite assessment
|
|
@@ -243,27 +272,22 @@ hackmyagent secure -b oasb-2 --json # JSON output
|
|
|
243
272
|
hackmyagent secure -b oasb-2 --fail-below 60 # CI gate
|
|
244
273
|
```
|
|
245
274
|
|
|
246
|
-
|
|
275
|
+
Requires a SOUL.md (or equivalent governance file) in the scanned directory.
|
|
247
276
|
|
|
248
277
|
---
|
|
249
278
|
|
|
250
|
-
### `hackmyagent scan-soul`
|
|
279
|
+
### `hackmyagent scan-soul` — Behavioral Governance
|
|
251
280
|
|
|
252
|
-
Scan a SOUL.md
|
|
281
|
+
Scan a SOUL.md against OASB v2 behavioral governance controls — 8 domains, up to 68 controls.
|
|
253
282
|
|
|
254
283
|
```bash
|
|
255
284
|
hackmyagent scan-soul # scan current directory
|
|
256
|
-
hackmyagent scan-soul ./my-agent # scan specific directory
|
|
257
285
|
hackmyagent scan-soul --tier MULTI-AGENT # override tier detection
|
|
258
|
-
hackmyagent scan-soul --json # JSON output for CI
|
|
259
|
-
hackmyagent scan-soul --verbose # show individual control results
|
|
260
286
|
hackmyagent scan-soul --deep # LLM semantic analysis (requires ANTHROPIC_API_KEY)
|
|
261
|
-
hackmyagent scan-soul --fail-below 60 #
|
|
287
|
+
hackmyagent scan-soul --fail-below 60 # CI gate
|
|
262
288
|
```
|
|
263
289
|
|
|
264
|
-
Auto-detects governance file
|
|
265
|
-
|
|
266
|
-
Tier-to-control counts:
|
|
290
|
+
Auto-detects governance file: `SOUL.md` > `system-prompt.md` > `CLAUDE.md` > `.cursorrules` > `agent-config.yaml`.
|
|
267
291
|
|
|
268
292
|
| Tier | Controls | Use case |
|
|
269
293
|
|------|----------|----------|
|
|
@@ -272,117 +296,146 @@ Tier-to-control counts:
|
|
|
272
296
|
| `AGENTIC` | 65 | Autonomous multi-step agents |
|
|
273
297
|
| `MULTI-AGENT` | 68 | Orchestrators and sub-agent systems |
|
|
274
298
|
|
|
275
|
-
Conformance levels:
|
|
276
|
-
|
|
277
|
-
| Level | Criteria |
|
|
278
|
-
|-------|----------|
|
|
279
|
-
| `none` | A critical control (SOUL-IH-003 or SOUL-HB-001) is missing — grade capped at C |
|
|
280
|
-
| `essential` | All critical controls pass |
|
|
281
|
-
| `standard` | All critical + high controls pass, score ≥ 60 |
|
|
282
|
-
| `hardened` | All controls pass, score ≥ 75 |
|
|
283
|
-
|
|
284
299
|
---
|
|
285
300
|
|
|
286
|
-
### `hackmyagent harden-soul`
|
|
301
|
+
### `hackmyagent harden-soul` — Generate Governance
|
|
287
302
|
|
|
288
|
-
Generate a SOUL.md
|
|
303
|
+
Generate a SOUL.md or add missing governance sections. Existing content is preserved.
|
|
289
304
|
|
|
290
305
|
```bash
|
|
291
306
|
hackmyagent harden-soul # add missing sections
|
|
292
307
|
hackmyagent harden-soul --dry-run # preview without writing
|
|
293
|
-
hackmyagent harden-soul ./my-agent # target specific directory
|
|
294
|
-
hackmyagent harden-soul --json # JSON output
|
|
295
308
|
```
|
|
296
309
|
|
|
297
|
-
Generates template content for each missing OASB v2 governance domain. Run `scan-soul` after to verify coverage improved.
|
|
298
|
-
|
|
299
310
|
---
|
|
300
311
|
|
|
301
|
-
### `hackmyagent fix-all`
|
|
312
|
+
### `hackmyagent fix-all` — Fix Everything
|
|
302
313
|
|
|
303
|
-
Run all security plugins in sequence: credential vault, file signing, skill guard.
|
|
314
|
+
Run all security plugins in sequence: credential vault, file signing, skill guard.
|
|
304
315
|
|
|
305
316
|
```bash
|
|
306
317
|
hackmyagent fix-all # scan and fix
|
|
307
|
-
hackmyagent fix-all ./my-agent # target specific directory
|
|
308
318
|
hackmyagent fix-all --dry-run # preview without modifying
|
|
309
|
-
hackmyagent fix-all --scan-only # scan only, no fixes
|
|
310
319
|
hackmyagent fix-all --with-aim # add agent identity + audit logging
|
|
311
320
|
hackmyagent fix-all --json # JSON output
|
|
312
321
|
```
|
|
313
322
|
|
|
314
|
-
**Plugins run in order:**
|
|
315
|
-
|
|
316
323
|
| Plugin | What it does |
|
|
317
324
|
|--------|--------------|
|
|
318
|
-
| **SkillGuard** | Hash pinning, tamper detection, dangerous pattern scanning
|
|
319
|
-
| **SignCrypt** | Ed25519 signing
|
|
320
|
-
| **CredVault** | Credential detection
|
|
325
|
+
| **SkillGuard** | Hash pinning, tamper detection, dangerous pattern scanning |
|
|
326
|
+
| **SignCrypt** | Ed25519 signing, SHA-256 hash pinning, signature verification |
|
|
327
|
+
| **CredVault** | Credential detection, env var replacement, AES-256-GCM encrypted store |
|
|
321
328
|
|
|
322
|
-
|
|
329
|
+
`--with-aim` adds: Ed25519 agent identity, cryptographic audit log, capability policy enforcement.
|
|
323
330
|
|
|
324
331
|
---
|
|
325
332
|
|
|
326
|
-
###
|
|
333
|
+
### More Commands
|
|
327
334
|
|
|
328
|
-
|
|
335
|
+
| Command | Description |
|
|
336
|
+
|---------|-------------|
|
|
337
|
+
| `hackmyagent check @publisher/skill` | Verify a skill's publisher identity and permissions |
|
|
338
|
+
| `hackmyagent scan example.com` | Scan external infrastructure for exposed AI endpoints |
|
|
339
|
+
| `hackmyagent rollback` | Undo auto-fix changes (backups created automatically) |
|
|
340
|
+
| `hackmyagent secure-openclaw` | 47 specialized checks for OpenClaw installations |
|
|
329
341
|
|
|
330
|
-
|
|
331
|
-
hackmyagent check @publisher/skill-name
|
|
332
|
-
hackmyagent check @publisher/skill --json
|
|
333
|
-
hackmyagent check @publisher/skill --offline # skip DNS verification
|
|
334
|
-
```
|
|
342
|
+
---
|
|
335
343
|
|
|
336
|
-
|
|
344
|
+
## Runtime Protection (ARP)
|
|
337
345
|
|
|
338
|
-
|
|
346
|
+
ARP (Agent Runtime Protection) monitors AI agents during execution with a 3-layer intelligence stack:
|
|
339
347
|
|
|
340
|
-
|
|
348
|
+
- **L0**: Rule-based pattern matching (40+ threat patterns, every event, free)
|
|
349
|
+
- **L1**: Statistical anomaly detection (z-score deviation from baseline, free)
|
|
350
|
+
- **L2**: LLM-assisted assessment (micro-prompts, budget-controlled, ~$0.01/day)
|
|
341
351
|
|
|
342
|
-
|
|
352
|
+
### Monitor Mode
|
|
353
|
+
|
|
354
|
+
Watches OS-level activity: child processes, network connections, and filesystem changes.
|
|
343
355
|
|
|
344
356
|
```bash
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
357
|
+
# Generate config for your project
|
|
358
|
+
opena2a runtime init
|
|
359
|
+
|
|
360
|
+
# Start monitoring
|
|
361
|
+
opena2a runtime start
|
|
362
|
+
|
|
363
|
+
# Check status and view events
|
|
364
|
+
opena2a runtime status
|
|
365
|
+
opena2a runtime tail --count 20
|
|
348
366
|
```
|
|
349
367
|
|
|
350
|
-
|
|
368
|
+
### Proxy Mode
|
|
351
369
|
|
|
352
|
-
|
|
370
|
+
HTTP reverse proxy that inspects AI protocol traffic in real-time:
|
|
353
371
|
|
|
354
|
-
|
|
372
|
+
```bash
|
|
373
|
+
npx hackmyagent arp-guard proxy --config arp.yaml
|
|
374
|
+
```
|
|
355
375
|
|
|
356
|
-
|
|
376
|
+
Detects 40+ attack patterns across three protocols:
|
|
357
377
|
|
|
358
|
-
|
|
378
|
+
| Protocol | Detections |
|
|
379
|
+
|----------|------------|
|
|
380
|
+
| **OpenAI API** | Prompt injection (PI-001-003), jailbreak (JB-001-003), data exfiltration (DE-001-003), output leaks (OL-001-003), context manipulation (CM-001-002) |
|
|
381
|
+
| **MCP (JSON-RPC)** | Path traversal (MCP-001), command injection (MCP-002), SSRF (MCP-003), tool allowlist enforcement |
|
|
382
|
+
| **A2A** | Identity spoofing (A2A-001), delegation abuse (A2A-002), trusted agent allowlist, embedded prompt injection |
|
|
359
383
|
|
|
360
|
-
|
|
384
|
+
### Configuration (arp.yaml)
|
|
361
385
|
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
|
|
386
|
+
```yaml
|
|
387
|
+
agentName: my-agent
|
|
388
|
+
monitors:
|
|
389
|
+
process: { enabled: true, intervalMs: 5000 }
|
|
390
|
+
network: { enabled: true, intervalMs: 10000, allowedHosts: [localhost] }
|
|
391
|
+
filesystem: { enabled: true }
|
|
392
|
+
aiLayer:
|
|
393
|
+
prompt: true
|
|
394
|
+
mcp-protocol: true
|
|
395
|
+
a2a-protocol: true
|
|
396
|
+
proxy:
|
|
397
|
+
port: 8080
|
|
398
|
+
blockOnDetection: false
|
|
399
|
+
upstreams:
|
|
400
|
+
- pathPrefix: /v1
|
|
401
|
+
target: http://localhost:3000
|
|
402
|
+
protocol: openai-api
|
|
365
403
|
```
|
|
366
404
|
|
|
367
|
-
|
|
405
|
+
### Programmatic API
|
|
368
406
|
|
|
369
|
-
|
|
407
|
+
```typescript
|
|
408
|
+
import { AgentRuntimeProtection } from 'hackmyagent/arp';
|
|
370
409
|
|
|
371
|
-
|
|
410
|
+
const arp = new AgentRuntimeProtection('arp.yaml');
|
|
411
|
+
await arp.start();
|
|
372
412
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
413
|
+
arp.onEvent((event) => console.log(event.severity, event.description));
|
|
414
|
+
arp.onEnforcement((result) => console.log(result.action, result.event));
|
|
415
|
+
|
|
416
|
+
// When done
|
|
417
|
+
await arp.stop();
|
|
378
418
|
```
|
|
379
419
|
|
|
380
|
-
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## What It Scans
|
|
423
|
+
|
|
424
|
+
| Platform | What HackMyAgent detects |
|
|
425
|
+
|----------|--------------------------|
|
|
426
|
+
| **Claude Code** | CLAUDE.md misconfigurations, skill permissions, MCP server exposure |
|
|
427
|
+
| **Cursor** | .cursor/ rules, MCP server configs, overly permissive settings |
|
|
428
|
+
| **VS Code** | .vscode/mcp.json configurations, extension risks |
|
|
429
|
+
| **Any MCP setup** | Transport security, tool boundaries, auth weaknesses |
|
|
430
|
+
|
|
431
|
+
All platforms are scanned automatically — no flags needed.
|
|
381
432
|
|
|
382
433
|
---
|
|
383
434
|
|
|
384
435
|
## CI/CD Integration
|
|
385
436
|
|
|
437
|
+
All commands support `--json` and `--ci` flags.
|
|
438
|
+
|
|
386
439
|
### GitHub Actions
|
|
387
440
|
|
|
388
441
|
```yaml
|
|
@@ -417,16 +470,6 @@ jobs:
|
|
|
417
470
|
npx hackmyagent secure --ignore LOG-001,RATE-001
|
|
418
471
|
```
|
|
419
472
|
|
|
420
|
-
### JSON Output
|
|
421
|
-
|
|
422
|
-
```bash
|
|
423
|
-
# Filter critical findings
|
|
424
|
-
hackmyagent secure --json | jq '.findings[] | select(.severity == "critical")'
|
|
425
|
-
|
|
426
|
-
# Count issues by category
|
|
427
|
-
hackmyagent secure --json | jq '[.findings[].id | split("-")[0]] | group_by(.) | map({(.[0]): length}) | add'
|
|
428
|
-
```
|
|
429
|
-
|
|
430
473
|
---
|
|
431
474
|
|
|
432
475
|
## Exit Codes
|
|
@@ -439,80 +482,17 @@ hackmyagent secure --json | jq '[.findings[].id | split("-")[0]] | group_by(.) |
|
|
|
439
482
|
|
|
440
483
|
---
|
|
441
484
|
|
|
442
|
-
##
|
|
443
|
-
|
|
444
|
-
HackMyAgent consolidates several OpenA2A security modules into a single package:
|
|
445
|
-
|
|
446
|
-
| Module | Description | Previously |
|
|
447
|
-
|--------|-------------|------------|
|
|
448
|
-
| Security scanner | 147 checks across 30 categories | hackmyagent-core |
|
|
449
|
-
| Attack simulation | 55 adversarial payloads, 5 categories | standalone |
|
|
450
|
-
| CredVault plugin | Credential detection + AES-256-GCM vault | @opena2a/credvault |
|
|
451
|
-
| SignCrypt plugin | Ed25519 signing + SHA-256 hash pinning | @opena2a/signcrypt |
|
|
452
|
-
| SkillGuard plugin | Permission pinning + tamper detection | @opena2a/skillguard |
|
|
453
|
-
| OASB benchmark | 46 controls, 3 maturity levels | @opena2a/oasb |
|
|
454
|
-
| ARP integration | Agent Runtime Protection hooks | @opena2a/arp |
|
|
455
|
-
| Semantic engine | Semantic analysis for finding deduplication | @opena2a/semantic-engine |
|
|
456
|
-
|
|
457
|
-
### Subpath Exports
|
|
458
|
-
|
|
459
|
-
For programmatic use, the package exposes subpath exports:
|
|
485
|
+
## Programmatic API
|
|
460
486
|
|
|
461
487
|
```typescript
|
|
462
488
|
import { HardeningScanner } from 'hackmyagent'; // Scanner engine
|
|
463
489
|
import { registerPlugin } from 'hackmyagent/plugins'; // Plugin API
|
|
464
490
|
import { SemanticEngine } from 'hackmyagent/semantic'; // Semantic analysis
|
|
465
|
-
import {
|
|
491
|
+
import { AgentRuntimeProtection } from 'hackmyagent/arp'; // Runtime protection
|
|
466
492
|
import { OASBHarness } from 'hackmyagent/oasb'; // Benchmark harness
|
|
467
493
|
```
|
|
468
494
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
## Writing Plugins
|
|
472
|
-
|
|
473
|
-
HackMyAgent supports custom security plugins. Each plugin implements `scan()` and `fix()` methods.
|
|
474
|
-
|
|
475
|
-
```typescript
|
|
476
|
-
import type { OpenA2APlugin, Finding, Remediation, FixOptions } from 'hackmyagent/plugins';
|
|
477
|
-
|
|
478
|
-
export class MyPlugin implements OpenA2APlugin {
|
|
479
|
-
readonly metadata = {
|
|
480
|
-
packageName: '@my-org/my-plugin',
|
|
481
|
-
displayName: 'My Plugin',
|
|
482
|
-
description: 'Detects and fixes X',
|
|
483
|
-
version: '1.0.0',
|
|
484
|
-
findings: ['MY-001'],
|
|
485
|
-
scoreImprovement: 10,
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
async scan(agentDir: string): Promise<Finding[]> {
|
|
489
|
-
return [{
|
|
490
|
-
id: 'MY-001',
|
|
491
|
-
title: 'Insecure widget',
|
|
492
|
-
description: 'Widget uses plaintext.',
|
|
493
|
-
severity: 'high',
|
|
494
|
-
filePath: 'config.json',
|
|
495
|
-
line: 12,
|
|
496
|
-
autoFixable: true,
|
|
497
|
-
}];
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
async fix(agentDir: string, options?: FixOptions): Promise<Remediation[]> {
|
|
501
|
-
if (options?.dryRun) return [{ findingId: 'MY-001', description: 'Would encrypt widget', filesModified: ['config.json'], rollbackAvailable: false }];
|
|
502
|
-
return [{ findingId: 'MY-001', description: 'Encrypted widget', filesModified: ['config.json'], rollbackAvailable: false }];
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
See the [full plugin API documentation](docs/PLUGIN_API.md) for details.
|
|
508
|
-
|
|
509
|
-
---
|
|
510
|
-
|
|
511
|
-
## Environment Variables
|
|
512
|
-
|
|
513
|
-
| Variable | Description |
|
|
514
|
-
|----------|-------------|
|
|
515
|
-
| `NO_COLOR` | Disable colored output |
|
|
495
|
+
See the [Plugin API documentation](docs/PLUGIN_API.md) for writing custom security plugins.
|
|
516
496
|
|
|
517
497
|
---
|
|
518
498
|
|
|
@@ -525,7 +505,7 @@ git clone https://github.com/opena2a-org/hackmyagent.git
|
|
|
525
505
|
cd hackmyagent
|
|
526
506
|
npm install
|
|
527
507
|
npm run build
|
|
528
|
-
npm test #
|
|
508
|
+
npm test # 817 tests
|
|
529
509
|
```
|
|
530
510
|
|
|
531
511
|
---
|
|
@@ -540,8 +520,8 @@ Apache-2.0
|
|
|
540
520
|
|
|
541
521
|
| Project | Description | Install |
|
|
542
522
|
|---------|-------------|---------|
|
|
543
|
-
| [**OpenA2A CLI**](https://github.com/opena2a-org/opena2a) | Unified security CLI
|
|
523
|
+
| [**OpenA2A CLI**](https://github.com/opena2a-org/opena2a) | Unified security CLI — scan, protect, guard, shield | `npm install -g opena2a-cli` |
|
|
544
524
|
| [**Secretless AI**](https://github.com/opena2a-org/secretless-ai) | Keep credentials out of AI context windows | `npx secretless-ai init` |
|
|
545
|
-
| [**AIM**](https://github.com/opena2a-org/agent-identity-management) | Agent
|
|
525
|
+
| [**AIM**](https://github.com/opena2a-org/agent-identity-management) | Agent identity and access control for AI agents | Self-hosted |
|
|
546
526
|
| [**AI Browser Guard**](https://github.com/opena2a-org/AI-BrowserGuard) | Detect and control AI agents in the browser | Chrome Web Store |
|
|
547
|
-
| [**DVAA**](https://github.com/opena2a-org/damn-vulnerable-ai-agent) |
|
|
527
|
+
| [**DVAA**](https://github.com/opena2a-org/damn-vulnerable-ai-agent) | Deliberately vulnerable AI agent for training | `docker pull opena2a/dvaa` |
|
|
@@ -10,7 +10,7 @@ const promptInjection = [
|
|
|
10
10
|
id: 'PI-001',
|
|
11
11
|
category: 'prompt-injection',
|
|
12
12
|
description: 'Instruction override attempt — direct override of system instructions',
|
|
13
|
-
pattern: /(?:ignore|disregard|forget|override|bypass)\s+(?:all\s+)?(?:your\s+|the\s+|my\s+)?(?:previous
|
|
13
|
+
pattern: /(?:ignore|disregard|forget|override|bypass)\s+(?:all\s+)?(?:your\s+|the\s+|my\s+)?(?:previous\s+|prior\s+|above\s+|earlier\s+|system\s+|original\s+)?(?:instructions?|prompts?|rules?|directives?|guidelines?|constraints?)/i,
|
|
14
14
|
severity: 'critical',
|
|
15
15
|
},
|
|
16
16
|
{
|
|
@@ -34,7 +34,7 @@ const jailbreak = [
|
|
|
34
34
|
id: 'JB-001',
|
|
35
35
|
category: 'jailbreak',
|
|
36
36
|
description: 'DAN mode — "Do Anything Now" jailbreak attempt',
|
|
37
|
-
pattern:
|
|
37
|
+
pattern: /(?:\b(?:DAN|D\.A\.N|do\s+anything\s+now)\b.*(?:mode|persona|act|pretend|enable|activate|jailbr[eo]ak)|(?:act|pretend|behave|roleplay|play)\s+(?:as|like)\s+(?:a\s+)?(?:DAN|D\.A\.N)\b|do\s+anything\s+now)/i,
|
|
38
38
|
severity: 'critical',
|
|
39
39
|
},
|
|
40
40
|
{
|
|
@@ -65,7 +65,7 @@ const dataExfiltration = [
|
|
|
65
65
|
id: 'DE-002',
|
|
66
66
|
category: 'data-exfiltration',
|
|
67
67
|
description: 'Credential extraction — attempting to extract secrets or API keys',
|
|
68
|
-
pattern: /(?:(?:what|show|reveal|give|tell|display|print|dump|list)\s+(?:me\s+)?(?:are\s+)?(?:your\s+|the\s+)?(?:api\s+keys?|secrets?|credentials?|passwords?|tokens?|auth(?:entication)?|(?:private|secret)\s+keys?|(?:access|bearer)\s+tokens?|environment\s+variables?|env\s+vars?|\.env))/i,
|
|
68
|
+
pattern: /(?:(?:what|show|reveal|give|tell|display|print|dump|list|output|extract|expose|leak)\s+(?:me\s+)?(?:are\s+)?(?:your\s+|the\s+|any\s+)?(?:api\s+keys?|secrets?|credentials?|passwords?|tokens?|auth(?:entication)?|(?:private|secret)\s+keys?|(?:access|bearer)\s+tokens?|environment\s+variables?|env\s+vars?|\.env))/i,
|
|
69
69
|
severity: 'critical',
|
|
70
70
|
},
|
|
71
71
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-threats.js","sourceRoot":"","sources":["../../../src/arp/patterns/ai-threats.ts"],"names":[],"mappings":";AAAA,qCAAqC;AACrC,qDAAqD;;;AAyOrD,4BAoBC;AA9OD,oCAAoC;AAEpC,MAAM,eAAe,GAAoB;IACvC;QACE,EAAE,EAAE,QAAQ;QACZ,QAAQ,EAAE,kBAAkB;QAC5B,WAAW,EAAE,uEAAuE;QACpF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ai-threats.js","sourceRoot":"","sources":["../../../src/arp/patterns/ai-threats.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/arp/proxy/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAA2B,MAAM,UAAU,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAI3E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED;;;;;;GAMG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY;IAK7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,OAAO,IAAI,MAAM;YAIH,aAAa;IAsD3B,OAAO,CAAC,YAAY;IAQpB;;;OAGG;YACW,cAAc;IA8B5B;;OAEG;YACW,eAAe;IA+B7B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,qBAAqB;IAsB7B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/arp/proxy/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAA2B,MAAM,UAAU,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAI3E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,WAAW,CAAC;IACpB,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,cAAc,CAAC,EAAE,sBAAsB,CAAC;CACzC;AAED;;;;;;GAMG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,MAAM,CAA4B;gBAE9B,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,YAAY;IAK7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmBtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,OAAO,IAAI,MAAM;YAIH,aAAa;IAsD3B,OAAO,CAAC,YAAY;IAQpB;;;OAGG;YACW,cAAc;IA8B5B;;OAEG;YACW,eAAe;IA+B7B,OAAO,CAAC,oBAAoB;IAqB5B,OAAO,CAAC,qBAAqB;IAsB7B,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,kBAAkB;IA8B1B,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,iBAAiB;CAgD1B"}
|
package/dist/arp/proxy/server.js
CHANGED
|
@@ -316,11 +316,30 @@ class ARPProxy {
|
|
|
316
316
|
else if (typeof parsed.params?.content === 'string') {
|
|
317
317
|
content = parsed.params.content;
|
|
318
318
|
}
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
return result.detected;
|
|
319
|
+
else if (typeof parsed.message === 'string') {
|
|
320
|
+
content = parsed.message;
|
|
322
321
|
}
|
|
323
|
-
|
|
322
|
+
else if (parsed.payload) {
|
|
323
|
+
// Common A2A formats: { payload: { task: "..." } } or { payload: "..." }
|
|
324
|
+
if (typeof parsed.payload === 'string') {
|
|
325
|
+
content = parsed.payload;
|
|
326
|
+
}
|
|
327
|
+
else if (typeof parsed.payload.task === 'string') {
|
|
328
|
+
content = parsed.payload.task;
|
|
329
|
+
}
|
|
330
|
+
else if (typeof parsed.payload.content === 'string') {
|
|
331
|
+
content = parsed.payload.content;
|
|
332
|
+
}
|
|
333
|
+
else if (typeof parsed.payload.message === 'string') {
|
|
334
|
+
content = parsed.payload.message;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else if (typeof parsed.task === 'string') {
|
|
338
|
+
content = parsed.task;
|
|
339
|
+
}
|
|
340
|
+
// Always scan if we have content or a sender identity to check
|
|
341
|
+
const result = this.deps.a2aInterceptor.scanMessage(from, to, content || bodyStr);
|
|
342
|
+
return result.detected;
|
|
324
343
|
}
|
|
325
344
|
catch {
|
|
326
345
|
return false;
|