@goplus/agentguard 1.1.3 → 1.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/README.md +28 -2
- package/dist/action/index.d.ts.map +1 -1
- package/dist/action/index.js +3 -1
- package/dist/action/index.js.map +1 -1
- package/dist/adapters/hermes.d.ts +25 -0
- package/dist/adapters/hermes.d.ts.map +1 -0
- package/dist/adapters/hermes.js +131 -0
- package/dist/adapters/hermes.js.map +1 -0
- package/dist/adapters/index.d.ts +1 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +3 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/openclaw-plugin.d.ts +12 -1
- package/dist/adapters/openclaw-plugin.d.ts.map +1 -1
- package/dist/adapters/openclaw-plugin.js +165 -9
- package/dist/adapters/openclaw-plugin.js.map +1 -1
- package/dist/cli.js +236 -0
- package/dist/cli.js.map +1 -1
- package/dist/cloud/client.d.ts +22 -0
- package/dist/cloud/client.d.ts.map +1 -1
- package/dist/cloud/client.js +61 -2
- package/dist/cloud/client.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +4 -2
- package/dist/config.js.map +1 -1
- package/dist/feed/cron.d.ts +25 -0
- package/dist/feed/cron.d.ts.map +1 -0
- package/dist/feed/cron.js +173 -0
- package/dist/feed/cron.js.map +1 -0
- package/dist/feed/selfcheck.d.ts +36 -0
- package/dist/feed/selfcheck.d.ts.map +1 -0
- package/dist/feed/selfcheck.js +198 -0
- package/dist/feed/selfcheck.js.map +1 -0
- package/dist/feed/state.d.ts +14 -0
- package/dist/feed/state.d.ts.map +1 -0
- package/dist/feed/state.js +57 -0
- package/dist/feed/state.js.map +1 -0
- package/dist/feed/types.d.ts +102 -0
- package/dist/feed/types.d.ts.map +1 -0
- package/dist/feed/types.js +15 -0
- package/dist/feed/types.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/installers.js +0 -1
- package/dist/installers.js.map +1 -1
- package/dist/runtime/protect.d.ts.map +1 -1
- package/dist/runtime/protect.js +6 -1
- package/dist/runtime/protect.js.map +1 -1
- package/dist/tests/adapter.test.js +146 -0
- package/dist/tests/adapter.test.js.map +1 -1
- package/dist/tests/feed-cloud.test.d.ts +2 -0
- package/dist/tests/feed-cloud.test.d.ts.map +1 -0
- package/dist/tests/feed-cloud.test.js +93 -0
- package/dist/tests/feed-cloud.test.js.map +1 -0
- package/dist/tests/feed-cron.test.d.ts +2 -0
- package/dist/tests/feed-cron.test.d.ts.map +1 -0
- package/dist/tests/feed-cron.test.js +78 -0
- package/dist/tests/feed-cron.test.js.map +1 -0
- package/dist/tests/feed-selfcheck.test.d.ts +2 -0
- package/dist/tests/feed-selfcheck.test.d.ts.map +1 -0
- package/dist/tests/feed-selfcheck.test.js +118 -0
- package/dist/tests/feed-selfcheck.test.js.map +1 -0
- package/dist/tests/installer.test.js +3 -1
- package/dist/tests/installer.test.js.map +1 -1
- package/dist/tests/integration.test.js +211 -1
- package/dist/tests/integration.test.js.map +1 -1
- package/dist/tests/runtime-cloud.test.js +30 -2
- package/dist/tests/runtime-cloud.test.js.map +1 -1
- package/dist/tests/smoke.test.js +141 -7
- package/dist/tests/smoke.test.js.map +1 -1
- package/docs/hermes.md +70 -0
- package/package.json +1 -1
- package/skills/agentguard/README.md +12 -0
- package/skills/agentguard/SKILL.md +104 -3
- package/skills/agentguard/hermes-hooks.yaml +31 -0
- package/skills/agentguard/package.json +1 -1
- package/skills/agentguard/scripts/auto-scan.js +3 -2
- package/skills/agentguard/scripts/hermes-hook.js +201 -0
package/dist/cloud/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AgentGuardCloudClient = void 0;
|
|
3
|
+
exports.CloudRequestError = exports.AgentGuardCloudClient = void 0;
|
|
4
4
|
const config_js_1 = require("../config.js");
|
|
5
5
|
const redaction_js_1 = require("../runtime/redaction.js");
|
|
6
6
|
const audit_js_1 = require("../runtime/audit.js");
|
|
@@ -48,6 +48,54 @@ class AgentGuardCloudClient {
|
|
|
48
48
|
});
|
|
49
49
|
return body.data.approvalId || null;
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Pull threat-feed advisories newer than `since`. Returns null when the
|
|
53
|
+
* cloud doesn't expose the endpoint yet (404) — callers should treat null
|
|
54
|
+
* as "no new advisories" rather than an error, so the subscribe command
|
|
55
|
+
* works against older AgentGuard Cloud versions too.
|
|
56
|
+
*/
|
|
57
|
+
async pullAdvisories(since) {
|
|
58
|
+
const params = new URLSearchParams();
|
|
59
|
+
if (since)
|
|
60
|
+
params.set('since', since);
|
|
61
|
+
const qs = params.toString();
|
|
62
|
+
const path = `/api/v1/feed/advisories${qs ? `?${qs}` : ''}`;
|
|
63
|
+
try {
|
|
64
|
+
const body = await this.request(path);
|
|
65
|
+
return body.data.advisories ?? [];
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
if (err instanceof CloudRequestError && err.status === 404) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Report the outcome of a single advisory self-check. Matches paths are
|
|
76
|
+
* redacted by the caller before they get here. Tolerates 404 so subscribe
|
|
77
|
+
* still completes locally even if the report sink is absent server-side.
|
|
78
|
+
*/
|
|
79
|
+
async reportSelfCheck(advisoryId, matches, options = {}) {
|
|
80
|
+
this.requireApiKey();
|
|
81
|
+
try {
|
|
82
|
+
await this.request('/api/v1/feed/self-check-report', {
|
|
83
|
+
method: 'POST',
|
|
84
|
+
body: JSON.stringify({
|
|
85
|
+
advisoryId,
|
|
86
|
+
matches,
|
|
87
|
+
elapsedMs: options.elapsedMs,
|
|
88
|
+
warnings: options.warnings,
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
if (err instanceof CloudRequestError && err.status === 404) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
throw err;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
51
99
|
async request(path, init = {}) {
|
|
52
100
|
const response = await fetch(`${this.cloudUrl}${path}`, {
|
|
53
101
|
...init,
|
|
@@ -60,7 +108,7 @@ class AgentGuardCloudClient {
|
|
|
60
108
|
});
|
|
61
109
|
const body = (await response.json().catch(() => null));
|
|
62
110
|
if (!response.ok || !body?.success) {
|
|
63
|
-
throw new
|
|
111
|
+
throw new CloudRequestError(response.status, path);
|
|
64
112
|
}
|
|
65
113
|
return body;
|
|
66
114
|
}
|
|
@@ -71,6 +119,17 @@ class AgentGuardCloudClient {
|
|
|
71
119
|
}
|
|
72
120
|
}
|
|
73
121
|
exports.AgentGuardCloudClient = AgentGuardCloudClient;
|
|
122
|
+
class CloudRequestError extends Error {
|
|
123
|
+
status;
|
|
124
|
+
path;
|
|
125
|
+
constructor(status, path) {
|
|
126
|
+
super(`AgentGuard Cloud request failed: ${status} (${path})`);
|
|
127
|
+
this.status = status;
|
|
128
|
+
this.path = path;
|
|
129
|
+
this.name = 'CloudRequestError';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.CloudRequestError = CloudRequestError;
|
|
74
133
|
function sanitizeActionRequest(action) {
|
|
75
134
|
return {
|
|
76
135
|
sessionId: (0, redaction_js_1.redactPreview)(action.sessionId, 160),
|
package/dist/cloud/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/cloud/client.ts"],"names":[],"mappings":";;;AAAA,4CAAiD;AAQjD,0DAAwE;AACxE,kDAAsD;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/cloud/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAKD,wBAAgB,kBAAkB,IAAI,eAAe,CASpD;AAED,wBAAgB,aAAa,IAAI,gBAAgB,CAUhD;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAKtD;AAED,wBAAgB,YAAY,IAAI,gBAAgB,CAQ/C;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CAkB7C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAKzD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAW7F;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,YAAY,CAAC;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAKD,wBAAgB,kBAAkB,IAAI,eAAe,CASpD;AAED,wBAAgB,aAAa,IAAI,gBAAgB,CAUhD;AAED,wBAAgB,oBAAoB,IAAI,eAAe,CAKtD;AAED,wBAAgB,YAAY,IAAI,gBAAgB,CAQ/C;AAED,wBAAgB,UAAU,IAAI,gBAAgB,CAkB7C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAKzD;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAW7F;AAED,wBAAgB,UAAU,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD;AAID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAevD"}
|
package/dist/config.js
CHANGED
|
@@ -101,6 +101,7 @@ function validateApiKey(apiKey) {
|
|
|
101
101
|
throw new Error('Invalid AgentGuard API key format. Expected an ag_live_ key.');
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
+
const LOOPBACK_HOSTS = new Set(['localhost', '127.0.0.1', '::1', '0.0.0.0']);
|
|
104
105
|
function normalizeCloudUrl(value) {
|
|
105
106
|
const normalized = value.replace(/\/+$/, '');
|
|
106
107
|
let parsed;
|
|
@@ -110,8 +111,9 @@ function normalizeCloudUrl(value) {
|
|
|
110
111
|
catch {
|
|
111
112
|
throw new Error('Invalid Cloud URL.');
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
const isLoopback = LOOPBACK_HOSTS.has(parsed.hostname);
|
|
115
|
+
if (parsed.protocol !== 'https:' && !(parsed.protocol === 'http:' && isLoopback)) {
|
|
116
|
+
throw new Error('Invalid Cloud URL. AgentGuard Cloud URLs must use https:// (http:// allowed only for loopback hosts).');
|
|
115
117
|
}
|
|
116
118
|
return normalized;
|
|
117
119
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;AA0BA,gDASC;AAED,sCAUC;AAED,oDAKC;AAED,oCAQC;AAED,gCAkBC;AAED,gCAKC;AAED,oCAWC;AAED,gCAIC;AAED,wCAIC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface OpenClawCronInstallResult {
|
|
2
|
+
name: string;
|
|
3
|
+
schedule: string;
|
|
4
|
+
created: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface OpenClawGatewayOptions {
|
|
7
|
+
host?: string;
|
|
8
|
+
port?: number;
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
request?: (method: string, params: unknown) => Promise<unknown>;
|
|
11
|
+
}
|
|
12
|
+
interface OpenClawCronJob {
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseIntervalMinutes(value: string): number;
|
|
17
|
+
export declare function installOpenClawThreatFeedCron(options: {
|
|
18
|
+
name: string;
|
|
19
|
+
intervalMinutes: number;
|
|
20
|
+
force: boolean;
|
|
21
|
+
}, gateway?: OpenClawGatewayOptions): Promise<OpenClawCronInstallResult>;
|
|
22
|
+
export declare function extractOpenClawCronJobs(value: unknown): OpenClawCronJob[];
|
|
23
|
+
export declare function openClawGatewayRequest(method: string, params: unknown, options?: OpenClawGatewayOptions): Promise<unknown>;
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/feed/cron.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACjE;AAED,UAAU,eAAe;IACvB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,wBAAsB,6BAA6B,CACjD,OAAO,EAAE;IACP,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;CAChB,EACD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,yBAAyB,CAAC,CAyDpC;AAoBD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,EAAE,CAczE;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC,CA8ElB"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseIntervalMinutes = parseIntervalMinutes;
|
|
7
|
+
exports.installOpenClawThreatFeedCron = installOpenClawThreatFeedCron;
|
|
8
|
+
exports.extractOpenClawCronJobs = extractOpenClawCronJobs;
|
|
9
|
+
exports.openClawGatewayRequest = openClawGatewayRequest;
|
|
10
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
11
|
+
function parseIntervalMinutes(value) {
|
|
12
|
+
if (!/^\d+$/.test(value)) {
|
|
13
|
+
throw new Error('Invalid --interval-minutes. Use an integer between 1 and 59.');
|
|
14
|
+
}
|
|
15
|
+
const minutes = Number.parseInt(value, 10);
|
|
16
|
+
if (!Number.isInteger(minutes) || minutes < 1 || minutes > 59) {
|
|
17
|
+
throw new Error('Invalid --interval-minutes. Use an integer between 1 and 59.');
|
|
18
|
+
}
|
|
19
|
+
return minutes;
|
|
20
|
+
}
|
|
21
|
+
async function installOpenClawThreatFeedCron(options, gateway = {}) {
|
|
22
|
+
const schedule = `*/${options.intervalMinutes} * * * *`;
|
|
23
|
+
const existing = await findOpenClawCronJobsByName(options.name, gateway);
|
|
24
|
+
if (existing.length > 0 && !options.force) {
|
|
25
|
+
return {
|
|
26
|
+
name: options.name,
|
|
27
|
+
schedule,
|
|
28
|
+
created: false,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const description = `AgentGuard Cloud threat feed self-check every ${options.intervalMinutes} minute${options.intervalMinutes === 1 ? '' : 's'}`;
|
|
32
|
+
const message = [
|
|
33
|
+
'Run `agentguard subscribe --json --cron-run`.',
|
|
34
|
+
'',
|
|
35
|
+
'Rules:',
|
|
36
|
+
'- If the JSON field `hardFailures` is greater than 0, output a short error summary and do not send a threat-match notification.',
|
|
37
|
+
'- If the JSON field `shouldNotify` is true, send `notification.body` exactly as-is using the current session notification context.',
|
|
38
|
+
'- If `shouldNotify` is false, output "skipped" and finish without sending any message.',
|
|
39
|
+
'- If the command fails or the JSON cannot be parsed, output a short error summary and do not send a threat-match notification.',
|
|
40
|
+
'',
|
|
41
|
+
'Follow these rules exactly.',
|
|
42
|
+
].join('\n');
|
|
43
|
+
if (existing.length > 0) {
|
|
44
|
+
await removeOpenClawCronJobs(existing, gateway);
|
|
45
|
+
}
|
|
46
|
+
await openClawGatewayRequest('cron.add', [
|
|
47
|
+
{
|
|
48
|
+
name: options.name,
|
|
49
|
+
description,
|
|
50
|
+
enabled: true,
|
|
51
|
+
schedule: {
|
|
52
|
+
kind: 'every',
|
|
53
|
+
everyMs: options.intervalMinutes * 60 * 1000,
|
|
54
|
+
},
|
|
55
|
+
sessionTarget: 'isolated',
|
|
56
|
+
payload: {
|
|
57
|
+
kind: 'agentTurn',
|
|
58
|
+
message,
|
|
59
|
+
timeoutSeconds: 300,
|
|
60
|
+
},
|
|
61
|
+
delivery: {
|
|
62
|
+
mode: 'none',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
], gateway);
|
|
66
|
+
return {
|
|
67
|
+
name: options.name,
|
|
68
|
+
schedule,
|
|
69
|
+
created: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async function findOpenClawCronJobsByName(name, gateway) {
|
|
73
|
+
const listed = await openClawGatewayRequest('cron.list', {}, gateway).catch(() => null);
|
|
74
|
+
return extractOpenClawCronJobs(listed).filter((job) => job.name === name);
|
|
75
|
+
}
|
|
76
|
+
async function removeOpenClawCronJobs(jobs, gateway) {
|
|
77
|
+
for (const job of jobs) {
|
|
78
|
+
if (!job.id)
|
|
79
|
+
continue;
|
|
80
|
+
await openClawGatewayRequest('cron.remove', { jobId: job.id }, gateway);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function extractOpenClawCronJobs(value) {
|
|
84
|
+
if (Array.isArray(value))
|
|
85
|
+
return value;
|
|
86
|
+
if (!value || typeof value !== 'object')
|
|
87
|
+
return [];
|
|
88
|
+
const obj = value;
|
|
89
|
+
for (const candidate of [obj.jobs, obj.cronJobs, obj.result, obj.data]) {
|
|
90
|
+
const jobs = extractOpenClawCronJobs(candidate);
|
|
91
|
+
if (jobs.length > 0)
|
|
92
|
+
return jobs;
|
|
93
|
+
}
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
function openClawGatewayRequest(method, params, options = {}) {
|
|
97
|
+
if (options.request) {
|
|
98
|
+
return options.request(method, params);
|
|
99
|
+
}
|
|
100
|
+
const payload = JSON.stringify({
|
|
101
|
+
jsonrpc: '2.0',
|
|
102
|
+
method,
|
|
103
|
+
params,
|
|
104
|
+
id: 1,
|
|
105
|
+
});
|
|
106
|
+
const host = options.host ?? '127.0.0.1';
|
|
107
|
+
const port = options.port ?? 18789;
|
|
108
|
+
const timeoutMs = options.timeoutMs ?? 5000;
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
let settled = false;
|
|
111
|
+
const fail = (err) => {
|
|
112
|
+
if (settled)
|
|
113
|
+
return;
|
|
114
|
+
settled = true;
|
|
115
|
+
reject(err);
|
|
116
|
+
};
|
|
117
|
+
const succeed = (value) => {
|
|
118
|
+
if (settled)
|
|
119
|
+
return;
|
|
120
|
+
settled = true;
|
|
121
|
+
resolve(value);
|
|
122
|
+
};
|
|
123
|
+
const req = node_http_1.default.request({
|
|
124
|
+
hostname: host,
|
|
125
|
+
port,
|
|
126
|
+
path: '/',
|
|
127
|
+
method: 'POST',
|
|
128
|
+
headers: {
|
|
129
|
+
'Content-Type': 'application/json',
|
|
130
|
+
'Content-Length': Buffer.byteLength(payload),
|
|
131
|
+
},
|
|
132
|
+
}, (res) => {
|
|
133
|
+
let data = '';
|
|
134
|
+
res.setEncoding('utf8');
|
|
135
|
+
res.on('error', (err) => {
|
|
136
|
+
fail(new Error(`OpenClaw Gateway ${method} response failed: ${err.message}`));
|
|
137
|
+
});
|
|
138
|
+
res.on('data', (chunk) => {
|
|
139
|
+
data += chunk;
|
|
140
|
+
});
|
|
141
|
+
res.on('end', () => {
|
|
142
|
+
let parsed;
|
|
143
|
+
try {
|
|
144
|
+
parsed = data ? JSON.parse(data) : null;
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
fail(new Error(`OpenClaw Gateway returned non-JSON response: ${data}`));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (parsed?.error) {
|
|
151
|
+
fail(new Error(`OpenClaw Gateway ${method} failed: ${parsed.error.message ?? JSON.stringify(parsed.error)}`));
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (res.statusCode && res.statusCode >= 400) {
|
|
155
|
+
fail(new Error(`OpenClaw Gateway ${method} failed with HTTP ${res.statusCode}`));
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
succeed(parsed?.result ?? parsed);
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
req.on('error', (err) => {
|
|
162
|
+
fail(new Error(`Could not reach OpenClaw Gateway at ${host}:${port}: ${err.message}`));
|
|
163
|
+
});
|
|
164
|
+
req.setTimeout(timeoutMs, () => {
|
|
165
|
+
const err = new Error(`OpenClaw Gateway ${method} request timed out after ${timeoutMs}ms`);
|
|
166
|
+
fail(err);
|
|
167
|
+
req.destroy(err);
|
|
168
|
+
});
|
|
169
|
+
req.write(payload);
|
|
170
|
+
req.end();
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/feed/cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-check engine — runs a single threat-feed advisory against the locally
|
|
3
|
+
* installed skills / plugins / MCP servers and reports which artifacts match.
|
|
4
|
+
*
|
|
5
|
+
* Designed to be cheap (read-only filesystem ops, hashing only when an
|
|
6
|
+
* advisory actually asks for a hash) and never crash on a single bad artifact.
|
|
7
|
+
*/
|
|
8
|
+
import type { Advisory, SelfCheckResult } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default search locations for each ecosystem.
|
|
11
|
+
*
|
|
12
|
+
* Skill locations cover the four agent frameworks that use the agentskills.io
|
|
13
|
+
* SKILL.md standard: Claude Code, OpenClaw, Hermes Agent, Cursor (project
|
|
14
|
+
* scope only — caller can supply extra roots). MCP server locations cover
|
|
15
|
+
* Claude Code's `~/.claude.json` and Codex's `~/.codex/config.toml` install
|
|
16
|
+
* conventions, but inspection of those is config-aware and lives elsewhere.
|
|
17
|
+
*/
|
|
18
|
+
export declare const DEFAULT_SKILL_ROOTS: string[];
|
|
19
|
+
export interface RunSelfCheckOptions {
|
|
20
|
+
/** Override the default per-ecosystem search roots. */
|
|
21
|
+
skillRoots?: string[];
|
|
22
|
+
/** Cap on hashing work: skill dirs beyond this count are skipped. */
|
|
23
|
+
maxArtifacts?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Run one advisory against the local environment. Never throws — failures
|
|
27
|
+
* become warnings on the result so the caller can keep iterating advisories.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runSelfCheckForAdvisory(advisory: Advisory, options?: RunSelfCheckOptions): Promise<SelfCheckResult>;
|
|
30
|
+
export declare function safeRegexTest(pattern: string, body: string): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Simple glob match supporting `*` as a single-segment wildcard. Sufficient
|
|
33
|
+
* for `slack-webhook-*` style advisories without pulling in a glob lib.
|
|
34
|
+
*/
|
|
35
|
+
export declare function globMatch(pattern: string, value: string): boolean;
|
|
36
|
+
//# sourceMappingURL=selfcheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selfcheck.d.ts","sourceRoot":"","sources":["../../src/feed/selfcheck.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EACV,QAAQ,EAGR,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,UAK/B,CAAC;AAEF,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,QAAQ,EAClB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,eAAe,CAAC,CAqC1B;AAgGD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBpE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOjE"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Self-check engine — runs a single threat-feed advisory against the locally
|
|
4
|
+
* installed skills / plugins / MCP servers and reports which artifacts match.
|
|
5
|
+
*
|
|
6
|
+
* Designed to be cheap (read-only filesystem ops, hashing only when an
|
|
7
|
+
* advisory actually asks for a hash) and never crash on a single bad artifact.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.DEFAULT_SKILL_ROOTS = void 0;
|
|
11
|
+
exports.runSelfCheckForAdvisory = runSelfCheckForAdvisory;
|
|
12
|
+
exports.safeRegexTest = safeRegexTest;
|
|
13
|
+
exports.globMatch = globMatch;
|
|
14
|
+
const node_fs_1 = require("node:fs");
|
|
15
|
+
const promises_1 = require("node:fs/promises");
|
|
16
|
+
const node_os_1 = require("node:os");
|
|
17
|
+
const node_path_1 = require("node:path");
|
|
18
|
+
const hash_js_1 = require("../utils/hash.js");
|
|
19
|
+
/**
|
|
20
|
+
* Default search locations for each ecosystem.
|
|
21
|
+
*
|
|
22
|
+
* Skill locations cover the four agent frameworks that use the agentskills.io
|
|
23
|
+
* SKILL.md standard: Claude Code, OpenClaw, Hermes Agent, Cursor (project
|
|
24
|
+
* scope only — caller can supply extra roots). MCP server locations cover
|
|
25
|
+
* Claude Code's `~/.claude.json` and Codex's `~/.codex/config.toml` install
|
|
26
|
+
* conventions, but inspection of those is config-aware and lives elsewhere.
|
|
27
|
+
*/
|
|
28
|
+
exports.DEFAULT_SKILL_ROOTS = [
|
|
29
|
+
(0, node_path_1.join)((0, node_os_1.homedir)(), '.claude', 'skills'),
|
|
30
|
+
(0, node_path_1.join)((0, node_os_1.homedir)(), '.openclaw', 'skills'),
|
|
31
|
+
(0, node_path_1.join)((0, node_os_1.homedir)(), '.openclaw', 'workspace', 'skills'),
|
|
32
|
+
(0, node_path_1.join)((0, node_os_1.homedir)(), '.hermes', 'skills'),
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Run one advisory against the local environment. Never throws — failures
|
|
36
|
+
* become warnings on the result so the caller can keep iterating advisories.
|
|
37
|
+
*/
|
|
38
|
+
async function runSelfCheckForAdvisory(advisory, options = {}) {
|
|
39
|
+
const startedAt = Date.now();
|
|
40
|
+
const matches = [];
|
|
41
|
+
const warnings = [];
|
|
42
|
+
if (advisory.withdrawnAt) {
|
|
43
|
+
return { advisoryId: advisory.id, matchedArtifacts: [], elapsedMs: 0, warnings };
|
|
44
|
+
}
|
|
45
|
+
if (advisory.ecosystem !== 'skill') {
|
|
46
|
+
warnings.push(`ecosystem "${advisory.ecosystem}" not implemented; only "skill" is supported in this build`);
|
|
47
|
+
return { advisoryId: advisory.id, matchedArtifacts: [], elapsedMs: Date.now() - startedAt, warnings };
|
|
48
|
+
}
|
|
49
|
+
const roots = options.skillRoots ?? exports.DEFAULT_SKILL_ROOTS;
|
|
50
|
+
const skillDirs = await listSkillDirs(roots);
|
|
51
|
+
const cap = options.maxArtifacts ?? 500;
|
|
52
|
+
const considered = skillDirs.slice(0, cap);
|
|
53
|
+
if (skillDirs.length > cap) {
|
|
54
|
+
warnings.push(`only checked first ${cap} of ${skillDirs.length} skill directories`);
|
|
55
|
+
}
|
|
56
|
+
for (const dir of considered) {
|
|
57
|
+
try {
|
|
58
|
+
const m = await matchSkillDir(dir, advisory.affected);
|
|
59
|
+
if (m)
|
|
60
|
+
matches.push(m);
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
warnings.push(`skipped ${dir}: ${err.message}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
advisoryId: advisory.id,
|
|
68
|
+
matchedArtifacts: matches,
|
|
69
|
+
elapsedMs: Date.now() - startedAt,
|
|
70
|
+
warnings,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Enumerate every immediate subdirectory of `roots` that contains a SKILL.md. */
|
|
74
|
+
async function listSkillDirs(roots) {
|
|
75
|
+
const found = [];
|
|
76
|
+
for (const root of roots) {
|
|
77
|
+
if (!(0, node_fs_1.existsSync)(root))
|
|
78
|
+
continue;
|
|
79
|
+
let entries;
|
|
80
|
+
try {
|
|
81
|
+
entries = await (0, promises_1.readdir)(root, { withFileTypes: true });
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
for (const entry of entries) {
|
|
87
|
+
if (!entry.isDirectory())
|
|
88
|
+
continue;
|
|
89
|
+
const skillPath = (0, node_path_1.join)(root, entry.name);
|
|
90
|
+
const manifest = (0, node_path_1.join)(skillPath, 'SKILL.md');
|
|
91
|
+
if ((0, node_fs_1.existsSync)(manifest))
|
|
92
|
+
found.push(skillPath);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return found;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Match one skill directory against an advisory's affected[] matchers.
|
|
99
|
+
* Returns the first match found (per matcher precedence: hash > regex > name).
|
|
100
|
+
* Returns null when nothing matched.
|
|
101
|
+
*/
|
|
102
|
+
async function matchSkillDir(skillDir, affected) {
|
|
103
|
+
const name = (0, node_path_1.basename)(skillDir);
|
|
104
|
+
const manifestPath = (0, node_path_1.join)(skillDir, 'SKILL.md');
|
|
105
|
+
// Canonical hash input: the SKILL.md content. The cloud publishes
|
|
106
|
+
// SKILL.md hashes (not directory rollups), so this is the field that
|
|
107
|
+
// must match server-side for `sha256` matchers to be meaningful.
|
|
108
|
+
let localHash = null;
|
|
109
|
+
const wantsHash = affected.some((m) => m.sha256);
|
|
110
|
+
if (wantsHash && (0, node_fs_1.existsSync)(manifestPath)) {
|
|
111
|
+
try {
|
|
112
|
+
localHash = await (0, hash_js_1.hashFile)(manifestPath);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
localHash = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Regex matching needs the manifest body — only read if some matcher asks.
|
|
119
|
+
let body = null;
|
|
120
|
+
const wantsBody = affected.some((m) => m.bodyRegex);
|
|
121
|
+
if (wantsBody) {
|
|
122
|
+
try {
|
|
123
|
+
body = await (0, promises_1.readFile)(manifestPath, 'utf8');
|
|
124
|
+
// Cap body length to keep regex evaluation bounded.
|
|
125
|
+
if (body.length > MAX_BODY_BYTES)
|
|
126
|
+
body = body.slice(0, MAX_BODY_BYTES);
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
body = '';
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
for (const matcher of affected) {
|
|
133
|
+
if (matcher.sha256 && localHash && matcher.sha256.toLowerCase() === localHash.toLowerCase()) {
|
|
134
|
+
return { path: skillDir, matchedBy: 'sha256', hash: localHash };
|
|
135
|
+
}
|
|
136
|
+
if (matcher.bodyRegex && body !== null) {
|
|
137
|
+
if (safeRegexTest(matcher.bodyRegex, body)) {
|
|
138
|
+
return { path: skillDir, matchedBy: 'bodyRegex' };
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (matcher.namePattern && globMatch(matcher.namePattern, name)) {
|
|
142
|
+
return { path: skillDir, matchedBy: 'namePattern' };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Defense against catastrophic backtracking and malformed regex coming
|
|
149
|
+
* from upstream advisory data:
|
|
150
|
+
* - cap the pattern length
|
|
151
|
+
* - reject patterns with obvious nested-quantifier shapes that explode
|
|
152
|
+
* under ReDoS (e.g. `(.+)+`, `(a*)*`, `(a|a)*`)
|
|
153
|
+
* - swallow compile errors silently (treated as "no match")
|
|
154
|
+
*
|
|
155
|
+
* Node's RegExp has no built-in timeout; the cheap-but-effective fix is
|
|
156
|
+
* to bound both the pattern and the body. We accept a slight false-negative
|
|
157
|
+
* rate over freezing on a hostile feed.
|
|
158
|
+
*/
|
|
159
|
+
const MAX_REGEX_LEN = 256;
|
|
160
|
+
const MAX_BODY_BYTES = 256 * 1024;
|
|
161
|
+
const CATASTROPHIC = [
|
|
162
|
+
/\([^)]*[+*]\)[+*]/, // nested quantifier: (x+)+
|
|
163
|
+
/\(([^|()]+\|)+\1\)[+*]/, // alternation duplicate: (a|a)*
|
|
164
|
+
];
|
|
165
|
+
function safeRegexTest(pattern, body) {
|
|
166
|
+
if (typeof pattern !== 'string' || pattern.length === 0)
|
|
167
|
+
return false;
|
|
168
|
+
if (pattern.length > MAX_REGEX_LEN)
|
|
169
|
+
return false;
|
|
170
|
+
for (const danger of CATASTROPHIC) {
|
|
171
|
+
if (danger.test(pattern))
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
let re;
|
|
175
|
+
try {
|
|
176
|
+
re = new RegExp(pattern);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
return re.test(body);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Simple glob match supporting `*` as a single-segment wildcard. Sufficient
|
|
190
|
+
* for `slack-webhook-*` style advisories without pulling in a glob lib.
|
|
191
|
+
*/
|
|
192
|
+
function globMatch(pattern, value) {
|
|
193
|
+
const re = new RegExp('^' +
|
|
194
|
+
pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '[^/]*') +
|
|
195
|
+
'$');
|
|
196
|
+
return re.test(value);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=selfcheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selfcheck.js","sourceRoot":"","sources":["../../src/feed/selfcheck.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local feed-subscription state I/O.
|
|
3
|
+
*
|
|
4
|
+
* Persisted at `~/.agentguard/feed-state.json` so the `subscribe` command
|
|
5
|
+
* doesn't re-process the same advisory across invocations / cron ticks.
|
|
6
|
+
*
|
|
7
|
+
* Kept tiny (single JSON object) on purpose — bigger ledgers go through the
|
|
8
|
+
* audit log path, not here.
|
|
9
|
+
*/
|
|
10
|
+
import type { FeedState } from './types.js';
|
|
11
|
+
export declare function loadFeedState(): FeedState;
|
|
12
|
+
export declare function saveFeedState(state: FeedState): void;
|
|
13
|
+
export declare function markAdvisorySeen(state: FeedState, advisoryId: string): FeedState;
|
|
14
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/feed/state.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAQ5C,wBAAgB,aAAa,IAAI,SAAS,CAezC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAQpD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAOhF"}
|