@guardion/guardion 0.2.0 → 0.4.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 +202 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +590 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/connectors/claude-code/hooks/enforce.cjs +58 -0
- package/dist/connectors/claude-code/hooks/guardion-hook.cjs +355 -0
- package/dist/connectors/claude-code/hooks/tool-scanner.cjs +272 -0
- package/dist/connectors/claude-code/src/collect.d.ts +5 -0
- package/dist/connectors/claude-code/src/collect.d.ts.map +1 -0
- package/dist/connectors/claude-code/src/collect.js +17 -0
- package/dist/connectors/claude-code/src/collect.js.map +1 -0
- package/dist/{installer.d.ts → connectors/claude-code/src/installer.d.ts} +2 -1
- package/dist/connectors/claude-code/src/installer.d.ts.map +1 -0
- package/dist/connectors/claude-code/src/installer.js +190 -0
- package/dist/connectors/claude-code/src/installer.js.map +1 -0
- package/dist/connectors/claude-code/src/scanner.d.ts.map +1 -0
- package/dist/{scanner.js → connectors/claude-code/src/scanner.js} +1 -1
- package/dist/connectors/claude-code/src/scanner.js.map +1 -0
- package/dist/core/config.d.ts +239 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +154 -0
- package/dist/core/config.js.map +1 -0
- package/dist/{constants.d.ts → core/constants.d.ts} +8 -3
- package/dist/core/constants.d.ts.map +1 -0
- package/dist/core/constants.js +54 -0
- package/dist/core/constants.js.map +1 -0
- package/dist/core/discover.d.ts +36 -0
- package/dist/core/discover.d.ts.map +1 -0
- package/dist/core/discover.js +154 -0
- package/dist/core/discover.js.map +1 -0
- package/dist/core/fingerprint.cjs +84 -0
- package/dist/core/inventory.d.ts +35 -0
- package/dist/core/inventory.d.ts.map +1 -0
- package/dist/core/inventory.js +69 -0
- package/dist/core/inventory.js.map +1 -0
- package/dist/core/keychain.d.ts.map +1 -0
- package/dist/{keychain.js → core/keychain.js} +53 -15
- package/dist/core/keychain.js.map +1 -0
- package/dist/core/mcp/guard-client.cjs +86 -0
- package/dist/core/mcp/interceptor.cjs +238 -0
- package/dist/core/mcp/jsonrpc.cjs +194 -0
- package/dist/core/mcp/transport/http-server-side.cjs +89 -0
- package/dist/core/mcp/transport/http-upstream.cjs +111 -0
- package/dist/core/mcp/transport/http_forward.cjs +40 -0
- package/dist/core/mcp/transport/http_input.cjs +46 -0
- package/dist/core/mcp/transport/http_reverse.cjs +33 -0
- package/dist/core/mcp/transport/index.cjs +32 -0
- package/dist/core/mcp/transport/sse_bridge.cjs +101 -0
- package/dist/core/mcp/transport/stdio.cjs +60 -0
- package/dist/core/mcp-interpose.cjs +141 -0
- package/dist/core/mcp-protect.d.ts +69 -0
- package/dist/core/mcp-protect.d.ts.map +1 -0
- package/dist/core/mcp-protect.js +205 -0
- package/dist/core/mcp-protect.js.map +1 -0
- package/dist/core/mcp-scan.d.ts +40 -0
- package/dist/core/mcp-scan.d.ts.map +1 -0
- package/dist/core/mcp-scan.js +201 -0
- package/dist/core/mcp-scan.js.map +1 -0
- package/dist/core/mock-server.d.ts.map +1 -0
- package/dist/{mock-server.js → core/mock-server.js} +60 -4
- package/dist/core/mock-server.js.map +1 -0
- package/package.json +9 -10
- package/config.yaml.example +0 -26
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -289
- package/dist/cli.js.map +0 -1
- package/dist/config.d.ts +0 -28
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -63
- package/dist/config.js.map +0 -1
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -44
- package/dist/constants.js.map +0 -1
- package/dist/installer.d.ts.map +0 -1
- package/dist/installer.js +0 -137
- package/dist/installer.js.map +0 -1
- package/dist/keychain.d.ts.map +0 -1
- package/dist/keychain.js.map +0 -1
- package/dist/mock-server.d.ts.map +0 -1
- package/dist/mock-server.js.map +0 -1
- package/dist/scanner.d.ts.map +0 -1
- package/dist/scanner.js.map +0 -1
- package/hooks/guardion-hook.cjs +0 -202
- /package/dist/{cli.d.ts → bin/cli.d.ts} +0 -0
- /package/dist/{scanner.d.ts → connectors/claude-code/src/scanner.d.ts} +0 -0
- /package/dist/{keychain.d.ts → core/keychain.d.ts} +0 -0
- /package/{hooks → dist/core}/metadata.cjs +0 -0
- /package/dist/{mock-server.d.ts → core/mock-server.d.ts} +0 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import yaml from 'js-yaml';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { GUARDION_DIR, CONFIG_YAML_PATH, CONFIG_JSON_PATH, DEFAULT_API_URL, DEFAULT_GATEWAY_URL, DEFAULT_MCP_URL, ALL_HOOK_EVENTS, } from './constants.js';
|
|
5
|
+
// ── Sub-schemas ───────────────────────────────────────────────────────────────
|
|
6
|
+
const GatewaySchema = z.object({
|
|
7
|
+
/** Base URL of the Guardion gateway container / cloud endpoint */
|
|
8
|
+
url: z.string().url().default(DEFAULT_GATEWAY_URL),
|
|
9
|
+
/** MCP proxy base URL */
|
|
10
|
+
mcp_url: z.string().url().default(DEFAULT_MCP_URL),
|
|
11
|
+
/** LLM provider the gateway will forward to */
|
|
12
|
+
provider: z.enum(['anthropic', 'vertex-ai', 'bedrock', 'openai']).default('anthropic'),
|
|
13
|
+
/** Vertex AI only */
|
|
14
|
+
vertex_project_id: z.string().default(''),
|
|
15
|
+
vertex_region: z.string().default(''),
|
|
16
|
+
});
|
|
17
|
+
const HooksConfigSchema = z.object({
|
|
18
|
+
/**
|
|
19
|
+
* Subset of Claude Code hook events to register.
|
|
20
|
+
* Defaults to all supported events when omitted.
|
|
21
|
+
* Security teams can narrow this list via MDM config.
|
|
22
|
+
*/
|
|
23
|
+
events: z.array(z.string()).default([...ALL_HOOK_EVENTS]),
|
|
24
|
+
/** Milliseconds to wait for Guard API before giving up (fire-and-forget) */
|
|
25
|
+
timeout_ms: z.number().int().positive().default(3000),
|
|
26
|
+
});
|
|
27
|
+
const InventoryConfigSchema = z.object({
|
|
28
|
+
/** Master switch — set to false to disable all local tool inventory scanning */
|
|
29
|
+
enabled: z.boolean().default(true),
|
|
30
|
+
/** Scan local SKILL.md files (~/.claude/skills, project .claude/skills, plugin cache) */
|
|
31
|
+
scan_skills: z.boolean().default(true),
|
|
32
|
+
/** Scan configured MCP servers (settings.json, .mcp.json) */
|
|
33
|
+
scan_mcp: z.boolean().default(true),
|
|
34
|
+
/** Scan installed plugins / their declared MCP servers */
|
|
35
|
+
scan_plugins: z.boolean().default(true),
|
|
36
|
+
/** Include Claude Code built-in tools (Bash, Read, Write, …) */
|
|
37
|
+
scan_builtins: z.boolean().default(true),
|
|
38
|
+
});
|
|
39
|
+
// ── Root schema ───────────────────────────────────────────────────────────────
|
|
40
|
+
const ConfigSchema = z.object({
|
|
41
|
+
version: z.literal(1),
|
|
42
|
+
/**
|
|
43
|
+
* Deployment tier:
|
|
44
|
+
* hooks — fire-and-forget hook events to Guard API, no LLM proxy
|
|
45
|
+
* full — route all LLM traffic through Guardion gateway + hook events
|
|
46
|
+
*/
|
|
47
|
+
tier: z.enum(['hooks', 'full']),
|
|
48
|
+
/** Guard API base URL */
|
|
49
|
+
api_url: z.string().url(),
|
|
50
|
+
/** Policy slug to evaluate hook events against */
|
|
51
|
+
policy: z.string().min(1),
|
|
52
|
+
/** Application label attached to every event in the console */
|
|
53
|
+
application: z.string().min(1),
|
|
54
|
+
/** Gateway proxy settings (full tier only) */
|
|
55
|
+
gateway: GatewaySchema.optional(),
|
|
56
|
+
/** Hook event configuration */
|
|
57
|
+
hooks: HooksConfigSchema.optional(),
|
|
58
|
+
/** Local tool inventory scanning (sent to Guard API on SessionStart) */
|
|
59
|
+
inventory: InventoryConfigSchema.optional(),
|
|
60
|
+
/**
|
|
61
|
+
* P2 enforcement: when true, PreToolUse/PostToolUse make a SYNCHRONOUS Guard
|
|
62
|
+
* eval and can deny/warn on tool input+output. Default OFF (observability-
|
|
63
|
+
* first) so policy false positives can't block real work on day one.
|
|
64
|
+
*/
|
|
65
|
+
enforce: z.boolean().default(false),
|
|
66
|
+
/**
|
|
67
|
+
* If the Guard eval is unreachable/times out: false (default) = fail-open
|
|
68
|
+
* (allow); true = fail-closed (deny). Should mirror the policy's fail_mode.
|
|
69
|
+
*/
|
|
70
|
+
fail_closed: z.boolean().default(false),
|
|
71
|
+
/**
|
|
72
|
+
* Default mode for the `guardion mcp` interposer when not set per-server:
|
|
73
|
+
* dlp (anonymize, never block) | enforce (block on deny + redact) | monitor (observe).
|
|
74
|
+
* Per-server `--mode` on the injected prefix overrides this.
|
|
75
|
+
*/
|
|
76
|
+
mode: z.enum(['dlp', 'enforce', 'monitor']).optional(),
|
|
77
|
+
/** Interposer: apply Guard corrections (default true). */
|
|
78
|
+
redact: z.boolean().optional(),
|
|
79
|
+
/** Interposer: tool-list integrity check at connect (default true). */
|
|
80
|
+
integrity: z.boolean().optional(),
|
|
81
|
+
});
|
|
82
|
+
// ── Defaults ──────────────────────────────────────────────────────────────────
|
|
83
|
+
export const DEFAULT_GATEWAY = {
|
|
84
|
+
url: DEFAULT_GATEWAY_URL,
|
|
85
|
+
mcp_url: DEFAULT_MCP_URL,
|
|
86
|
+
provider: 'anthropic',
|
|
87
|
+
vertex_project_id: '',
|
|
88
|
+
vertex_region: '',
|
|
89
|
+
};
|
|
90
|
+
export const DEFAULT_HOOKS_CONFIG = {
|
|
91
|
+
events: [...ALL_HOOK_EVENTS],
|
|
92
|
+
timeout_ms: 3000,
|
|
93
|
+
};
|
|
94
|
+
export const DEFAULT_INVENTORY_CONFIG = {
|
|
95
|
+
enabled: true,
|
|
96
|
+
scan_skills: true,
|
|
97
|
+
scan_mcp: true,
|
|
98
|
+
scan_plugins: true,
|
|
99
|
+
scan_builtins: true,
|
|
100
|
+
};
|
|
101
|
+
export const DEFAULT_CONFIG = {
|
|
102
|
+
version: 1,
|
|
103
|
+
tier: 'hooks',
|
|
104
|
+
api_url: DEFAULT_API_URL,
|
|
105
|
+
policy: 'prompt-defense',
|
|
106
|
+
application: 'claude-code',
|
|
107
|
+
enforce: false,
|
|
108
|
+
fail_closed: false,
|
|
109
|
+
};
|
|
110
|
+
/** Resolved hooks events — falls back to all events when not configured */
|
|
111
|
+
export function resolvedHookEvents(cfg) {
|
|
112
|
+
const events = cfg.hooks?.events;
|
|
113
|
+
if (!events || events.length === 0)
|
|
114
|
+
return ALL_HOOK_EVENTS;
|
|
115
|
+
// Filter to only known events to prevent config injection
|
|
116
|
+
return events.filter(e => ALL_HOOK_EVENTS.includes(e));
|
|
117
|
+
}
|
|
118
|
+
// ── Read ──────────────────────────────────────────────────────────────────────
|
|
119
|
+
export function readConfig() {
|
|
120
|
+
for (const p of [CONFIG_YAML_PATH, CONFIG_YAML_PATH.replace('.yaml', '.json')]) {
|
|
121
|
+
try {
|
|
122
|
+
const raw = fs.readFileSync(p, 'utf-8');
|
|
123
|
+
const parsed = p.endsWith('.json') ? JSON.parse(raw) : yaml.load(raw);
|
|
124
|
+
return ConfigSchema.parse(parsed);
|
|
125
|
+
}
|
|
126
|
+
catch { /* try next */ }
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
export function readConfigOrDefault() {
|
|
131
|
+
return readConfig() ?? DEFAULT_CONFIG;
|
|
132
|
+
}
|
|
133
|
+
// ── Write ─────────────────────────────────────────────────────────────────────
|
|
134
|
+
export function writeConfig(cfg) {
|
|
135
|
+
const validated = ConfigSchema.parse(cfg);
|
|
136
|
+
fs.mkdirSync(GUARDION_DIR, { recursive: true });
|
|
137
|
+
// Human-editable YAML
|
|
138
|
+
const header = [
|
|
139
|
+
'# Guardion config — edit freely, generated by `npx guardion init`',
|
|
140
|
+
'# Token is stored in your OS keychain, not here.',
|
|
141
|
+
'# Docs: https://guardion.ai/docs/claude-code',
|
|
142
|
+
'',
|
|
143
|
+
].join('\n');
|
|
144
|
+
writeAtomic(CONFIG_YAML_PATH, header + yaml.dump(validated, { indent: 2 }));
|
|
145
|
+
// JSON for the CJS hook (zero-dep, no YAML parser)
|
|
146
|
+
writeAtomic(CONFIG_JSON_PATH, JSON.stringify(validated, null, 2) + '\n');
|
|
147
|
+
}
|
|
148
|
+
// ── Atomic write ──────────────────────────────────────────────────────────────
|
|
149
|
+
function writeAtomic(filePath, content) {
|
|
150
|
+
const tmp = filePath + '.tmp';
|
|
151
|
+
fs.writeFileSync(tmp, content, 'utf-8');
|
|
152
|
+
fs.renameSync(tmp, filePath);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../core/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAQ,SAAS,CAAC;AAC3B,OAAO,IAAI,MAAO,SAAS,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAExB,iFAAiF;AAEjF,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,kEAAkE;IAClE,GAAG,EAAgB,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAChE,yBAAyB;IACzB,OAAO,EAAY,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC;IAC5D,+CAA+C;IAC/C,QAAQ,EAAW,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAC/F,qBAAqB;IACrB,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACzC,aAAa,EAAM,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;CAC1C,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC;;;;OAIG;IACH,MAAM,EAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,eAAe,CAAC,CAAC;IAC7D,4EAA4E;IAC5E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACtD,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,gFAAgF;IAChF,OAAO,EAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,yFAAyF;IACzF,WAAW,EAAI,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,6DAA6D;IAC7D,QAAQ,EAAO,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,0DAA0D;IAC1D,YAAY,EAAG,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACxC,gEAAgE;IAChE,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;CACzC,CAAC,CAAC;AAEH,iFAAiF;AAEjF,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,OAAO,EAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACzB;;;;OAIG;IACH,IAAI,EAAS,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACtC,yBAAyB;IACzB,OAAO,EAAM,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC7B,kDAAkD;IAClD,MAAM,EAAO,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,+DAA+D;IAC/D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,8CAA8C;IAC9C,OAAO,EAAM,aAAa,CAAC,QAAQ,EAAE;IACrC,+BAA+B;IAC/B,KAAK,EAAQ,iBAAiB,CAAC,QAAQ,EAAE;IACzC,wEAAwE;IACxE,SAAS,EAAI,qBAAqB,CAAC,QAAQ,EAAE;IAC7C;;;;OAIG;IACH,OAAO,EAAM,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACvC;;;OAGG;IACH,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACvC;;;;OAIG;IACH,IAAI,EAAS,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC7D,0DAA0D;IAC1D,MAAM,EAAO,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACnC,uEAAuE;IACvE,SAAS,EAAI,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAOH,iFAAiF;AAEjF,MAAM,CAAC,MAAM,eAAe,GAAkB;IAC5C,GAAG,EAAgB,mBAAmB;IACtC,OAAO,EAAY,eAAe;IAClC,QAAQ,EAAW,WAAW;IAC9B,iBAAiB,EAAE,EAAE;IACrB,aAAa,EAAM,EAAE;CACtB,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,MAAM,EAAM,CAAC,GAAG,eAAe,CAAC;IAChC,UAAU,EAAE,IAAI;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACvD,OAAO,EAAQ,IAAI;IACnB,WAAW,EAAI,IAAI;IACnB,QAAQ,EAAO,IAAI;IACnB,YAAY,EAAG,IAAI;IACnB,aAAa,EAAE,IAAI;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,OAAO,EAAM,CAAC;IACd,IAAI,EAAS,OAAO;IACpB,OAAO,EAAM,eAAe;IAC5B,MAAM,EAAO,gBAAgB;IAC7B,WAAW,EAAE,aAAa;IAC1B,OAAO,EAAM,KAAK;IAClB,WAAW,EAAE,KAAK;CACnB,CAAC;AAEF,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IACpD,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC;IACjC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IAC3D,0DAA0D;IAC1D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAE,eAAqC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,UAAU;IACxB,KAAK,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;QAC/E,IAAI,CAAC;YACH,MAAM,GAAG,GAAM,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC3C,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtE,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,UAAU,EAAE,IAAI,cAAc,CAAC;AACxC,CAAC;AAED,iFAAiF;AAEjF,MAAM,UAAU,WAAW,CAAC,GAAmB;IAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1C,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhD,sBAAsB;IACtB,MAAM,MAAM,GAAG;QACb,mEAAmE;QACnE,kDAAkD;QAClD,8CAA8C;QAC9C,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,WAAW,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5E,mDAAmD;IACnD,WAAW,CAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,iFAAiF;AAEjF,SAAS,WAAW,CAAC,QAAgB,EAAE,OAAe;IACpD,MAAM,GAAG,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9B,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACxC,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const GUARDION_VERSION = "0.
|
|
1
|
+
export declare const GUARDION_VERSION = "0.4.0";
|
|
2
2
|
export declare const TOKEN_PREFIX = "grd_";
|
|
3
3
|
export declare const BACKUP_KEEP = 5;
|
|
4
4
|
export declare const DEFAULT_API_URL = "https://api.guardion.ai";
|
|
@@ -21,6 +21,11 @@ export declare const CLAUDE_SETTINGS_PATH: string;
|
|
|
21
21
|
export declare const BACKUP_SUFFIX = ".guardion";
|
|
22
22
|
export declare const KEYCHAIN_SERVICE = "guardion";
|
|
23
23
|
export declare const KEYCHAIN_ACCOUNT = "token";
|
|
24
|
-
export declare const
|
|
25
|
-
export type HookEvent = (typeof
|
|
24
|
+
export declare const ALL_HOOK_EVENTS: readonly ["SessionStart", "SessionEnd", "UserPromptSubmit", "PreToolUse", "PostToolUse", "PostToolUseFailure", "PostToolBatch", "SubagentStart", "SubagentStop", "Stop", "StopFailure", "PermissionDenied"];
|
|
25
|
+
export type HookEvent = (typeof ALL_HOOK_EVENTS)[number];
|
|
26
|
+
export declare const HEADER_API_KEY = "x-guardion-api-key";
|
|
27
|
+
export declare const HEADER_PROVIDER = "x-guardion-provider";
|
|
28
|
+
export declare const HEADER_POLICY = "x-guardion-policy";
|
|
29
|
+
export declare const HEADER_TRACE_ID = "x-guardion-trace-id";
|
|
30
|
+
export declare const HEADER_METADATA = "x-guardion-metadata";
|
|
26
31
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../core/constants.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,YAAY,SAAa,CAAC;AACvC,eAAO,MAAM,WAAW,IAAS,CAAC;AAGlC,eAAO,MAAM,eAAe,4BAAgC,CAAC;AAC7D,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AACjE,eAAO,MAAM,eAAe,4BAAgC,CAAC;AAG7D,eAAO,MAAM,WAAW,0BAA8B,CAAC;AACvD,eAAO,MAAM,eAAe,0BAA0B,CAAC;AACvD,eAAO,MAAM,WAAW,8BAAkC,CAAC;AAG3D,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,WAAW,YAAiB,CAAC;AAG1C,eAAO,MAAM,QAAQ,QAA2B,CAAC;AACjD,eAAO,MAAM,YAAY,QAA2C,CAAC;AACrE,eAAO,MAAM,gBAAgB,QAA6C,CAAC;AAC3E,eAAO,MAAM,gBAAgB,QAA6C,CAAC;AAC3E,eAAO,MAAM,eAAe,QAAwC,CAAC;AACrE,eAAO,MAAM,kBAAkB,8BAAgC,CAAC;AAChE,eAAO,MAAM,iBAAiB,wBAA2B,CAAC;AAE1D,eAAO,MAAM,UAAU,QAA2C,CAAC;AACnE,eAAO,MAAM,oBAAoB,QAAyC,CAAC;AAC3E,eAAO,MAAM,aAAa,cAAqB,CAAC;AAGhD,eAAO,MAAM,gBAAgB,aAAa,CAAC;AAC3C,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAKxC,eAAO,MAAM,eAAe,6MAalB,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAGzD,eAAO,MAAM,cAAc,uBAAyB,CAAC;AACrD,eAAO,MAAM,eAAe,wBAAyB,CAAC;AACtD,eAAO,MAAM,aAAa,sBAAyB,CAAC;AACpD,eAAO,MAAM,eAAe,wBAAyB,CAAC;AACtD,eAAO,MAAM,eAAe,wBAAyB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
export const GUARDION_VERSION = '0.4.0';
|
|
4
|
+
export const TOKEN_PREFIX = 'grd_';
|
|
5
|
+
export const BACKUP_KEEP = 5;
|
|
6
|
+
// ── Production URLs ───────────────────────────────────────────────────────────
|
|
7
|
+
export const DEFAULT_API_URL = 'https://api.guardion.ai';
|
|
8
|
+
export const DEFAULT_GATEWAY_URL = 'https://gateway.guardion.ai';
|
|
9
|
+
export const DEFAULT_MCP_URL = 'https://mcp.guardion.ai';
|
|
10
|
+
// ── Local dev (Docker stack) ──────────────────────────────────────────────────
|
|
11
|
+
export const DEV_API_URL = 'http://localhost:8082'; // guardion-guard
|
|
12
|
+
export const DEV_GATEWAY_URL = 'http://localhost:8788'; // guardion-gateway
|
|
13
|
+
export const DEV_MCP_URL = 'http://localhost:8082/mcp';
|
|
14
|
+
// ── Endpoint paths ────────────────────────────────────────────────────────────
|
|
15
|
+
export const HOOK_EVENTS_PATH = '/v1/hooks/events';
|
|
16
|
+
export const HEALTH_PATH = '/health';
|
|
17
|
+
// ── Filesystem paths ──────────────────────────────────────────────────────────
|
|
18
|
+
export const HOME_DIR = os.homedir();
|
|
19
|
+
export const GUARDION_DIR = path.join(HOME_DIR, '.guardion');
|
|
20
|
+
export const CONFIG_YAML_PATH = path.join(GUARDION_DIR, 'config.yaml');
|
|
21
|
+
export const CONFIG_JSON_PATH = path.join(GUARDION_DIR, 'config.json');
|
|
22
|
+
export const TOKEN_FILE_PATH = path.join(GUARDION_DIR, 'token');
|
|
23
|
+
export const SYSTEM_CONFIG_PATH = '/etc/guardion/config.yaml';
|
|
24
|
+
export const SYSTEM_TOKEN_PATH = '/etc/guardion/token';
|
|
25
|
+
export const CLAUDE_DIR = path.join(HOME_DIR, '.claude');
|
|
26
|
+
export const CLAUDE_SETTINGS_PATH = path.join(CLAUDE_DIR, 'settings.json');
|
|
27
|
+
export const BACKUP_SUFFIX = '.guardion';
|
|
28
|
+
// ── Keychain ──────────────────────────────────────────────────────────────────
|
|
29
|
+
export const KEYCHAIN_SERVICE = 'guardion';
|
|
30
|
+
export const KEYCHAIN_ACCOUNT = 'token';
|
|
31
|
+
// ── Hook events ───────────────────────────────────────────────────────────────
|
|
32
|
+
// Complete list of Claude Code hook events Guardion can register.
|
|
33
|
+
// The active subset is controlled by config.yaml hooks.events.
|
|
34
|
+
export const ALL_HOOK_EVENTS = [
|
|
35
|
+
'SessionStart',
|
|
36
|
+
'SessionEnd',
|
|
37
|
+
'UserPromptSubmit',
|
|
38
|
+
'PreToolUse',
|
|
39
|
+
'PostToolUse',
|
|
40
|
+
'PostToolUseFailure',
|
|
41
|
+
'PostToolBatch',
|
|
42
|
+
'SubagentStart',
|
|
43
|
+
'SubagentStop',
|
|
44
|
+
'Stop',
|
|
45
|
+
'StopFailure',
|
|
46
|
+
'PermissionDenied',
|
|
47
|
+
];
|
|
48
|
+
// ── Gateway header names ──────────────────────────────────────────────────────
|
|
49
|
+
export const HEADER_API_KEY = 'x-guardion-api-key';
|
|
50
|
+
export const HEADER_PROVIDER = 'x-guardion-provider';
|
|
51
|
+
export const HEADER_POLICY = 'x-guardion-policy';
|
|
52
|
+
export const HEADER_TRACE_ID = 'x-guardion-trace-id';
|
|
53
|
+
export const HEADER_METADATA = 'x-guardion-metadata';
|
|
54
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../core/constants.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAQ,SAAS,CAAC;AAE3B,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AACxC,MAAM,CAAC,MAAM,YAAY,GAAO,MAAM,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAQ,CAAC,CAAC;AAElC,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAO,yBAAyB,CAAC;AAC7D,MAAM,CAAC,MAAM,mBAAmB,GAAG,6BAA6B,CAAC;AACjE,MAAM,CAAC,MAAM,eAAe,GAAO,yBAAyB,CAAC;AAE7D,iFAAiF;AACjF,MAAM,CAAC,MAAM,WAAW,GAAO,uBAAuB,CAAC,CAAG,iBAAiB;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAG,uBAAuB,CAAC,CAAG,mBAAmB;AAC7E,MAAM,CAAC,MAAM,WAAW,GAAO,2BAA2B,CAAC;AAE3D,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AACnD,MAAM,CAAC,MAAM,WAAW,GAAQ,SAAS,CAAC;AAE1C,iFAAiF;AACjF,MAAM,CAAC,MAAM,QAAQ,GAAe,EAAE,CAAC,OAAO,EAAE,CAAC;AACjD,MAAM,CAAC,MAAM,YAAY,GAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,gBAAgB,GAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,gBAAgB,GAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,eAAe,GAAQ,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AACrE,MAAM,CAAC,MAAM,kBAAkB,GAAK,2BAA2B,CAAC;AAChE,MAAM,CAAC,MAAM,iBAAiB,GAAM,qBAAqB,CAAC;AAE1D,MAAM,CAAC,MAAM,UAAU,GAAa,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AACnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAC3E,MAAM,CAAC,MAAM,aAAa,GAAU,WAAW,CAAC;AAEhD,iFAAiF;AACjF,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAC3C,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAExC,iFAAiF;AACjF,kEAAkE;AAClE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,YAAY;IACZ,kBAAkB;IAClB,YAAY;IACZ,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,eAAe;IACf,cAAc;IACd,MAAM;IACN,aAAa;IACb,kBAAkB;CACV,CAAC;AAIX,iFAAiF;AACjF,MAAM,CAAC,MAAM,cAAc,GAAK,oBAAoB,CAAC;AACrD,MAAM,CAAC,MAAM,eAAe,GAAI,qBAAqB,CAAC;AACtD,MAAM,CAAC,MAAM,aAAa,GAAM,mBAAmB,CAAC;AACpD,MAAM,CAAC,MAAM,eAAe,GAAI,qBAAqB,CAAC;AACtD,MAAM,CAAC,MAAM,eAAe,GAAI,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type Scanner = 'process' | 'config' | 'repo';
|
|
2
|
+
export interface DiscoveredAgent {
|
|
3
|
+
fingerprint: string;
|
|
4
|
+
name: string;
|
|
5
|
+
agent_type: string;
|
|
6
|
+
scanner: Scanner;
|
|
7
|
+
evidence: string;
|
|
8
|
+
source_location: string;
|
|
9
|
+
confidence: number;
|
|
10
|
+
risk_level: 'info' | 'low' | 'medium' | 'high' | 'critical';
|
|
11
|
+
risk_score: number;
|
|
12
|
+
}
|
|
13
|
+
interface Sig {
|
|
14
|
+
agent_type: string;
|
|
15
|
+
proc: RegExp;
|
|
16
|
+
deps: RegExp;
|
|
17
|
+
}
|
|
18
|
+
export declare const SIGNATURES: Sig[];
|
|
19
|
+
/** Redact obvious secrets from a string before it's displayed/stored. */
|
|
20
|
+
export declare function redactSecrets(text: string): string;
|
|
21
|
+
/** Pure: classify `ps`-style command lines into discovered agents. */
|
|
22
|
+
export declare function scanProcessLines(lines: string[]): DiscoveredAgent[];
|
|
23
|
+
/** Pure: classify dependency names (from a manifest) into discovered agents. */
|
|
24
|
+
export declare function scanDeps(deps: string[], location: string): DiscoveredAgent[];
|
|
25
|
+
export interface DiscoverOpts {
|
|
26
|
+
cwd?: string;
|
|
27
|
+
scanners?: Scanner[];
|
|
28
|
+
}
|
|
29
|
+
/** Run the requested scanners and return de-duplicated discovered agents. */
|
|
30
|
+
export declare function discover(opts?: DiscoverOpts): DiscoveredAgent[];
|
|
31
|
+
/** Submit discovered agents to Guard (/v1/discovery → ai_shadow_agents). */
|
|
32
|
+
export declare function submitDiscovery(apiUrl: string, token: string, agents: DiscoveredAgent[], application?: string): Promise<{
|
|
33
|
+
status: number;
|
|
34
|
+
}>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=discover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../core/discover.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,UAAU,GAAG;IAAG,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAChE,eAAO,MAAM,UAAU,EAAE,GAAG,EAY3B,CAAC;AAEF,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKlD;AAqBD,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAcnE;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAY5E;AAmBD,MAAM,WAAW,YAAY;IAAG,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE;AAEpE,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,IAAI,GAAE,YAAiB,GAAG,eAAe,EAAE,CA8BnE;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,EAAE,WAAW,SAAa,GACjF,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa7B"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// `guardion discover` — Shadow-AI Discovery (AGT port). Finds UNREGISTERED agents
|
|
2
|
+
// running or configured on this machine across three scanners: process (running
|
|
3
|
+
// agent frameworks), config (agent config files), and repo (framework deps in
|
|
4
|
+
// manifests). Output is local-only; CLI secrets are redacted before display.
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import http from 'node:http';
|
|
8
|
+
import https from 'node:https';
|
|
9
|
+
import crypto from 'node:crypto';
|
|
10
|
+
import { spawnSync } from 'node:child_process';
|
|
11
|
+
export const SIGNATURES = [
|
|
12
|
+
{ agent_type: 'langchain', proc: /langchain|langgraph/i, deps: /^(langchain|langgraph|@langchain\/)/i },
|
|
13
|
+
{ agent_type: 'crewai', proc: /crewai/i, deps: /^crewai/i },
|
|
14
|
+
{ agent_type: 'autogen', proc: /autogen|pyautogen|\bag2\b/i, deps: /^(autogen|pyautogen|ag2)/i },
|
|
15
|
+
{ agent_type: 'openai_agents', proc: /openai[-_ ]agents/i, deps: /^(openai-agents|@openai\/agents)/i },
|
|
16
|
+
{ agent_type: 'semantic_kernel', proc: /semantic[-_ ]kernel/i, deps: /semantic[-_]kernel/i },
|
|
17
|
+
{ agent_type: 'llamaindex', proc: /llama[-_ ]?index/i, deps: /llama[-_]?index/i },
|
|
18
|
+
{ agent_type: 'haystack', proc: /haystack/i, deps: /haystack/i },
|
|
19
|
+
{ agent_type: 'pydantic_ai', proc: /pydantic[-_ ]ai/i, deps: /^pydantic-ai/i },
|
|
20
|
+
{ agent_type: 'google_adk', proc: /google[-_ ]adk|google\.adk/i, deps: /google[-_]adk/i },
|
|
21
|
+
{ agent_type: 'mcp_server', proc: /modelcontextprotocol|mcp[-_ ]?server/i, deps: /(@modelcontextprotocol\/|^mcp$|^fastmcp$)/i },
|
|
22
|
+
{ agent_type: 'agt', proc: /agentmesh|agent[-_ ]governance/i, deps: /(agentmesh|agent-governance)/i },
|
|
23
|
+
];
|
|
24
|
+
/** Redact obvious secrets from a string before it's displayed/stored. */
|
|
25
|
+
export function redactSecrets(text) {
|
|
26
|
+
return (text || '')
|
|
27
|
+
.replace(/\b(sk|grd|ghp|gho|xox[baprs]|AKIA)[-_][A-Za-z0-9_-]{8,}/g, '$1-[REDACTED]')
|
|
28
|
+
.replace(/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g, '[REDACTED_JWT]')
|
|
29
|
+
.replace(/\b[A-Za-z0-9_-]{32,}\b/g, (m) => (/[0-9]/.test(m) && /[a-zA-Z]/.test(m) ? '[REDACTED]' : m));
|
|
30
|
+
}
|
|
31
|
+
function fingerprint(agent_type, name, location) {
|
|
32
|
+
return crypto.createHash('sha256').update(`${agent_type}:${name}:${location}`).digest('hex').slice(0, 16);
|
|
33
|
+
}
|
|
34
|
+
function score(agent_type, scanner) {
|
|
35
|
+
// Running (process) > configured (config) > declared (repo dep).
|
|
36
|
+
const base = scanner === 'process' ? 70 : scanner === 'config' ? 45 : 25;
|
|
37
|
+
const conf = scanner === 'process' ? 0.9 : scanner === 'config' ? 0.7 : 0.5;
|
|
38
|
+
const risk_score = Math.min(100, base + (agent_type === 'mcp_server' ? 10 : 0));
|
|
39
|
+
const risk_level = risk_score >= 80 ? 'high' : risk_score >= 55 ? 'medium' : risk_score >= 30 ? 'low' : 'info';
|
|
40
|
+
return { confidence: conf, risk_score, risk_level };
|
|
41
|
+
}
|
|
42
|
+
function mk(agent_type, name, scanner, evidence, location) {
|
|
43
|
+
const s = score(agent_type, scanner);
|
|
44
|
+
return { fingerprint: fingerprint(agent_type, name, location), name, agent_type, scanner,
|
|
45
|
+
evidence: redactSecrets(evidence).slice(0, 200), source_location: location, ...s };
|
|
46
|
+
}
|
|
47
|
+
/** Pure: classify `ps`-style command lines into discovered agents. */
|
|
48
|
+
export function scanProcessLines(lines) {
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const raw of lines) {
|
|
51
|
+
const line = (raw || '').trim();
|
|
52
|
+
if (!line)
|
|
53
|
+
continue;
|
|
54
|
+
for (const sig of SIGNATURES) {
|
|
55
|
+
if (sig.proc.test(line)) {
|
|
56
|
+
const name = (line.split(/\s+/).find((w) => /\.(py|ts|js|mjs)$/.test(w)) || sig.agent_type);
|
|
57
|
+
out.push(mk(sig.agent_type, path.basename(name), 'process', line, 'process'));
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
/** Pure: classify dependency names (from a manifest) into discovered agents. */
|
|
65
|
+
export function scanDeps(deps, location) {
|
|
66
|
+
const out = [];
|
|
67
|
+
const seen = new Set();
|
|
68
|
+
for (const dep of deps) {
|
|
69
|
+
for (const sig of SIGNATURES) {
|
|
70
|
+
if (sig.deps.test(dep) && !seen.has(sig.agent_type)) {
|
|
71
|
+
seen.add(sig.agent_type);
|
|
72
|
+
out.push(mk(sig.agent_type, dep, 'repo', `dependency: ${dep}`, location));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function depsFromManifest(file) {
|
|
79
|
+
try {
|
|
80
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
81
|
+
if (file.endsWith('package.json')) {
|
|
82
|
+
const j = JSON.parse(raw);
|
|
83
|
+
return [...Object.keys(j.dependencies || {}), ...Object.keys(j.devDependencies || {})];
|
|
84
|
+
}
|
|
85
|
+
if (file.endsWith('requirements.txt')) {
|
|
86
|
+
return raw.split('\n').map((l) => l.split(/[=<>~!\[ ]/)[0].trim()).filter(Boolean);
|
|
87
|
+
}
|
|
88
|
+
if (file.endsWith('pyproject.toml')) {
|
|
89
|
+
return (raw.match(/^[\s"']*([A-Za-z0-9._-]+)\s*[=>~]/gm) || []).map((l) => l.replace(/[\s"'=>~].*$/, '').trim()).filter(Boolean);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch { /* ignore */ }
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
/** Run the requested scanners and return de-duplicated discovered agents. */
|
|
96
|
+
export function discover(opts = {}) {
|
|
97
|
+
const cwd = opts.cwd || process.cwd();
|
|
98
|
+
const scanners = opts.scanners || ['process', 'config', 'repo'];
|
|
99
|
+
const found = [];
|
|
100
|
+
if (scanners.includes('process')) {
|
|
101
|
+
try {
|
|
102
|
+
const ps = spawnSync('ps', ['-axo', 'command='], { encoding: 'utf8', timeout: 5000 });
|
|
103
|
+
if (ps.stdout)
|
|
104
|
+
found.push(...scanProcessLines(ps.stdout.split('\n')));
|
|
105
|
+
}
|
|
106
|
+
catch { /* ps unavailable */ }
|
|
107
|
+
}
|
|
108
|
+
if (scanners.includes('repo')) {
|
|
109
|
+
for (const f of ['package.json', 'requirements.txt', 'pyproject.toml']) {
|
|
110
|
+
const p = path.join(cwd, f);
|
|
111
|
+
if (fs.existsSync(p))
|
|
112
|
+
found.push(...scanDeps(depsFromManifest(p), p));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (scanners.includes('config')) {
|
|
116
|
+
const map = {
|
|
117
|
+
'agentmesh.yaml': 'agt', 'crewai.yaml': 'crewai', 'mcp.json': 'mcp_server', '.mcp.json': 'mcp_server',
|
|
118
|
+
};
|
|
119
|
+
for (const [fname, type] of Object.entries(map)) {
|
|
120
|
+
const p = path.join(cwd, fname);
|
|
121
|
+
if (fs.existsSync(p))
|
|
122
|
+
found.push(mk(type, fname, 'config', `config: ${fname}`, p));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// de-dup by fingerprint
|
|
126
|
+
const byFp = new Map();
|
|
127
|
+
for (const a of found)
|
|
128
|
+
if (!byFp.has(a.fingerprint))
|
|
129
|
+
byFp.set(a.fingerprint, a);
|
|
130
|
+
return [...byFp.values()];
|
|
131
|
+
}
|
|
132
|
+
/** Submit discovered agents to Guard (/v1/discovery → ai_shadow_agents). */
|
|
133
|
+
export function submitDiscovery(apiUrl, token, agents, application = 'discover') {
|
|
134
|
+
const body = JSON.stringify({ agents, application });
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
let url;
|
|
137
|
+
try {
|
|
138
|
+
url = new URL('/v1/discovery', apiUrl);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
return reject(e);
|
|
142
|
+
}
|
|
143
|
+
const transport = url.protocol === 'https:' ? https : http;
|
|
144
|
+
const req = transport.request({
|
|
145
|
+
hostname: url.hostname, port: url.port, path: url.pathname, method: 'POST', timeout: 8000,
|
|
146
|
+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, 'Content-Length': Buffer.byteLength(body) },
|
|
147
|
+
}, (res) => { res.resume(); res.on('end', () => resolve({ status: res.statusCode ?? 0 })); });
|
|
148
|
+
req.on('error', reject);
|
|
149
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
|
|
150
|
+
req.write(body);
|
|
151
|
+
req.end();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../core/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Local tool fingerprint pin (P1, AGT rug-pull). Zero-dep (node:crypto + fs).
|
|
4
|
+
*
|
|
5
|
+
* MUST match guard/core/tools/fingerprint.py byte-for-byte so the server can
|
|
6
|
+
* compare the prev_* hashes we send against the current ones it computes:
|
|
7
|
+
* description_hash = sha256(description.trim())[:16]
|
|
8
|
+
* schema_hash = sha256(canonicalSchema(parameters))[:16]
|
|
9
|
+
* canonicalSchema = JSON of params sorted by name, fields {name,type,description},
|
|
10
|
+
* no whitespace (JSON.stringify default == python separators=(",",":")).
|
|
11
|
+
*
|
|
12
|
+
* The pin (~/.guardion/fingerprints.json) records the last hashes seen per tool;
|
|
13
|
+
* on the next scan we attach prev_* so a changed description/schema is flagged as
|
|
14
|
+
* a rug-pull by the server, then we update the pin to the new baseline.
|
|
15
|
+
*/
|
|
16
|
+
const crypto = require('crypto');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
const path = require('path');
|
|
19
|
+
|
|
20
|
+
const HASH_LEN = 16;
|
|
21
|
+
|
|
22
|
+
function _h(text) {
|
|
23
|
+
return crypto.createHash('sha256').update(String(text == null ? '' : text), 'utf8')
|
|
24
|
+
.digest('hex').slice(0, HASH_LEN);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function descriptionHash(description) {
|
|
28
|
+
return _h(String(description == null ? '' : description).trim());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function canonicalSchema(parameters) {
|
|
32
|
+
const items = (parameters || []).map((p) => ({
|
|
33
|
+
name: (p && p.name) || '',
|
|
34
|
+
type: (p && p.type) || '',
|
|
35
|
+
description: (p && p.description) || '',
|
|
36
|
+
}));
|
|
37
|
+
items.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
38
|
+
return JSON.stringify(items);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function schemaHash(parameters) {
|
|
42
|
+
return _h(canonicalSchema(parameters));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function _key(t) {
|
|
46
|
+
return `${t.source || 'unknown'}:${t.server || ''}:${t.name || ''}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function _readPin(pinPath) {
|
|
50
|
+
try { return JSON.parse(fs.readFileSync(pinPath, 'utf8')) || {}; } catch { return {}; }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _writePin(pinPath, pin) {
|
|
54
|
+
try {
|
|
55
|
+
fs.mkdirSync(path.dirname(pinPath), { recursive: true });
|
|
56
|
+
const tmp = pinPath + '.tmp';
|
|
57
|
+
fs.writeFileSync(tmp, JSON.stringify(pin), 'utf8');
|
|
58
|
+
fs.renameSync(tmp, pinPath);
|
|
59
|
+
} catch { /* non-critical */ }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Attach prev_description_hash/prev_schema_hash to each tool from the local pin,
|
|
64
|
+
* then update the pin to the current hashes. Mutates + returns `tools`. Never throws.
|
|
65
|
+
*/
|
|
66
|
+
function pinAndEnrich(tools, pinPath) {
|
|
67
|
+
if (!Array.isArray(tools) || tools.length === 0) return tools || [];
|
|
68
|
+
let pin;
|
|
69
|
+
try { pin = _readPin(pinPath); } catch { pin = {}; }
|
|
70
|
+
for (const t of tools) {
|
|
71
|
+
try {
|
|
72
|
+
const dh = descriptionHash(t.description);
|
|
73
|
+
const sh = schemaHash(t.parameters); // [] for scan tools (no params) → constant
|
|
74
|
+
const prev = pin[_key(t)] || {};
|
|
75
|
+
t.prev_description_hash = prev.description_hash || '';
|
|
76
|
+
t.prev_schema_hash = prev.schema_hash || '';
|
|
77
|
+
pin[_key(t)] = { description_hash: dh, schema_hash: sh };
|
|
78
|
+
} catch { /* skip a bad tool, keep going */ }
|
|
79
|
+
}
|
|
80
|
+
_writePin(pinPath, pin);
|
|
81
|
+
return tools;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
module.exports = { descriptionHash, schemaHash, canonicalSchema, pinAndEnrich };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface ScannedTool {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
server: string;
|
|
5
|
+
source: string;
|
|
6
|
+
snapshot_source: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
marketplace?: string;
|
|
9
|
+
capabilities?: string[];
|
|
10
|
+
has_hooks?: boolean;
|
|
11
|
+
has_mcp?: boolean;
|
|
12
|
+
has_skills?: boolean;
|
|
13
|
+
parameters?: Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
type?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
}>;
|
|
18
|
+
prev_description_hash?: string;
|
|
19
|
+
prev_schema_hash?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Attach prev_* fingerprints from the local pin (~/.guardion/fingerprints.json)
|
|
22
|
+
* so the server can flag a changed tool as a rug-pull. Best-effort; never throws. */
|
|
23
|
+
export declare function pinInventory(tools: ScannedTool[]): ScannedTool[];
|
|
24
|
+
export interface SubmitOptions {
|
|
25
|
+
apiUrl: string;
|
|
26
|
+
token: string;
|
|
27
|
+
tools: ScannedTool[];
|
|
28
|
+
policy?: string;
|
|
29
|
+
application?: string;
|
|
30
|
+
}
|
|
31
|
+
/** POST the inventory to Guard API /v1/guard, tagged snapshot_source=plugin_scan. */
|
|
32
|
+
export declare function submitInventory(opts: SubmitOptions): Promise<{
|
|
33
|
+
status: number;
|
|
34
|
+
}>;
|
|
35
|
+
//# sourceMappingURL=inventory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../core/inventory.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;sFACsF;AACtF,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAUhE;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CA6ChF"}
|