@ch4p/cli 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-6WIHK7NM.js +767 -0
- package/dist/agent-ANIZYPPF.js +767 -0
- package/dist/agent-HSAJ5EBN.js +761 -0
- package/dist/agent-N2P2SXGG.js +767 -0
- package/dist/audit-HLOQBMBT.js +12 -0
- package/dist/audit-UIGPH3FK.js +12 -0
- package/dist/canvas-3VTC4XPV.js +313 -0
- package/dist/canvas-4FMNW6FZ.js +313 -0
- package/dist/canvas-HJSLG76B.js +313 -0
- package/dist/canvas-XQHVCY27.js +313 -0
- package/dist/chunk-3XAW4XHG.js +185 -0
- package/dist/chunk-4IRZQCRN.js +1832 -0
- package/dist/chunk-AORLXQHZ.js +304 -0
- package/dist/chunk-BMEBRUYL.js +6995 -0
- package/dist/chunk-G6PJSDEJ.js +4372 -0
- package/dist/chunk-IN2I6XRM.js +185 -0
- package/dist/chunk-PAJOAXLQ.js +4368 -0
- package/dist/chunk-TB4IZ7F7.js +301 -0
- package/dist/chunk-U7S375OS.js +1841 -0
- package/dist/chunk-VJATFD4D.js +7003 -0
- package/dist/dist-37TB6EWP.js +25 -0
- package/dist/dist-CIJPZC2B.js +25 -0
- package/dist/doctor-5M3ZB435.js +274 -0
- package/dist/doctor-IQ3MWQSN.js +274 -0
- package/dist/gateway-DV5OL45G.js +2164 -0
- package/dist/gateway-H4Z2EQK2.js +2165 -0
- package/dist/gateway-LUCG72YX.js +2129 -0
- package/dist/gateway-O3QNSZKF.js +2123 -0
- package/dist/gateway-OJW7RY3H.js +2094 -0
- package/dist/gateway-PBLJEK5I.js +2165 -0
- package/dist/gateway-PHPRQTZP.js +2165 -0
- package/dist/gateway-YKKJ4DZE.js +2115 -0
- package/dist/gateway-Z65DCM2Q.js +2097 -0
- package/dist/gateway-ZSXTAYPF.js +2157 -0
- package/dist/gateway-ZVLF7B4C.js +2165 -0
- package/dist/identity-RHQFPSDS.js +215 -0
- package/dist/identity-VGDDAKBY.js +215 -0
- package/dist/index.js +12 -12
- package/dist/install-6LV7B2SV.js +378 -0
- package/dist/install-NAUPXVCI.js +378 -0
- package/dist/message-PTH4CEOD.js +189 -0
- package/dist/message-QCRZIBTO.js +189 -0
- package/dist/message-TGAPVVI4.js +189 -0
- package/dist/message-YQGIARNE.js +189 -0
- package/dist/onboard-CN56V5P6.js +849 -0
- package/dist/onboard-LJFC6HXD.js +849 -0
- package/dist/pairing-ARWQYATE.js +147 -0
- package/dist/pairing-PXCJMCT2.js +147 -0
- package/dist/skills-4EELFYO2.js +138 -0
- package/dist/skills-KXRTDSF2.js +138 -0
- package/dist/status-2ZJPK3VL.js +94 -0
- package/dist/status-W2OXOSH4.js +94 -0
- package/package.json +24 -24
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadConfig
|
|
3
|
+
} from "./chunk-AORLXQHZ.js";
|
|
4
|
+
import {
|
|
5
|
+
BOLD,
|
|
6
|
+
DIM,
|
|
7
|
+
GREEN,
|
|
8
|
+
RED,
|
|
9
|
+
RESET,
|
|
10
|
+
TEAL,
|
|
11
|
+
YELLOW,
|
|
12
|
+
box
|
|
13
|
+
} from "./chunk-NMGPBPNU.js";
|
|
14
|
+
|
|
15
|
+
// src/commands/audit.ts
|
|
16
|
+
function severityIcon(severity) {
|
|
17
|
+
switch (severity) {
|
|
18
|
+
case "pass":
|
|
19
|
+
return `${GREEN}PASS${RESET}`;
|
|
20
|
+
case "warn":
|
|
21
|
+
return `${YELLOW}WARN${RESET}`;
|
|
22
|
+
case "fail":
|
|
23
|
+
return `${RED}FAIL${RESET}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function severityPrefix(severity) {
|
|
27
|
+
switch (severity) {
|
|
28
|
+
case "pass":
|
|
29
|
+
return `${GREEN}+${RESET}`;
|
|
30
|
+
case "warn":
|
|
31
|
+
return `${YELLOW}~${RESET}`;
|
|
32
|
+
case "fail":
|
|
33
|
+
return `${RED}x${RESET}`;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function performAudit(config) {
|
|
37
|
+
const results = [];
|
|
38
|
+
let id = 0;
|
|
39
|
+
id++;
|
|
40
|
+
const port = config.gateway?.port ?? 18789;
|
|
41
|
+
const allowPublic = config.gateway?.allowPublicBind ?? false;
|
|
42
|
+
results.push({
|
|
43
|
+
id,
|
|
44
|
+
name: "Gateway binding",
|
|
45
|
+
severity: allowPublic ? "fail" : "pass",
|
|
46
|
+
message: allowPublic ? `Gateway allows public binding (0.0.0.0:${port}). Restrict to loopback.` : `Gateway bound to loopback (127.0.0.1:${port})`
|
|
47
|
+
});
|
|
48
|
+
id++;
|
|
49
|
+
const requirePairing = config.gateway?.requirePairing ?? true;
|
|
50
|
+
results.push({
|
|
51
|
+
id,
|
|
52
|
+
name: "Pairing required",
|
|
53
|
+
severity: requirePairing ? "pass" : "warn",
|
|
54
|
+
message: requirePairing ? "Gateway requires pairing for all connections" : "Pairing is disabled. Any local process can connect."
|
|
55
|
+
});
|
|
56
|
+
id++;
|
|
57
|
+
const workspaceOnly = config.security?.workspaceOnly ?? true;
|
|
58
|
+
results.push({
|
|
59
|
+
id,
|
|
60
|
+
name: "Workspace scoping",
|
|
61
|
+
severity: workspaceOnly ? "pass" : "warn",
|
|
62
|
+
message: workspaceOnly ? "Filesystem access restricted to workspace" : "Workspace scoping disabled. Agent can access files outside workspace."
|
|
63
|
+
});
|
|
64
|
+
id++;
|
|
65
|
+
const blockedPaths = config.security?.blockedPaths ?? [];
|
|
66
|
+
results.push({
|
|
67
|
+
id,
|
|
68
|
+
name: "Blocked paths",
|
|
69
|
+
severity: "pass",
|
|
70
|
+
message: blockedPaths.length > 0 ? `${blockedPaths.length} additional blocked path(s) configured` : "Using default system blocked paths (14 dirs + 4 dotfiles)"
|
|
71
|
+
});
|
|
72
|
+
id++;
|
|
73
|
+
const autonomy = config.autonomy?.level ?? "supervised";
|
|
74
|
+
results.push({
|
|
75
|
+
id,
|
|
76
|
+
name: "Autonomy level",
|
|
77
|
+
severity: autonomy === "full" ? "warn" : "pass",
|
|
78
|
+
message: autonomy === "full" ? "Full autonomy enabled. Agent will not ask for confirmation." : `Autonomy level: ${autonomy}`
|
|
79
|
+
});
|
|
80
|
+
id++;
|
|
81
|
+
const allowedCommands = config.autonomy?.allowedCommands ?? [];
|
|
82
|
+
results.push({
|
|
83
|
+
id,
|
|
84
|
+
name: "Command allowlist",
|
|
85
|
+
severity: allowedCommands.length > 0 ? "pass" : "warn",
|
|
86
|
+
message: allowedCommands.length > 0 ? `${allowedCommands.length} command(s) in allowlist` : "No command allowlist configured. All commands may be executed."
|
|
87
|
+
});
|
|
88
|
+
id++;
|
|
89
|
+
const encryptSecrets = config.secrets?.encrypt ?? true;
|
|
90
|
+
results.push({
|
|
91
|
+
id,
|
|
92
|
+
name: "Secrets encryption",
|
|
93
|
+
severity: encryptSecrets ? "pass" : "fail",
|
|
94
|
+
message: encryptSecrets ? "Secrets are encrypted at rest (AES-256-GCM)" : "Secrets encryption is disabled. Credentials stored in plaintext."
|
|
95
|
+
});
|
|
96
|
+
id++;
|
|
97
|
+
const engineDefault = config.engines?.default ?? "native";
|
|
98
|
+
const usesSubprocessEngine = engineDefault === "claude-cli" || engineDefault === "codex-cli";
|
|
99
|
+
const usesOllama = config.agent?.provider === "ollama";
|
|
100
|
+
if (usesSubprocessEngine) {
|
|
101
|
+
results.push({
|
|
102
|
+
id,
|
|
103
|
+
name: "API keys",
|
|
104
|
+
severity: "pass",
|
|
105
|
+
message: `Using ${engineDefault} engine. Auth handled by CLI tool.`
|
|
106
|
+
});
|
|
107
|
+
} else if (usesOllama) {
|
|
108
|
+
results.push({
|
|
109
|
+
id,
|
|
110
|
+
name: "API keys",
|
|
111
|
+
severity: "pass",
|
|
112
|
+
message: "Using Ollama provider. No API key required (local inference)."
|
|
113
|
+
});
|
|
114
|
+
} else {
|
|
115
|
+
const anthropicKey = config.providers?.["anthropic"]?.["apiKey"];
|
|
116
|
+
const openaiKey = config.providers?.["openai"]?.["apiKey"];
|
|
117
|
+
const hasAnthropicKey = typeof anthropicKey === "string" && anthropicKey.length > 0 && !anthropicKey.includes("${");
|
|
118
|
+
const hasOpenaiKey = typeof openaiKey === "string" && openaiKey.length > 0 && !openaiKey.includes("${");
|
|
119
|
+
const hasAnyKey = hasAnthropicKey || hasOpenaiKey;
|
|
120
|
+
results.push({
|
|
121
|
+
id,
|
|
122
|
+
name: "API keys",
|
|
123
|
+
severity: hasAnyKey ? "pass" : "warn",
|
|
124
|
+
message: hasAnyKey ? `API key(s) configured: ${[hasAnthropicKey && "Anthropic", hasOpenaiKey && "OpenAI"].filter(Boolean).join(", ")}` : "No API keys configured. Set keys via onboard or environment variables."
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
id++;
|
|
128
|
+
const tunnelProvider = config.tunnel?.provider ?? "none";
|
|
129
|
+
results.push({
|
|
130
|
+
id,
|
|
131
|
+
name: "Tunnel exposure",
|
|
132
|
+
severity: tunnelProvider === "none" ? "pass" : "warn",
|
|
133
|
+
message: tunnelProvider === "none" ? "No tunnel configured. Gateway is local only." : `Tunnel active via ${tunnelProvider}. Gateway is exposed to the internet.`
|
|
134
|
+
});
|
|
135
|
+
id++;
|
|
136
|
+
const observers = config.observability?.observers ?? [];
|
|
137
|
+
results.push({
|
|
138
|
+
id,
|
|
139
|
+
name: "Observability",
|
|
140
|
+
severity: observers.length > 0 ? "pass" : "warn",
|
|
141
|
+
message: observers.length > 0 ? `Observer(s) active: ${observers.join(", ")}` : "No observers configured. Security events may go unlogged."
|
|
142
|
+
});
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
function runAudit(config) {
|
|
146
|
+
const results = performAudit(config);
|
|
147
|
+
const lines = [];
|
|
148
|
+
for (const r of results) {
|
|
149
|
+
const padId = String(r.id).padStart(2, " ");
|
|
150
|
+
lines.push(`${severityPrefix(r.severity)} ${DIM}${padId}.${RESET} ${r.message}`);
|
|
151
|
+
}
|
|
152
|
+
const passed = results.filter((r) => r.severity === "pass").length;
|
|
153
|
+
const warned = results.filter((r) => r.severity === "warn").length;
|
|
154
|
+
const failed = results.filter((r) => r.severity === "fail").length;
|
|
155
|
+
lines.push("");
|
|
156
|
+
lines.push(
|
|
157
|
+
`${severityIcon("pass")} ${passed} ${severityIcon("warn")} ${warned} ${severityIcon("fail")} ${failed} ${DIM}(${results.length} checks)${RESET}`
|
|
158
|
+
);
|
|
159
|
+
if (failed > 0) {
|
|
160
|
+
lines.push("");
|
|
161
|
+
lines.push(`${RED}${BOLD}Action required:${RESET} ${failed} check(s) failed. Review your config.`);
|
|
162
|
+
}
|
|
163
|
+
console.log(box("ch4p Security Audit", lines));
|
|
164
|
+
}
|
|
165
|
+
async function audit() {
|
|
166
|
+
try {
|
|
167
|
+
const config = loadConfig();
|
|
168
|
+
console.log("");
|
|
169
|
+
runAudit(config);
|
|
170
|
+
console.log("");
|
|
171
|
+
} catch (err) {
|
|
172
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
173
|
+
console.error(`
|
|
174
|
+
${RED}Failed to load config:${RESET} ${message}`);
|
|
175
|
+
console.error(` ${DIM}Run ${TEAL}ch4p onboard${DIM} to create a config file.${RESET}
|
|
176
|
+
`);
|
|
177
|
+
process.exitCode = 1;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export {
|
|
182
|
+
performAudit,
|
|
183
|
+
runAudit,
|
|
184
|
+
audit
|
|
185
|
+
};
|