clawarmor 1.1.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/LICENSE +21 -0
- package/README.md +163 -0
- package/SECURITY.md +40 -0
- package/SKILL.md +87 -0
- package/cli.js +155 -0
- package/lib/audit.js +257 -0
- package/lib/checks/allowfrom.js +104 -0
- package/lib/checks/auth.js +63 -0
- package/lib/checks/channels.js +69 -0
- package/lib/checks/filesystem.js +87 -0
- package/lib/checks/gateway.js +177 -0
- package/lib/checks/hooks.js +33 -0
- package/lib/checks/tools.js +75 -0
- package/lib/checks/version.js +61 -0
- package/lib/compare.js +96 -0
- package/lib/config.js +48 -0
- package/lib/discovery.js +92 -0
- package/lib/fix.js +175 -0
- package/lib/output/colors.js +24 -0
- package/lib/output/formatter.js +212 -0
- package/lib/output/progress.js +27 -0
- package/lib/probes/gateway-probe.js +260 -0
- package/lib/scan.js +129 -0
- package/lib/scanner/file-scanner.js +69 -0
- package/lib/scanner/patterns.js +74 -0
- package/lib/scanner/skill-finder.js +58 -0
- package/lib/scanner/skill-md-scanner.js +121 -0
- package/lib/trend.js +180 -0
- package/lib/verify.js +149 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pinzas AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# 🛡 ClawArmor
|
|
4
|
+
|
|
5
|
+
**The security auditor for OpenClaw agents.**
|
|
6
|
+
|
|
7
|
+
Checks your config. Probes your live gateway. Scans your skills.
|
|
8
|
+
Runs in 30 seconds. Finds what config-only tools miss. Free forever.
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/clawarmor)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](package.json)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g clawarmor && clawarmor audit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
ℹ Reads: ~/.openclaw/openclaw.json + file permissions only
|
|
24
|
+
Network: registry.npmjs.org (version check) + 127.0.0.1:18789 (live probes)
|
|
25
|
+
Sends nothing. Source: github.com/pinzasai/clawarmor
|
|
26
|
+
|
|
27
|
+
── LIVE GATEWAY PROBES (connecting to 127.0.0.1) ──
|
|
28
|
+
✓ Gateway running on port 18789
|
|
29
|
+
✓ Not reachable on network interfaces (probed live)
|
|
30
|
+
✓ Authentication required (WebSocket probe confirmed)
|
|
31
|
+
✓ /health endpoint does not leak sensitive data
|
|
32
|
+
✓ CORS not open to arbitrary origins
|
|
33
|
+
|
|
34
|
+
Security Score: 100/100 ┃ Grade: A
|
|
35
|
+
████████████████████ 100%
|
|
36
|
+
|
|
37
|
+
Verdict: Your instance is secure. No issues found.
|
|
38
|
+
|
|
39
|
+
── PASSED (30 checks) ──────────────────────────────
|
|
40
|
+
✓ Gateway bound to loopback only
|
|
41
|
+
✓ Auth token is strong
|
|
42
|
+
✓ Agent sandbox mode: "non-main" (sessions isolated)
|
|
43
|
+
✓ Browser SSRF to private networks blocked
|
|
44
|
+
✓ All channel allowFrom settings are restricted
|
|
45
|
+
... 25 more
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Why ClawArmor
|
|
51
|
+
|
|
52
|
+
Every other OpenClaw security tool reads your config file and tells you if things look right on paper.
|
|
53
|
+
|
|
54
|
+
**ClawArmor also connects locally to your running gateway and verifies live behavior.**
|
|
55
|
+
|
|
56
|
+
Config says `bind: loopback`. Is your gateway *actually* unreachable on LAN? Config says auth is enabled. Does the live WebSocket endpoint *actually* reject unauthenticated connections? A misconfigured nginx in front can make your config lie. Live probes can't be faked.
|
|
57
|
+
|
|
58
|
+
> All probes connect from your machine to `127.0.0.1` (and your local network interfaces). Nothing leaves your machine.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Five commands
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
clawarmor audit # 30 checks + 5 live gateway probes. Score 0-100. Plain-English verdict.
|
|
66
|
+
clawarmor scan # Scan every skill file (.js .sh .py .ts SKILL.md) for malicious code.
|
|
67
|
+
clawarmor fix # Auto-apply safe fixes. --dry-run to preview, --apply to execute.
|
|
68
|
+
clawarmor verify # Re-run only previously-failed checks. Exit 0 if all fixed (CI-friendly).
|
|
69
|
+
clawarmor trend # ASCII chart of your security score over time.
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## What it checks
|
|
75
|
+
|
|
76
|
+
### Live gateway probes (behavioral — not just config reads)
|
|
77
|
+
|
|
78
|
+
| Probe | What it checks |
|
|
79
|
+
|---|---|
|
|
80
|
+
| Port reachability | TCP-connects to gateway on every non-loopback interface |
|
|
81
|
+
| Auth enforcement | WebSocket handshake without token — does server reject it? |
|
|
82
|
+
| Health endpoint | GET /health — does response contain config data or secrets? |
|
|
83
|
+
| CORS headers | OPTIONS with `Origin: https://evil.example.com` |
|
|
84
|
+
|
|
85
|
+
These probes are **read-only and non-destructive**. They observe — they don't modify anything.
|
|
86
|
+
|
|
87
|
+
### Config audit (30 checks)
|
|
88
|
+
|
|
89
|
+
Gateway bind · auth mode · token strength · dangerous flags · mDNS exposure · real-IP fallback · trusted proxy config · file permissions (`~/.openclaw/`, `openclaw.json`, `agent-accounts.json`, `credentials/`) · channel allowFrom policies · wildcard detection · group policies · elevated tools · exec sandbox · tool restrictions (filesystem scope, apply_patch scope) · browser SSRF policy · plugin allowlist · log redaction · version currency · webhook security · multi-user trust model
|
|
90
|
+
|
|
91
|
+
### Skill supply chain scan
|
|
92
|
+
|
|
93
|
+
Scans **all files** in every installed skill — `.js`, `.ts`, `.sh`, `.py`, `.rb` and `SKILL.md`. Not just markdown.
|
|
94
|
+
|
|
95
|
+
**Code patterns:** `eval()`, `new Function()`, `child_process`, credential file reads, pipe-to-shell, known exfil domains, large base64 blobs, dynamic `require()`
|
|
96
|
+
|
|
97
|
+
**SKILL.md instruction patterns:** credential read instructions, system prompt overrides, exfiltration instructions, deception instructions, hardcoded IP fetches
|
|
98
|
+
|
|
99
|
+
> **Honest limitation:** The scanner catches unsophisticated threats and common patterns. Obfuscated code (string concatenation, encoded payloads) can bypass static analysis. Treat a clean scan as a good signal, not a guarantee.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## What it protects against
|
|
104
|
+
|
|
105
|
+
| Threat | Covered | Notes |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| T-ACCESS-003: Token/config exposure | ✅ | File permission checks + config hardening |
|
|
108
|
+
| T-PERSIST-001: Malicious skill supply chain | ✅ | All skill files scanned, not just SKILL.md |
|
|
109
|
+
| T-EXEC-001/002: Prompt injection | ❌ | Runtime policy layer — use [SupraWall](https://suprawall.io) |
|
|
110
|
+
| T-EXFIL-001: Data exfiltration | ❌ | Runtime policy layer — use SupraWall |
|
|
111
|
+
|
|
112
|
+
ClawArmor hardens your configuration and detects supply chain threats. It does not provide runtime policy enforcement — that's a different layer.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Auto-fix
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
clawarmor fix --dry-run # preview what would change
|
|
120
|
+
clawarmor fix --apply # apply safe one-liner fixes + gateway restart instructions
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Sandbox isolation is enabled safely: if Docker is installed, `fix --apply` sets `sandbox.mode=non-main` + `workspaceAccess=rw` so your Telegram/group sessions keep workspace access.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## CI integration
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# Fail CI if security score drops
|
|
131
|
+
clawarmor verify # exit 0 = all previously-failed checks now pass
|
|
132
|
+
# exit 1 = still failing
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Score history persists in `~/.clawarmor/history.json`.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Privacy & security
|
|
140
|
+
|
|
141
|
+
- `audit`, `scan`, `fix`, `verify`, `trend` run **entirely locally**
|
|
142
|
+
- One optional network call: `registry.npmjs.org` for version check (skippable with `--offline`)
|
|
143
|
+
- Every run prints exactly what files it reads and what network calls it makes before executing
|
|
144
|
+
- Nothing is sent anywhere
|
|
145
|
+
|
|
146
|
+
**Found a vulnerability in ClawArmor itself?** Please email `pinzasrojas@proton.me` before public disclosure.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Installation
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
npm install -g clawarmor # requires Node.js 18+
|
|
154
|
+
clawarmor audit
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Zero runtime npm dependencies. Node.js built-ins only (`net`, `http`, `os`, `fs`, `crypto`).
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## License
|
|
162
|
+
|
|
163
|
+
MIT — see [LICENSE](LICENSE)
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Security Policy & Ethics Statement
|
|
2
|
+
|
|
3
|
+
## What ClawArmor scans
|
|
4
|
+
|
|
5
|
+
**`clawarmor audit`** reads a single file: `~/.openclaw/openclaw.json`. It checks configuration values — bind address, auth mode, file permissions, channel policies. It never reads credentials or sends any data over the network.
|
|
6
|
+
|
|
7
|
+
**`clawarmor scan`** reads source files in installed skill directories. It runs regex patterns against file content to detect suspicious code. It does not execute any skill code. It never sends file contents anywhere.
|
|
8
|
+
|
|
9
|
+
**`clawarmor monitor`** is a planned future command. Details TBD.
|
|
10
|
+
|
|
11
|
+
## What ClawArmor never does
|
|
12
|
+
|
|
13
|
+
- Sends your config, credentials, or file contents to any server
|
|
14
|
+
- Stores anything on disk beyond what you explicitly configure
|
|
15
|
+
- Executes skill code during scanning
|
|
16
|
+
- Makes outbound network calls during `audit` or `scan` (except: `clawarmor audit` fetches the latest OpenClaw version from the npm registry to check if you're up to date — this is a GET request with no identifying information)
|
|
17
|
+
- Shares scan results with third parties
|
|
18
|
+
|
|
19
|
+
## Responsible disclosure
|
|
20
|
+
|
|
21
|
+
ClawArmor is built on research into exposed OpenClaw instances. We follow responsible disclosure principles:
|
|
22
|
+
|
|
23
|
+
1. We notify owners before publishing any findings about their specific instances
|
|
24
|
+
2. We do not exploit vulnerabilities we discover — we report them
|
|
25
|
+
3. We do not store or log the content of notifications sent to exposed instances
|
|
26
|
+
4. We maintain a public transparency log of notifications sent (IP + timestamp + message hash, no content)
|
|
27
|
+
|
|
28
|
+
## Reporting vulnerabilities in ClawArmor
|
|
29
|
+
|
|
30
|
+
If you find a security vulnerability in ClawArmor itself, please email **pinzasrojas@proton.me** before public disclosure. We commit to:
|
|
31
|
+
|
|
32
|
+
- Acknowledging your report within 48 hours
|
|
33
|
+
- Providing a fix or mitigation within 14 days for critical issues
|
|
34
|
+
- Crediting you in the release notes (if desired)
|
|
35
|
+
|
|
36
|
+
## False positives
|
|
37
|
+
|
|
38
|
+
ClawArmor's `scan` command uses static pattern matching. Some findings — particularly in built-in skills — are legitimate uses of flagged patterns (e.g., `spawnSync` in a TTS binary wrapper). Always review findings in context before taking action.
|
|
39
|
+
|
|
40
|
+
If you believe a pattern produces excessive false positives, please open an issue at github.com/pinzasai/clawarmor.
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# ClawArmor
|
|
2
|
+
|
|
3
|
+
Security armor for your OpenClaw agent. Audits your config, probes your live gateway, and scans installed skills for threats.
|
|
4
|
+
|
|
5
|
+
## When to use this skill
|
|
6
|
+
|
|
7
|
+
Call `clawarmor` when you want to:
|
|
8
|
+
- Check if your OpenClaw instance is securely configured
|
|
9
|
+
- Verify your live gateway actually requires authentication (not just config)
|
|
10
|
+
- Scan installed skills for malicious code or dangerous instructions
|
|
11
|
+
- Auto-fix common misconfigurations
|
|
12
|
+
- Track your security score over time
|
|
13
|
+
|
|
14
|
+
## Commands
|
|
15
|
+
|
|
16
|
+
### Audit (most important — run this first)
|
|
17
|
+
```
|
|
18
|
+
Run: clawarmor audit
|
|
19
|
+
```
|
|
20
|
+
Performs 32 security checks including live behavioral probes of the running gateway. Returns a 0-100 score, letter grade, plain-English verdict, and specific findings with fix commands.
|
|
21
|
+
|
|
22
|
+
### Scan installed skills
|
|
23
|
+
```
|
|
24
|
+
Run: clawarmor scan
|
|
25
|
+
```
|
|
26
|
+
Scans all installed skill files (.js, .sh, .py, .ts, SKILL.md) for malicious patterns: credential theft, RCE, exfiltration, prompt injection.
|
|
27
|
+
|
|
28
|
+
### Auto-fix safe issues
|
|
29
|
+
```
|
|
30
|
+
Run: clawarmor fix --dry-run # preview what would change
|
|
31
|
+
Run: clawarmor fix --apply # apply safe one-liner fixes
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Verify fixes worked
|
|
35
|
+
```
|
|
36
|
+
Run: clawarmor verify
|
|
37
|
+
```
|
|
38
|
+
Re-runs only previously-failed checks. Exits 0 if all now pass.
|
|
39
|
+
|
|
40
|
+
### Track score over time
|
|
41
|
+
```
|
|
42
|
+
Run: clawarmor trend
|
|
43
|
+
```
|
|
44
|
+
Shows ASCII chart of score history across all previous audits.
|
|
45
|
+
|
|
46
|
+
## What it checks
|
|
47
|
+
|
|
48
|
+
**Live gateway probes** (behavioral — not just config reads):
|
|
49
|
+
- Is the gateway port actually open on non-loopback network interfaces?
|
|
50
|
+
- Does the live WebSocket endpoint reject connections without an auth token?
|
|
51
|
+
- Does the /health endpoint leak sensitive config data?
|
|
52
|
+
- Are CORS headers misconfigured to allow arbitrary origins?
|
|
53
|
+
|
|
54
|
+
**Config audit** (32 static checks):
|
|
55
|
+
- Gateway bind address, auth mode, token strength
|
|
56
|
+
- File permissions on ~/.openclaw/, openclaw.json, agent-accounts.json, credentials/
|
|
57
|
+
- Channel allowFrom policies — allowlist enforcement, wildcard detection
|
|
58
|
+
- Tool restrictions — filesystem scope, apply_patch scope, elevated tools
|
|
59
|
+
- Sandbox isolation configuration
|
|
60
|
+
- Plugin allowlist enforcement
|
|
61
|
+
- OpenClaw version currency
|
|
62
|
+
- Browser SSRF policy
|
|
63
|
+
- Webhook security
|
|
64
|
+
- mDNS exposure mode
|
|
65
|
+
- Multi-user trust model vs sandbox isolation
|
|
66
|
+
|
|
67
|
+
**Skill supply chain scan**:
|
|
68
|
+
- Malicious code patterns in .js, .sh, .py, .ts skill scripts
|
|
69
|
+
- Dangerous natural language instructions in SKILL.md files
|
|
70
|
+
- Context-aware severity: built-in skills capped at INFO, user-installed get full severity
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
npm install -g clawarmor
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Zero runtime dependencies. Node.js 18+ required. Local only — nothing sent to external servers except one version check to registry.npmjs.org.
|
|
79
|
+
|
|
80
|
+
Source and full documentation: https://github.com/pinzasai/clawarmor
|
|
81
|
+
|
|
82
|
+
## Notes
|
|
83
|
+
|
|
84
|
+
- Run `clawarmor audit` after any config change to verify your security posture
|
|
85
|
+
- The `verify` command is CI-friendly (exit codes: 0 = all fixed, 1 = still failing)
|
|
86
|
+
- Score history is stored at `~/.clawarmor/history.json`
|
|
87
|
+
- This skill does NOT replace runtime policy enforcement (see SupraWall for that)
|
package/cli.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ClawArmor v1.1.0 — Security armor for OpenClaw agents
|
|
3
|
+
|
|
4
|
+
import { paint } from './lib/output/colors.js';
|
|
5
|
+
|
|
6
|
+
const VERSION = '1.1.0';
|
|
7
|
+
const GATEWAY_PORT_DEFAULT = 18789;
|
|
8
|
+
|
|
9
|
+
function isLocalhost(host) {
|
|
10
|
+
return host === '127.0.0.1' || host === 'localhost' || host === '::1';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseUrlFlag(urlArg) {
|
|
14
|
+
// Accepts host:port or plain host (defaults to GATEWAY_PORT_DEFAULT)
|
|
15
|
+
if (!urlArg) return null;
|
|
16
|
+
const lastColon = urlArg.lastIndexOf(':');
|
|
17
|
+
if (lastColon !== -1 && lastColon !== 0) {
|
|
18
|
+
const maybePort = urlArg.slice(lastColon + 1);
|
|
19
|
+
if (/^\d+$/.test(maybePort)) {
|
|
20
|
+
return { host: urlArg.slice(0, lastColon), port: parseInt(maybePort, 10) };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return { host: urlArg, port: GATEWAY_PORT_DEFAULT };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function trustHeader(port, targetHost) {
|
|
27
|
+
const isRemote = targetHost && !isLocalhost(targetHost);
|
|
28
|
+
const probeTarget = targetHost ? `${targetHost}:${port}` : `127.0.0.1:${port}`;
|
|
29
|
+
console.log('');
|
|
30
|
+
console.log(` ${paint.dim('ℹ')} ${paint.dim('Config: local (~/.openclaw/openclaw.json)')}`);
|
|
31
|
+
console.log(` ${paint.dim('Probes: ' + probeTarget + (isRemote ? ' (remote)' : ' (local)'))}`);
|
|
32
|
+
console.log(` ${paint.dim('Sends nothing. Source: github.com/pinzasai/clawarmor')}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function usage() {
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(` ${paint.bold('ClawArmor')} ${paint.dim('v'+VERSION)} — Security armor for OpenClaw agents`);
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(` ${paint.cyan('Usage:')} clawarmor <command> [flags]`);
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log(` ${paint.bold('Commands:')}`);
|
|
42
|
+
console.log(` ${paint.cyan('audit')} Score your OpenClaw config (0-100), zero false positives`);
|
|
43
|
+
console.log(` ${paint.cyan('scan')} Scan ALL skill files for malicious code + SKILL.md instructions`);
|
|
44
|
+
console.log(` ${paint.cyan('verify')} Re-check only previously-failed items`);
|
|
45
|
+
console.log(` ${paint.cyan('trend')} Show score over last N audits (ASCII chart)`);
|
|
46
|
+
console.log(` ${paint.cyan('compare')} Compare coverage vs openclaw security audit`);
|
|
47
|
+
console.log(` ${paint.cyan('fix')} Auto-apply safe fixes (--dry-run to preview, --apply to run)`);
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log(` ${paint.dim('Flags:')}`);
|
|
50
|
+
console.log(` ${paint.dim('--url <host:port>')} Probe a specific host:port instead of 127.0.0.1`);
|
|
51
|
+
console.log(` ${paint.dim('--config <path>')} Use a specific config file instead of ~/.openclaw/openclaw.json`);
|
|
52
|
+
console.log(` ${paint.dim('--json')} Machine-readable JSON output (audit only)`);
|
|
53
|
+
console.log(` ${paint.dim('--explain-reads')} Print every file read and network call before executing`);
|
|
54
|
+
console.log('');
|
|
55
|
+
console.log(` ${paint.dim('Examples:')}`);
|
|
56
|
+
console.log(` ${paint.dim('clawarmor audit')} ${paint.dim('# local, default')}`);
|
|
57
|
+
console.log(` ${paint.dim('clawarmor audit --url 10.0.0.5:18789')} ${paint.dim('# probe LAN instance')}`);
|
|
58
|
+
console.log(` ${paint.dim('clawarmor audit --url myserver.com:18789')} ${paint.dim('# probe remote (auth warning)')}`);
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log(` ${paint.dim('github.com/pinzasai/clawarmor')}`);
|
|
61
|
+
console.log('');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const args = process.argv.slice(2);
|
|
65
|
+
const cmd = args[0];
|
|
66
|
+
|
|
67
|
+
// Parse --url flag
|
|
68
|
+
const urlIdx = args.indexOf('--url');
|
|
69
|
+
const urlArg = urlIdx !== -1 ? args[urlIdx + 1] : null;
|
|
70
|
+
const parsedUrl = parseUrlFlag(urlArg);
|
|
71
|
+
|
|
72
|
+
// Parse --config flag
|
|
73
|
+
const configIdx = args.indexOf('--config');
|
|
74
|
+
const configPathArg = configIdx !== -1 ? args[configIdx + 1] : null;
|
|
75
|
+
|
|
76
|
+
const flags = {
|
|
77
|
+
json: args.includes('--json'),
|
|
78
|
+
explainReads: args.includes('--explain-reads'),
|
|
79
|
+
targetHost: parsedUrl?.host || null,
|
|
80
|
+
targetPort: parsedUrl?.port || null,
|
|
81
|
+
configPath: configPathArg || null,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
if (!cmd || cmd === '--help' || cmd === '-h' || cmd === 'help') { usage(); process.exit(0); }
|
|
85
|
+
if (cmd === '--version' || cmd === '-v') { console.log(VERSION); process.exit(0); }
|
|
86
|
+
|
|
87
|
+
// Load config once for port info (used in trust header)
|
|
88
|
+
const { loadConfig } = await import('./lib/config.js');
|
|
89
|
+
const { config } = loadConfig(flags.configPath);
|
|
90
|
+
const gatewayPort = flags.targetPort || config?.gateway?.port || GATEWAY_PORT_DEFAULT;
|
|
91
|
+
const targetHost = flags.targetHost || null;
|
|
92
|
+
|
|
93
|
+
if (flags.explainReads) {
|
|
94
|
+
const probeTarget = targetHost ? `${targetHost}:${gatewayPort}` : `127.0.0.1:${gatewayPort}`;
|
|
95
|
+
console.log('');
|
|
96
|
+
console.log(` ${paint.cyan('--explain-reads')} — files and network calls this command will make:`);
|
|
97
|
+
console.log(` ${paint.dim('Read:')} ${flags.configPath || '~/.openclaw/openclaw.json'}`);
|
|
98
|
+
console.log(` ${paint.dim('Read:')} ~/.openclaw/agent-accounts.json (permissions only)`);
|
|
99
|
+
console.log(` ${paint.dim('Read:')} ~/.openclaw/ (directory permissions)`);
|
|
100
|
+
console.log(` ${paint.dim('Read:')} ~/.clawarmor/history.json (audit history)`);
|
|
101
|
+
if (['audit', 'verify'].includes(cmd)) {
|
|
102
|
+
console.log(` ${paint.dim('Network:')} ${probeTarget} (TCP/WebSocket/HTTP live probes — gateway only)`);
|
|
103
|
+
}
|
|
104
|
+
console.log(` ${paint.dim('Network:')} registry.npmjs.org (version check)`);
|
|
105
|
+
console.log('');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Remote host warning (printed before trust header so it's prominent)
|
|
109
|
+
if (targetHost && !isLocalhost(targetHost)) {
|
|
110
|
+
console.log('');
|
|
111
|
+
console.log(` ${paint.yellow('⚠')} ${paint.bold('Probing remote host — ensure you have authorization')}`);
|
|
112
|
+
console.log(` ${paint.dim('Target: ' + targetHost + ':' + gatewayPort)}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Print trust header before every command (except --json mode)
|
|
116
|
+
if (!flags.json) {
|
|
117
|
+
trustHeader(gatewayPort, targetHost);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (cmd === 'audit') {
|
|
121
|
+
const { runAudit } = await import('./lib/audit.js');
|
|
122
|
+
process.exit(await runAudit(flags));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (cmd === 'scan') {
|
|
126
|
+
const { runScan } = await import('./lib/scan.js');
|
|
127
|
+
process.exit(await runScan());
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (cmd === 'verify') {
|
|
131
|
+
const { runVerify } = await import('./lib/verify.js');
|
|
132
|
+
process.exit(await runVerify());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (cmd === 'trend') {
|
|
136
|
+
const idx = args.indexOf('--last');
|
|
137
|
+
const n = (idx !== -1 && args[idx+1]) ? (parseInt(args[idx+1], 10) || 10) : 10;
|
|
138
|
+
const { runTrend } = await import('./lib/trend.js');
|
|
139
|
+
process.exit(await runTrend({ n }));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (cmd === 'compare') {
|
|
143
|
+
const { runCompare } = await import('./lib/compare.js');
|
|
144
|
+
process.exit(await runCompare());
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if (cmd === 'fix') {
|
|
149
|
+
const { runFix } = await import('./lib/fix.js');
|
|
150
|
+
const fixFlags = { apply: process.argv.includes('--apply'), dryRun: process.argv.includes('--dry-run') };
|
|
151
|
+
process.exit(await runFix(fixFlags));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
console.log(` ${paint.red('✗')} Unknown command: ${paint.bold(cmd)}`);
|
|
155
|
+
usage(); process.exit(1);
|