opena2a-cli 0.3.6 → 0.3.8
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 +73 -12
- package/dist/adapters/registry.d.ts.map +1 -1
- package/dist/adapters/registry.js +13 -6
- package/dist/adapters/registry.js.map +1 -1
- package/dist/commands/identity.d.ts +12 -0
- package/dist/commands/identity.d.ts.map +1 -0
- package/dist/commands/identity.js +157 -0
- package/dist/commands/identity.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +91 -39
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/onepassword-migration.d.ts.map +1 -1
- package/dist/commands/onepassword-migration.js +7 -4
- package/dist/commands/onepassword-migration.js.map +1 -1
- package/dist/commands/protect.d.ts.map +1 -1
- package/dist/commands/protect.js +75 -19
- package/dist/commands/protect.js.map +1 -1
- package/dist/commands/runtime.d.ts.map +1 -1
- package/dist/commands/runtime.js +3 -3
- package/dist/commands/runtime.js.map +1 -1
- package/dist/commands/shield.d.ts.map +1 -1
- package/dist/commands/shield.js +3 -9
- package/dist/commands/shield.js.map +1 -1
- package/dist/commands/vault-migration.d.ts +17 -0
- package/dist/commands/vault-migration.d.ts.map +1 -0
- package/dist/commands/vault-migration.js +212 -0
- package/dist/commands/vault-migration.js.map +1 -0
- package/dist/index.js +27 -2
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +32 -4
- package/dist/router.js.map +1 -1
- package/dist/util/colors.d.ts +1 -0
- package/dist/util/colors.d.ts.map +1 -1
- package/dist/util/colors.js +2 -1
- package/dist/util/colors.js.map +1 -1
- package/dist/util/credential-patterns.d.ts.map +1 -1
- package/dist/util/credential-patterns.js +11 -2
- package/dist/util/credential-patterns.js.map +1 -1
- package/dist/util/format.js +2 -2
- package/dist/util/format.js.map +1 -1
- package/dist/util/report-submission.d.ts +5 -0
- package/dist/util/report-submission.d.ts.map +1 -1
- package/dist/util/report-submission.js +64 -0
- package/dist/util/report-submission.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Open-source security platform for AI agents**
|
|
6
6
|
|
|
7
|
-
Credential detection, scope drift analysis, config integrity, runtime monitoring, and supply chain verification -- one CLI.
|
|
7
|
+
Credential detection, scope drift analysis, config integrity, runtime monitoring, behavioral governance scanning, and supply chain verification -- one CLI.
|
|
8
8
|
|
|
9
9
|
[](https://github.com/opena2a-org/opena2a/blob/main/LICENSE)
|
|
10
10
|
[]()
|
|
@@ -36,7 +36,7 @@ No configuration required. Works with Node.js, Python, Go, and MCP server projec
|
|
|
36
36
|
Run `opena2a init` in any project directory to get an instant security assessment:
|
|
37
37
|
|
|
38
38
|
```
|
|
39
|
-
OpenA2A Security Report v0.3.
|
|
39
|
+
OpenA2A Security Report v0.3.7
|
|
40
40
|
|
|
41
41
|
Project myapp v2.1.0
|
|
42
42
|
Type Node.js + MCP server
|
|
@@ -435,6 +435,8 @@ The CLI orchestrates these specialized tools through a unified interface:
|
|
|
435
435
|
| Command | Tool | Description |
|
|
436
436
|
|---------|------|-------------|
|
|
437
437
|
| `opena2a scan` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | 150+ security checks, attack simulation, auto-fix |
|
|
438
|
+
| `opena2a scan-soul` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | Behavioral governance scan against AGS (SOUL.md) |
|
|
439
|
+
| `opena2a harden-soul` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | Generate or improve SOUL.md governance file |
|
|
438
440
|
| `opena2a secrets` | [Secretless AI](https://github.com/opena2a-org/secretless-ai) | Credential management for AI coding tools |
|
|
439
441
|
| `opena2a benchmark` | [OASB](https://github.com/opena2a-org/oasb) | 222 attack scenarios, compliance scoring |
|
|
440
442
|
| `opena2a registry` | [AI Trust](https://github.com/opena2a-org/ai-trust) | Trust Registry queries, package verification |
|
|
@@ -446,32 +448,91 @@ The CLI orchestrates these specialized tools through a unified interface:
|
|
|
446
448
|
|
|
447
449
|
Adapters install tools on first use. Each tool works standalone or through the CLI.
|
|
448
450
|
|
|
451
|
+
## Behavioral Governance
|
|
452
|
+
|
|
453
|
+
The [Agent Governance Specification (AGS)](https://github.com/opena2a-org/agent-governance-spec) defines a tiered behavioral safety framework for AI agents across 8 domains and 68 controls (OASB v2). OpenA2A CLI integrates AGS scanning through HackMyAgent.
|
|
454
|
+
|
|
455
|
+
### `opena2a scan-soul`
|
|
456
|
+
|
|
457
|
+
Scan your governance file (SOUL.md or equivalent) against AGS controls for your agent's capability tier. Auto-detects tier from file content.
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
opena2a scan-soul # Scan SOUL.md in current directory
|
|
461
|
+
opena2a scan-soul ./agent/ # Scan specific directory
|
|
462
|
+
opena2a scan-soul --tier TOOL-USING # Force TOOL-USING tier (54 controls)
|
|
463
|
+
opena2a scan-soul --tier AGENTIC # Force AGENTIC tier (65 controls)
|
|
464
|
+
opena2a scan-soul --tier MULTI-AGENT # Force MULTI-AGENT tier (68 controls)
|
|
465
|
+
opena2a scan-soul --json # Machine-readable output for CI
|
|
466
|
+
opena2a scan-soul --deep # Enable LLM semantic analysis (requires ANTHROPIC_API_KEY)
|
|
467
|
+
opena2a scan-soul --fail-below 60 # Exit 1 if score below threshold
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Tier-to-control mapping:
|
|
471
|
+
|
|
472
|
+
| Tier | Controls | Use Case |
|
|
473
|
+
|------|----------|----------|
|
|
474
|
+
| `BASIC` | 27 | Single-turn chatbots, no tool use |
|
|
475
|
+
| `TOOL-USING` | 54 | Agents with tool/function calling |
|
|
476
|
+
| `AGENTIC` | 65 | Long-running, multi-step autonomous agents |
|
|
477
|
+
| `MULTI-AGENT` | 68 | Orchestrators and sub-agent systems |
|
|
478
|
+
|
|
479
|
+
Governance file search order: `SOUL.md` > `system-prompt.md` > `CLAUDE.md` > `.cursorrules` > `agent-config.yaml` (and more).
|
|
480
|
+
|
|
481
|
+
Conformance levels shown in output:
|
|
482
|
+
- `none` — a critical control is missing (grade capped at C)
|
|
483
|
+
- `essential` — all critical controls pass
|
|
484
|
+
- `standard` — all critical + high controls pass, score ≥ 60
|
|
485
|
+
- `hardened` — all controls pass, score ≥ 75
|
|
486
|
+
|
|
487
|
+
### `opena2a harden-soul`
|
|
488
|
+
|
|
489
|
+
Generate a SOUL.md governance file, or add missing sections to an existing one. Existing content is always preserved.
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
opena2a harden-soul # Add missing sections to SOUL.md
|
|
493
|
+
opena2a harden-soul ./agent/ # Target specific directory
|
|
494
|
+
opena2a harden-soul --dry-run # Preview what would be added, no writes
|
|
495
|
+
opena2a harden-soul --json # Machine-readable output
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
The 8 AGS behavioral domains (OASB v2, domains 7–14):
|
|
499
|
+
|
|
500
|
+
| Domain | What it governs |
|
|
501
|
+
|--------|----------------|
|
|
502
|
+
| Trust Hierarchy | Principal relationships, conflict resolution |
|
|
503
|
+
| Capability Boundaries | Allowed/denied actions, least privilege |
|
|
504
|
+
| Injection Hardening | Prompt injection defense, encoded payload rejection |
|
|
505
|
+
| Data Handling | PII protection, credential handling, data minimization |
|
|
506
|
+
| Hardcoded Behaviors | Immutable safety rules (no exfiltration, kill switch) |
|
|
507
|
+
| Agentic Safety | Iteration limits, budget caps, rollback, plan disclosure |
|
|
508
|
+
| Honesty and Transparency | Uncertainty acknowledgment, identity disclosure |
|
|
509
|
+
| Human Oversight | Approval gates, override mechanisms, monitoring |
|
|
510
|
+
|
|
449
511
|
## CI/CD Integration
|
|
450
512
|
|
|
451
|
-
|
|
513
|
+
Several commands support `--json` output and `--fail-below` for pipeline gates:
|
|
452
514
|
|
|
453
515
|
```yaml
|
|
454
516
|
# GitHub Actions example
|
|
455
|
-
- name: Security assessment
|
|
456
|
-
run: npx opena2a-cli init --ci --format json > security-report.json
|
|
457
|
-
|
|
458
517
|
- name: Credential check
|
|
459
518
|
run: |
|
|
460
|
-
npx opena2a-cli protect --dry-run --
|
|
461
|
-
# Fail if credentials found
|
|
519
|
+
npx opena2a-cli protect --dry-run --json > cred-report.json
|
|
462
520
|
jq -e '.totalFound == 0' cred-report.json
|
|
463
521
|
|
|
522
|
+
- name: Behavioral governance gate
|
|
523
|
+
run: npx opena2a-cli scan-soul --json --fail-below 60
|
|
524
|
+
|
|
464
525
|
- name: Config integrity
|
|
465
|
-
run: npx opena2a-cli guard verify
|
|
526
|
+
run: npx opena2a-cli guard verify
|
|
466
527
|
```
|
|
467
528
|
|
|
468
529
|
## Output Formats
|
|
469
530
|
|
|
470
531
|
| Format | Flag | Use Case |
|
|
471
532
|
|--------|------|----------|
|
|
472
|
-
| Text |
|
|
473
|
-
| JSON | `--
|
|
474
|
-
| HTML | `--report <path>` | Interactive report
|
|
533
|
+
| Text | (default) | Human-readable terminal output |
|
|
534
|
+
| JSON | `--json` | CI pipelines, programmatic consumption |
|
|
535
|
+
| HTML | `--report <path>` | Interactive report (protect and shield commands) |
|
|
475
536
|
|
|
476
537
|
## Credential Patterns
|
|
477
538
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA4D1D,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAE1E"}
|
|
@@ -24,6 +24,18 @@ exports.ADAPTER_REGISTRY = {
|
|
|
24
24
|
packageName: 'hackmyagent',
|
|
25
25
|
description: 'Run security benchmark against AI agent (OASB)',
|
|
26
26
|
},
|
|
27
|
+
'scan-soul': {
|
|
28
|
+
name: 'scan-soul',
|
|
29
|
+
method: 'import',
|
|
30
|
+
packageName: 'hackmyagent',
|
|
31
|
+
description: 'Scan governance file for behavioral safety coverage (AGS)',
|
|
32
|
+
},
|
|
33
|
+
'harden-soul': {
|
|
34
|
+
name: 'harden-soul',
|
|
35
|
+
method: 'import',
|
|
36
|
+
packageName: 'hackmyagent',
|
|
37
|
+
description: 'Generate or improve governance file with AGS templates',
|
|
38
|
+
},
|
|
27
39
|
registry: {
|
|
28
40
|
name: 'registry',
|
|
29
41
|
method: 'import',
|
|
@@ -42,12 +54,7 @@ exports.ADAPTER_REGISTRY = {
|
|
|
42
54
|
pythonModule: 'cryptoserve',
|
|
43
55
|
description: 'Cryptographic inventory and PQC readiness (CryptoServe)',
|
|
44
56
|
},
|
|
45
|
-
identity
|
|
46
|
-
name: 'identity',
|
|
47
|
-
method: 'spawn',
|
|
48
|
-
command: 'aim',
|
|
49
|
-
description: 'Agent identity management (AIM SDK)',
|
|
50
|
-
},
|
|
57
|
+
// identity is now handled directly by packages/cli/src/commands/identity.ts
|
|
51
58
|
// guard is now handled directly by packages/cli/src/commands/guard.ts (ConfigGuard)
|
|
52
59
|
broker: {
|
|
53
60
|
name: 'broker',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":";;;AAgEA,gCAEC;AAED,oCAEC;AAED,kDAEC;AAxEY,QAAA,gBAAgB,GAAkC;IAC7D,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,0DAA0D;KACxE;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,qDAAqD;KACnE;IACD,0EAA0E;IAC1E,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,gDAAgD;KAC9D;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,2DAA2D;KACzE;IACD,aAAa,EAAE;QACb,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,wDAAwD;KACtE;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,wDAAwD;KACtE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,gDAAgD;KAC9D;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,yDAAyD;KACvE;IACD,4EAA4E;IAC5E,oFAAoF;IACpF,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,yCAAyC;KACvD;IACD,iFAAiF;CAClF,CAAC;AAEF,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,wBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB,CAAC,MAAqB;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface IdentityOptions {
|
|
2
|
+
subcommand: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
limit?: number;
|
|
5
|
+
dir?: string;
|
|
6
|
+
ci?: boolean;
|
|
7
|
+
format?: string;
|
|
8
|
+
verbose?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function identity(options: IdentityOptions): Promise<number>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/commands/identity.ts"],"names":[],"mappings":"AAGA,UAAU,eAAe;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBxE"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.identity = identity;
|
|
4
|
+
const colors_js_1 = require("../util/colors.js");
|
|
5
|
+
async function identity(options) {
|
|
6
|
+
const sub = options.subcommand;
|
|
7
|
+
switch (sub) {
|
|
8
|
+
case 'list':
|
|
9
|
+
case 'show':
|
|
10
|
+
return handleList(options);
|
|
11
|
+
case 'create':
|
|
12
|
+
return handleCreate(options);
|
|
13
|
+
case 'trust':
|
|
14
|
+
return handleTrust(options);
|
|
15
|
+
case 'audit':
|
|
16
|
+
return handleAudit(options);
|
|
17
|
+
default:
|
|
18
|
+
process.stderr.write(`Unknown identity subcommand: ${sub}\n`);
|
|
19
|
+
process.stderr.write('\nUsage: opena2a identity <list|create|trust|audit>\n\n');
|
|
20
|
+
process.stderr.write(' list Show local agent identity\n');
|
|
21
|
+
process.stderr.write(' create --name <n> Create a new agent identity\n');
|
|
22
|
+
process.stderr.write(' trust Show trust score\n');
|
|
23
|
+
process.stderr.write(' audit [--limit N] Show recent audit events\n');
|
|
24
|
+
return 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async function loadAimCore() {
|
|
28
|
+
try {
|
|
29
|
+
return await import('@opena2a/aim-core');
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
process.stderr.write('aim-core is not available.\n');
|
|
33
|
+
process.stderr.write('Install: npm install @opena2a/aim-core\n');
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function handleList(options) {
|
|
38
|
+
const mod = await loadAimCore();
|
|
39
|
+
if (!mod)
|
|
40
|
+
return 1;
|
|
41
|
+
const isJson = options.format === 'json';
|
|
42
|
+
try {
|
|
43
|
+
const aim = new mod.AIMCore({ agentName: 'default' });
|
|
44
|
+
const id = aim.getIdentity();
|
|
45
|
+
if (isJson) {
|
|
46
|
+
process.stdout.write(JSON.stringify(id, null, 2) + '\n');
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
process.stdout.write((0, colors_js_1.bold)('Agent Identity') + '\n');
|
|
50
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
|
|
51
|
+
process.stdout.write(` Agent ID: ${(0, colors_js_1.cyan)(id.agentId)}\n`);
|
|
52
|
+
process.stdout.write(` Name: ${id.agentName}\n`);
|
|
53
|
+
process.stdout.write(` Public Key: ${(0, colors_js_1.dim)(id.publicKey.slice(0, 32) + '...')}\n`);
|
|
54
|
+
process.stdout.write(` Created: ${id.createdAt}\n`);
|
|
55
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
process.stderr.write(`Failed to load identity: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
60
|
+
return 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function handleCreate(options) {
|
|
64
|
+
const mod = await loadAimCore();
|
|
65
|
+
if (!mod)
|
|
66
|
+
return 1;
|
|
67
|
+
const name = options.name;
|
|
68
|
+
if (!name) {
|
|
69
|
+
process.stderr.write('Missing required option: --name <name>\n');
|
|
70
|
+
process.stderr.write('Usage: opena2a identity create --name my-agent\n');
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
const isJson = options.format === 'json';
|
|
74
|
+
try {
|
|
75
|
+
const aim = new mod.AIMCore({ agentName: name });
|
|
76
|
+
const id = aim.getIdentity();
|
|
77
|
+
if (isJson) {
|
|
78
|
+
process.stdout.write(JSON.stringify(id, null, 2) + '\n');
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
process.stdout.write((0, colors_js_1.green)('Identity created') + '\n');
|
|
82
|
+
process.stdout.write(` Agent ID: ${(0, colors_js_1.cyan)(id.agentId)}\n`);
|
|
83
|
+
process.stdout.write(` Name: ${id.agentName}\n`);
|
|
84
|
+
process.stdout.write(` Public Key: ${(0, colors_js_1.dim)(id.publicKey.slice(0, 32) + '...')}\n`);
|
|
85
|
+
process.stdout.write(` Stored in: ${(0, colors_js_1.dim)(aim.getDataDir())}\n`);
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
process.stderr.write(`Failed to create identity: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
90
|
+
return 1;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function handleTrust(options) {
|
|
94
|
+
const mod = await loadAimCore();
|
|
95
|
+
if (!mod)
|
|
96
|
+
return 1;
|
|
97
|
+
const isJson = options.format === 'json';
|
|
98
|
+
try {
|
|
99
|
+
const aim = new mod.AIMCore({ agentName: 'default' });
|
|
100
|
+
aim.getIdentity(); // ensure identity exists
|
|
101
|
+
const trust = aim.calculateTrust();
|
|
102
|
+
if (isJson) {
|
|
103
|
+
process.stdout.write(JSON.stringify(trust, null, 2) + '\n');
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
process.stdout.write((0, colors_js_1.bold)('Trust Score') + '\n');
|
|
107
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
|
|
108
|
+
process.stdout.write(` Score: ${(0, colors_js_1.bold)(String(trust.score))} Grade: ${(0, colors_js_1.bold)(trust.grade)}\n`);
|
|
109
|
+
process.stdout.write('\n');
|
|
110
|
+
process.stdout.write(' Factors:\n');
|
|
111
|
+
for (const [factor, value] of Object.entries(trust.factors)) {
|
|
112
|
+
const label = factor.replace(/([A-Z])/g, ' $1').toLowerCase().trim();
|
|
113
|
+
const status = value > 0 ? (0, colors_js_1.green)('active') : (0, colors_js_1.dim)('inactive');
|
|
114
|
+
process.stdout.write(` ${label.padEnd(22)} ${status}\n`);
|
|
115
|
+
}
|
|
116
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
process.stderr.write(`Failed to calculate trust: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
121
|
+
return 1;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function handleAudit(options) {
|
|
125
|
+
const mod = await loadAimCore();
|
|
126
|
+
if (!mod)
|
|
127
|
+
return 1;
|
|
128
|
+
const isJson = options.format === 'json';
|
|
129
|
+
const limit = options.limit ?? 10;
|
|
130
|
+
try {
|
|
131
|
+
const aim = new mod.AIMCore({ agentName: 'default' });
|
|
132
|
+
const events = aim.readAuditLog({ limit });
|
|
133
|
+
if (isJson) {
|
|
134
|
+
process.stdout.write(JSON.stringify(events, null, 2) + '\n');
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
if (events.length === 0) {
|
|
138
|
+
process.stdout.write((0, colors_js_1.dim)('No audit events recorded yet.') + '\n');
|
|
139
|
+
process.stdout.write((0, colors_js_1.dim)('Events are logged when using aim-core in your agent.') + '\n');
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
142
|
+
process.stdout.write((0, colors_js_1.bold)(`Audit Log (last ${events.length})`) + '\n');
|
|
143
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(70)) + '\n');
|
|
144
|
+
for (const e of events) {
|
|
145
|
+
const ts = e.timestamp.slice(0, 19).replace('T', ' ');
|
|
146
|
+
const resultColor = e.result === 'allowed' ? colors_js_1.green : e.result === 'denied' ? colors_js_1.yellow : colors_js_1.dim;
|
|
147
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(ts)} ${e.action.padEnd(16)} ${e.target.padEnd(16)} ${resultColor(e.result)}\n`);
|
|
148
|
+
}
|
|
149
|
+
process.stdout.write((0, colors_js_1.gray)('-'.repeat(70)) + '\n');
|
|
150
|
+
return 0;
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
process.stderr.write(`Failed to read audit log: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
154
|
+
return 1;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/commands/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,EACL,sBAAsB,IAAI,4BAA4B,EAKvD,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA0DD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,EACL,sBAAsB,IAAI,4BAA4B,EAKvD,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA0DD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAwOhE;AAmQD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qCAA+B,CAAC"}
|
package/dist/commands/init.js
CHANGED
|
@@ -219,22 +219,58 @@ async function init(options) {
|
|
|
219
219
|
if (driftFindings.length > 0) {
|
|
220
220
|
process.stdout.write((0, colors_js_1.yellow)((0, colors_js_1.bold)(' Scope Drift Detected')) + '\n');
|
|
221
221
|
process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
|
|
222
|
+
// Group by drift type and show once per type with count
|
|
223
|
+
const driftByType = new Map();
|
|
222
224
|
for (const d of driftFindings) {
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
225
|
+
const existing = driftByType.get(d.findingId) ?? [];
|
|
226
|
+
existing.push(d);
|
|
227
|
+
driftByType.set(d.findingId, existing);
|
|
228
|
+
}
|
|
229
|
+
for (const [findingId, items] of driftByType) {
|
|
230
|
+
const first = items[0];
|
|
231
|
+
const relPath = path.relative(targetDir, first.filePath);
|
|
232
|
+
const extra = items.length > 1 ? ` (+${items.length - 1} more)` : '';
|
|
233
|
+
if (findingId === 'DRIFT-001') {
|
|
234
|
+
process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} Google Maps key may access Gemini AI (${items.length} location${items.length === 1 ? '' : 's'})\n`);
|
|
235
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
|
|
236
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Keys provisioned for Maps silently authenticate to Gemini if the')}\n`);
|
|
237
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Generative Language API is enabled in the same GCP project.')}\n`);
|
|
238
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
|
|
239
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' (runs live Gemini API access check, no changes made)')}\n`);
|
|
240
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
|
|
241
|
+
}
|
|
242
|
+
else if (findingId === 'DRIFT-002') {
|
|
243
|
+
process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} AWS key may access Bedrock AI (${items.length} location${items.length === 1 ? '' : 's'})\n`);
|
|
244
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
|
|
245
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' IAM policies frequently over-provision. A key scoped for S3/EC2')}\n`);
|
|
246
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' may also pass STS auth and call Bedrock LLM endpoints.')}\n`);
|
|
247
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
|
|
248
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' (runs live STS + Bedrock access check, no changes made)')}\n`);
|
|
249
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} Credential scope drift (${items.length} location${items.length === 1 ? '' : 's'})\n`);
|
|
253
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
|
|
254
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
|
|
255
|
+
process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
|
|
256
|
+
}
|
|
257
|
+
process.stdout.write('\n');
|
|
227
258
|
}
|
|
228
|
-
process.stdout.write('\n');
|
|
229
|
-
process.stdout.write((0, colors_js_1.dim)(' Scope drift: keys provisioned for one service silently') + '\n');
|
|
230
|
-
process.stdout.write((0, colors_js_1.dim)(' gain access to AI services, expanding attack surface.') + '\n');
|
|
231
|
-
process.stdout.write((0, colors_js_1.dim)(' Run: opena2a protect') + '\n');
|
|
232
|
-
process.stdout.write('\n');
|
|
233
259
|
}
|
|
234
260
|
// Show advisory warnings after main report
|
|
235
261
|
if (advisoryCheck.advisories.length > 0) {
|
|
236
262
|
(0, advisories_js_1.printAdvisoryWarnings)(advisoryCheck);
|
|
237
263
|
}
|
|
264
|
+
// Contextual tip
|
|
265
|
+
const tip = getContextualTip(report);
|
|
266
|
+
process.stdout.write((0, colors_js_1.dim)(` Tip: ${tip.command}`) + '\n');
|
|
267
|
+
const wrappedTipText = (0, format_js_1.wordWrap)(tip.text, 68, 7);
|
|
268
|
+
process.stdout.write((0, colors_js_1.dim)(wrappedTipText) + '\n');
|
|
269
|
+
process.stdout.write('\n');
|
|
270
|
+
// OpenA2A footer
|
|
271
|
+
process.stdout.write((0, colors_js_1.cyan)(' OpenA2A -- open-source security for AI agents') + '\n');
|
|
272
|
+
process.stdout.write((0, colors_js_1.cyan)(' opena2a.org | github.com/opena2a-org') + '\n');
|
|
273
|
+
process.stdout.write('\n');
|
|
238
274
|
}
|
|
239
275
|
const hasCritical = nextSteps.some(s => s.severity === 'critical');
|
|
240
276
|
return hasCritical ? 1 : 0;
|
|
@@ -697,55 +733,71 @@ function getToolRecommendation(findingId) {
|
|
|
697
733
|
return null;
|
|
698
734
|
}
|
|
699
735
|
function getContextualTip(report) {
|
|
700
|
-
const
|
|
701
|
-
|
|
736
|
+
const credCount = report.credentialFindings;
|
|
737
|
+
const criticalCount = report.credentialsBySeverity['critical'] ?? 0;
|
|
738
|
+
const driftFindings = report.findings.filter(f => f.findingId.startsWith('DRIFT-'));
|
|
739
|
+
const hasDrift = driftFindings.length > 0;
|
|
740
|
+
const hasAwsDrift = report.findings.some(f => f.findingId === 'DRIFT-002');
|
|
741
|
+
const hasGcpDrift = report.findings.some(f => f.findingId === 'DRIFT-001');
|
|
742
|
+
if (credCount > 0) {
|
|
743
|
+
if (hasDrift && hasAwsDrift) {
|
|
744
|
+
return {
|
|
745
|
+
text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files, including AWS keys with potential Bedrock access. opena2a protect moves them to Secretless AI (encrypted local vault) and runs a live STS + Bedrock check to confirm actual exposure.`,
|
|
746
|
+
command: 'opena2a protect',
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
if (hasDrift && hasGcpDrift) {
|
|
750
|
+
return {
|
|
751
|
+
text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files, including Google keys with potential Gemini access. opena2a protect moves them to Secretless AI (encrypted local vault) and verifies live Generative Language API access.`,
|
|
752
|
+
command: 'opena2a protect',
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
if (criticalCount > 0) {
|
|
756
|
+
return {
|
|
757
|
+
text: `${criticalCount} critical credential${criticalCount === 1 ? '' : 's'} in source files — anyone with repo access can use them now. opena2a protect moves them to Secretless AI (encrypted local vault) and rewrites the source files to reference env vars.`,
|
|
758
|
+
command: 'opena2a protect',
|
|
759
|
+
};
|
|
760
|
+
}
|
|
702
761
|
return {
|
|
703
|
-
text: '
|
|
762
|
+
text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files. opena2a protect moves them to Secretless AI, rewrites the source to use env var references, and updates .gitignore.`,
|
|
704
763
|
command: 'opena2a protect',
|
|
705
764
|
};
|
|
706
765
|
}
|
|
707
766
|
const hasMcpCred = report.findings.some(f => f.findingId === 'MCP-CRED');
|
|
708
767
|
if (hasMcpCred) {
|
|
709
768
|
return {
|
|
710
|
-
text: '
|
|
769
|
+
text: 'Credentials in MCP config files are read by every AI tool that loads the config. opena2a protect moves them to Secretless AI and injects them as env vars at runtime — no more plaintext in config files.',
|
|
711
770
|
command: 'opena2a protect',
|
|
712
771
|
};
|
|
713
772
|
}
|
|
714
773
|
const hasAiConfig = report.findings.some(f => f.findingId === 'AI-CONFIG');
|
|
715
774
|
if (hasAiConfig) {
|
|
716
775
|
return {
|
|
717
|
-
text: '
|
|
776
|
+
text: 'AI tool config files (Claude, Cursor, Copilot) have fixable issues. opena2a protect applies all auto-fixable changes in one pass and signs the files so Guard can detect future unauthorized changes.',
|
|
718
777
|
command: 'opena2a protect',
|
|
719
778
|
};
|
|
720
779
|
}
|
|
721
780
|
const hasLLM = report.findings.some(f => f.findingId === 'ENV-LLM');
|
|
722
781
|
if (hasLLM) {
|
|
723
782
|
return {
|
|
724
|
-
text: '
|
|
783
|
+
text: 'An unauthenticated LLM server is running locally. opena2a shield status shows which Shield modules are active and what ARP is monitoring at the process and network level.',
|
|
725
784
|
command: 'opena2a shield status',
|
|
726
785
|
};
|
|
727
786
|
}
|
|
728
|
-
const hasEnv = report.findings.some(f => f.findingId === 'ENV-DOTENV');
|
|
729
|
-
if (hasEnv) {
|
|
730
|
-
return {
|
|
731
|
-
text: 'Fix all auto-fixable findings',
|
|
732
|
-
command: 'opena2a protect',
|
|
733
|
-
};
|
|
734
|
-
}
|
|
735
787
|
if (report.securityScore >= 90) {
|
|
736
788
|
return {
|
|
737
|
-
text: 'Strong baseline.
|
|
738
|
-
command: '
|
|
789
|
+
text: 'Strong baseline. HackMyAgent runs 147 checks including agent-layer attacks, MCP exploitation, and OASB-1 + OASB-2 compliance scoring.',
|
|
790
|
+
command: 'npx hackmyagent secure',
|
|
739
791
|
};
|
|
740
792
|
}
|
|
741
793
|
if (report.securityScore >= 70) {
|
|
742
794
|
return {
|
|
743
|
-
text: 'Good posture.
|
|
795
|
+
text: 'Good posture. opena2a guard sign creates signed baselines for your config files — Guard will alert if anything changes without a new signature.',
|
|
744
796
|
command: 'opena2a guard sign',
|
|
745
797
|
};
|
|
746
798
|
}
|
|
747
799
|
return {
|
|
748
|
-
text: '
|
|
800
|
+
text: 'opena2a shield status shows all active protections: ARP runtime monitoring, Guard config integrity, Secretless credential management, and HackMyAgent scan coverage.',
|
|
749
801
|
command: 'opena2a shield status',
|
|
750
802
|
};
|
|
751
803
|
}
|
|
@@ -783,13 +835,18 @@ function printReport(report, elapsed, verbose) {
|
|
|
783
835
|
if (report.findings.length > 0) {
|
|
784
836
|
process.stdout.write((0, colors_js_1.bold)(' Findings') + '\n');
|
|
785
837
|
process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
|
|
786
|
-
|
|
787
|
-
const
|
|
838
|
+
// Always show all critical + high; truncate medium/low at 2 (unless verbose)
|
|
839
|
+
const important = report.findings.filter(f => f.severity === 'critical' || f.severity === 'high');
|
|
840
|
+
const minor = report.findings.filter(f => f.severity !== 'critical' && f.severity !== 'high');
|
|
841
|
+
const maxMinor = verbose ? minor.length : 2;
|
|
842
|
+
const displayFindings = [...important, ...minor.slice(0, maxMinor)];
|
|
843
|
+
const hiddenCount = verbose ? 0 : minor.length - maxMinor;
|
|
788
844
|
for (const finding of displayFindings) {
|
|
789
|
-
const
|
|
790
|
-
: finding.severity === 'high' ?
|
|
791
|
-
: finding.severity === 'medium' ?
|
|
792
|
-
:
|
|
845
|
+
const sevPad = finding.severity === 'critical' ? ''
|
|
846
|
+
: finding.severity === 'high' ? ' '
|
|
847
|
+
: finding.severity === 'medium' ? ' '
|
|
848
|
+
: ' ';
|
|
849
|
+
const sevTag = (0, format_js_1.severityColor)(finding.severity)(finding.severity.toUpperCase()) + sevPad;
|
|
793
850
|
const countPrefix = finding.count > 1 ? `${finding.count} ` : '';
|
|
794
851
|
process.stdout.write(` ${sevTag} ${countPrefix}${(0, colors_js_1.bold)(finding.title)}\n`);
|
|
795
852
|
if (finding.explanation) {
|
|
@@ -821,9 +878,8 @@ function printReport(report, elapsed, verbose) {
|
|
|
821
878
|
}
|
|
822
879
|
process.stdout.write('\n');
|
|
823
880
|
}
|
|
824
|
-
if (
|
|
825
|
-
|
|
826
|
-
process.stdout.write((0, colors_js_1.dim)(` [+${remaining} more finding${remaining === 1 ? '' : 's'} -- run with --verbose to see all]`) + '\n');
|
|
881
|
+
if (hiddenCount > 0) {
|
|
882
|
+
process.stdout.write((0, colors_js_1.dim)(` [+${hiddenCount} lower-severity finding${hiddenCount === 1 ? '' : 's'} -- run with --verbose to see all]`) + '\n');
|
|
827
883
|
process.stdout.write('\n');
|
|
828
884
|
}
|
|
829
885
|
}
|
|
@@ -877,9 +933,5 @@ function printReport(report, elapsed, verbose) {
|
|
|
877
933
|
process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
|
|
878
934
|
}
|
|
879
935
|
process.stdout.write('\n');
|
|
880
|
-
// Contextual tip
|
|
881
|
-
const tip = getContextualTip(report);
|
|
882
|
-
process.stdout.write((0, colors_js_1.dim)(` Tip: ${tip.command} -- ${tip.text}`) + '\n');
|
|
883
|
-
process.stdout.write('\n');
|
|
884
936
|
}
|
|
885
937
|
//# sourceMappingURL=init.js.map
|