podwatch 1.0.2
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 +28 -0
- package/README.md +92 -0
- package/bin/podwatch.js +10 -0
- package/dist/classifier.d.ts +22 -0
- package/dist/classifier.d.ts.map +1 -0
- package/dist/classifier.js +157 -0
- package/dist/classifier.js.map +1 -0
- package/dist/hooks/cost.d.ts +26 -0
- package/dist/hooks/cost.d.ts.map +1 -0
- package/dist/hooks/cost.js +107 -0
- package/dist/hooks/cost.js.map +1 -0
- package/dist/hooks/lifecycle.d.ts +16 -0
- package/dist/hooks/lifecycle.d.ts.map +1 -0
- package/dist/hooks/lifecycle.js +273 -0
- package/dist/hooks/lifecycle.js.map +1 -0
- package/dist/hooks/security.d.ts +19 -0
- package/dist/hooks/security.d.ts.map +1 -0
- package/dist/hooks/security.js +128 -0
- package/dist/hooks/security.js.map +1 -0
- package/dist/hooks/sessions.d.ts +10 -0
- package/dist/hooks/sessions.d.ts.map +1 -0
- package/dist/hooks/sessions.js +53 -0
- package/dist/hooks/sessions.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +120 -0
- package/dist/index.js.map +1 -0
- package/dist/redact.d.ts +35 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +372 -0
- package/dist/redact.js.map +1 -0
- package/dist/scanner.d.ts +27 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +117 -0
- package/dist/scanner.js.map +1 -0
- package/dist/transmitter.d.ts +58 -0
- package/dist/transmitter.d.ts.map +1 -0
- package/dist/transmitter.js +654 -0
- package/dist/transmitter.js.map +1 -0
- package/dist/types.d.ts +116 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/updater.d.ts +168 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +579 -0
- package/dist/updater.js.map +1 -0
- package/lib/installer.js +599 -0
- package/openclaw.plugin.json +59 -0
- package/package.json +56 -0
- package/skills/podwatch/SKILL.md +112 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Podwatch Plugin — OpenClaw cost monitoring, budget enforcement, and security alerts.
|
|
4
|
+
*
|
|
5
|
+
* Registers hook handlers and subscribes to diagnostic events to capture:
|
|
6
|
+
* - Cost/token data per LLM call (onDiagnosticEvent → model.usage)
|
|
7
|
+
* - Tool security scanning + budget blocking (before_tool_call)
|
|
8
|
+
* - Tool latency + success/failure (after_tool_call)
|
|
9
|
+
* - Session lifecycle (session_start, session_end)
|
|
10
|
+
* - Context pressure (before_compaction)
|
|
11
|
+
* - Pulse alive-ping + skill/plugin scanning (register())
|
|
12
|
+
* - Graceful shutdown (gateway_stop)
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.default = register;
|
|
16
|
+
const cost_js_1 = require("./hooks/cost.js");
|
|
17
|
+
const security_js_1 = require("./hooks/security.js");
|
|
18
|
+
const sessions_js_1 = require("./hooks/sessions.js");
|
|
19
|
+
const lifecycle_js_1 = require("./hooks/lifecycle.js");
|
|
20
|
+
const transmitter_js_1 = require("./transmitter.js");
|
|
21
|
+
const updater_js_1 = require("./updater.js");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Plugin registration
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const DEBUG = !!process.env.PODWATCH_DEBUG;
|
|
26
|
+
/**
|
|
27
|
+
* Redact sensitive fields from an object for safe debug logging.
|
|
28
|
+
* Returns a shallow copy with secret values replaced by '***'.
|
|
29
|
+
*/
|
|
30
|
+
function redactForLog(obj) {
|
|
31
|
+
if (!obj || typeof obj !== "object")
|
|
32
|
+
return obj;
|
|
33
|
+
const SENSITIVE_KEYS = ["apiKey", "apiSecret", "secret", "token", "password", "key"];
|
|
34
|
+
const redacted = { ...obj };
|
|
35
|
+
for (const k of SENSITIVE_KEYS) {
|
|
36
|
+
if (k in redacted && redacted[k]) {
|
|
37
|
+
redacted[k] = "***";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return redacted;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* OpenClaw plugin entry point.
|
|
44
|
+
* Called by the Gateway when the plugin is loaded.
|
|
45
|
+
*/
|
|
46
|
+
function register(api) {
|
|
47
|
+
if (DEBUG) {
|
|
48
|
+
console.log("[podwatch:debug] register() called");
|
|
49
|
+
console.log("[podwatch:debug] api object keys:", Object.keys(api));
|
|
50
|
+
// Log only safe gateway config fields — never dump the full api.config
|
|
51
|
+
const safeConfigKeys = api.config
|
|
52
|
+
? { diagnostics: api.config.diagnostics, agents: api.config.agents ? "(present)" : "(absent)" }
|
|
53
|
+
: "(undefined)";
|
|
54
|
+
console.log("[podwatch:debug] api.config (safe fields):", JSON.stringify(safeConfigKeys, null, 2));
|
|
55
|
+
console.log("[podwatch:debug] api.pluginConfig:", JSON.stringify(redactForLog(api.pluginConfig ?? {}), null, 2));
|
|
56
|
+
console.log("[podwatch:debug] api.runtime keys:", api.runtime ? Object.keys(api.runtime) : "undefined");
|
|
57
|
+
}
|
|
58
|
+
const config = resolveConfig(api);
|
|
59
|
+
if (DEBUG) {
|
|
60
|
+
console.log("[podwatch:debug] Resolved config:", JSON.stringify(redactForLog(config), null, 2));
|
|
61
|
+
}
|
|
62
|
+
if (!config.apiKey) {
|
|
63
|
+
api.logger.error("[podwatch] No API key configured. Set it in plugins.entries.podwatch.config.apiKey");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Start the transmitter (batched HTTP to Podwatch cloud)
|
|
67
|
+
transmitter_js_1.transmitter.start({
|
|
68
|
+
apiKey: config.apiKey,
|
|
69
|
+
endpoint: config.endpoint ?? "https://podwatch.app/api",
|
|
70
|
+
batchSize: 50,
|
|
71
|
+
flushIntervalMs: 30_000,
|
|
72
|
+
});
|
|
73
|
+
// Check if diagnostics are enabled
|
|
74
|
+
const diagnosticsEnabled = api.config?.diagnostics?.enabled === true;
|
|
75
|
+
if (!diagnosticsEnabled) {
|
|
76
|
+
api.logger.warn("[podwatch] diagnostics.enabled is not set to true in gateway config. " +
|
|
77
|
+
"Cost tracking will not work. Enable it: diagnostics: { enabled: true }");
|
|
78
|
+
// POST setup warning to dashboard
|
|
79
|
+
transmitter_js_1.transmitter.enqueue({
|
|
80
|
+
type: "setup_warning",
|
|
81
|
+
message: "Enable diagnostics for cost tracking: set diagnostics.enabled: true in openclaw.json",
|
|
82
|
+
ts: Date.now(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// Register all hook handlers
|
|
86
|
+
(0, cost_js_1.registerCostHandler)(api, config, diagnosticsEnabled);
|
|
87
|
+
(0, security_js_1.registerSecurityHandlers)(api, config);
|
|
88
|
+
(0, sessions_js_1.registerSessionHandlers)(api);
|
|
89
|
+
(0, lifecycle_js_1.registerLifecycleHandlers)(api, config);
|
|
90
|
+
// Schedule non-blocking auto-update check (30s after boot, 24h cooldown)
|
|
91
|
+
// Auto-update is opt-in (default false) for supply chain security.
|
|
92
|
+
const currentVersion = api.version ?? "0.0.0";
|
|
93
|
+
const endpoint = config.endpoint ?? "https://podwatch.app/api";
|
|
94
|
+
(0, updater_js_1.scheduleUpdateCheck)(currentVersion, endpoint, api.logger, { autoUpdate: config.autoUpdate });
|
|
95
|
+
api.logger.info(`[podwatch] Plugin loaded (v${currentVersion}). Budget enforcement: ${config.enableBudgetEnforcement ? "ON" : "OFF"}, ` +
|
|
96
|
+
`Security alerts: ${config.enableSecurityAlerts ? "ON" : "OFF"}, ` +
|
|
97
|
+
`Diagnostics: ${diagnosticsEnabled ? "ON" : "OFF"}`);
|
|
98
|
+
}
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
// Config resolution
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
function resolveConfig(api) {
|
|
103
|
+
const pluginConfig = api.pluginConfig ?? {};
|
|
104
|
+
if (DEBUG) {
|
|
105
|
+
console.log("[podwatch:debug] resolveConfig() — raw pluginConfig:", JSON.stringify(redactForLog(pluginConfig), null, 2));
|
|
106
|
+
console.log("[podwatch:debug] resolveConfig() — env PODWATCH_API_KEY set:", !!process.env.PODWATCH_API_KEY);
|
|
107
|
+
console.log("[podwatch:debug] resolveConfig() — env PODWATCH_ENDPOINT:", process.env.PODWATCH_ENDPOINT ?? "(unset)");
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
apiKey: pluginConfig.apiKey ?? process.env.PODWATCH_API_KEY ?? "",
|
|
111
|
+
endpoint: pluginConfig.endpoint ?? process.env.PODWATCH_ENDPOINT,
|
|
112
|
+
enableBudgetEnforcement: pluginConfig.enableBudgetEnforcement ?? true,
|
|
113
|
+
enableSecurityAlerts: pluginConfig.enableSecurityAlerts ?? true,
|
|
114
|
+
autoUpdate: pluginConfig.autoUpdate ?? false,
|
|
115
|
+
// Backward compat: fall back to heartbeatIntervalMs if pulseIntervalMs not set
|
|
116
|
+
pulseIntervalMs: pluginConfig.pulseIntervalMs ?? pluginConfig.heartbeatIntervalMs ?? 300_000,
|
|
117
|
+
scanIntervalMs: pluginConfig.scanIntervalMs ?? 21_600_000, // 6 hours
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Param redaction — strips sensitive values before transmitting to dashboard.
|
|
3
|
+
*
|
|
4
|
+
* Keeps structure but replaces values of sensitive keys with "[REDACTED]".
|
|
5
|
+
* Truncates long string values to prevent bloated payloads.
|
|
6
|
+
*
|
|
7
|
+
* Returns { result, redactedCount } so callers can track how many fields
|
|
8
|
+
* were scrubbed (heavy redaction > 3 feeds into risk classification).
|
|
9
|
+
*/
|
|
10
|
+
declare const SENSITIVE_KEYS: Set<string>;
|
|
11
|
+
declare const SENSITIVE_VALUE_PATTERNS: RegExp[];
|
|
12
|
+
/**
|
|
13
|
+
* Calculate Shannon entropy of a string.
|
|
14
|
+
* Higher values indicate more randomness (potential secrets).
|
|
15
|
+
*/
|
|
16
|
+
declare function shannonEntropy(s: string): number;
|
|
17
|
+
declare function looksLikeToken(s: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Length-based entropy thresholds.
|
|
20
|
+
* Short high-entropy strings (20-32 chars) are often UUIDs/hashes, not secrets.
|
|
21
|
+
* Longer strings need less entropy to be suspicious.
|
|
22
|
+
*/
|
|
23
|
+
declare function getEntropyThreshold(length: number): number;
|
|
24
|
+
declare function isHighEntropySecret(s: string): boolean;
|
|
25
|
+
export interface RedactResult {
|
|
26
|
+
result: Record<string, unknown>;
|
|
27
|
+
redactedCount: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Redact sensitive values from tool call params.
|
|
31
|
+
* Returns the scrubbed object and a count of how many values were redacted.
|
|
32
|
+
*/
|
|
33
|
+
export declare function redactParams(params: Record<string, unknown>): RedactResult;
|
|
34
|
+
export { shannonEntropy, looksLikeToken, isHighEntropySecret, getEntropyThreshold, SENSITIVE_VALUE_PATTERNS, SENSITIVE_KEYS };
|
|
35
|
+
//# sourceMappingURL=redact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,QAAA,MAAM,cAAc,aAgFlB,CAAC;AAMH,QAAA,MAAM,wBAAwB,EAAE,MAAM,EAmGrC,CAAC;AAMF;;;GAGG;AACH,iBAAS,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAYzC;AAcD,iBAAS,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAY1C;AAID;;;;GAIG;AACH,iBAAS,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAInD;AAED,iBAAS,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAI/C;AAaD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,aAAa,EAAE,MAAM,CAAC;CACvB;AA4CD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAK1E;AA+ED,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,cAAc,EAAE,CAAC"}
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Param redaction — strips sensitive values before transmitting to dashboard.
|
|
4
|
+
*
|
|
5
|
+
* Keeps structure but replaces values of sensitive keys with "[REDACTED]".
|
|
6
|
+
* Truncates long string values to prevent bloated payloads.
|
|
7
|
+
*
|
|
8
|
+
* Returns { result, redactedCount } so callers can track how many fields
|
|
9
|
+
* were scrubbed (heavy redaction > 3 feeds into risk classification).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.SENSITIVE_KEYS = exports.SENSITIVE_VALUE_PATTERNS = void 0;
|
|
13
|
+
exports.redactParams = redactParams;
|
|
14
|
+
exports.shannonEntropy = shannonEntropy;
|
|
15
|
+
exports.looksLikeToken = looksLikeToken;
|
|
16
|
+
exports.isHighEntropySecret = isHighEntropySecret;
|
|
17
|
+
exports.getEntropyThreshold = getEntropyThreshold;
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Sensitive key patterns (normalized: lowercase, no hyphens/underscores)
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
const SENSITIVE_KEYS = new Set([
|
|
22
|
+
// Original
|
|
23
|
+
"password",
|
|
24
|
+
"secret",
|
|
25
|
+
"token",
|
|
26
|
+
"apikey",
|
|
27
|
+
"api_key",
|
|
28
|
+
"authorization",
|
|
29
|
+
"credentials",
|
|
30
|
+
"private_key",
|
|
31
|
+
"privatekey",
|
|
32
|
+
"access_token",
|
|
33
|
+
"accesstoken",
|
|
34
|
+
"refresh_token",
|
|
35
|
+
"refreshtoken",
|
|
36
|
+
"client_secret",
|
|
37
|
+
"clientsecret",
|
|
38
|
+
"bearer",
|
|
39
|
+
"cookie",
|
|
40
|
+
"session_id",
|
|
41
|
+
"sessionid",
|
|
42
|
+
"passphrase",
|
|
43
|
+
// Encryption / signing
|
|
44
|
+
"encryptionkey",
|
|
45
|
+
"encryption_key",
|
|
46
|
+
"signingkey",
|
|
47
|
+
"signing_key",
|
|
48
|
+
"masterkey",
|
|
49
|
+
"master_key",
|
|
50
|
+
// Database
|
|
51
|
+
"databaseurl",
|
|
52
|
+
"database_url",
|
|
53
|
+
"dburl",
|
|
54
|
+
"db_url",
|
|
55
|
+
"dbpassword",
|
|
56
|
+
"db_password",
|
|
57
|
+
"connectionstring",
|
|
58
|
+
"connection_string",
|
|
59
|
+
// Communication / SMTP
|
|
60
|
+
"smtppassword",
|
|
61
|
+
"smtp_password",
|
|
62
|
+
"webhooksecret",
|
|
63
|
+
"webhook_secret",
|
|
64
|
+
// JWT / App
|
|
65
|
+
"jwtsecret",
|
|
66
|
+
"jwt_secret",
|
|
67
|
+
"appsecret",
|
|
68
|
+
"app_secret",
|
|
69
|
+
// Crypto primitives (when used as keys)
|
|
70
|
+
"hmac",
|
|
71
|
+
"nonce",
|
|
72
|
+
"salt",
|
|
73
|
+
// Provider-specific key names
|
|
74
|
+
"resendapikey",
|
|
75
|
+
"resend_api_key",
|
|
76
|
+
"inngestkey",
|
|
77
|
+
"inngest_signing_key",
|
|
78
|
+
"planetscaletoken",
|
|
79
|
+
"planetscale_token",
|
|
80
|
+
"railwaytoken",
|
|
81
|
+
"railway_token",
|
|
82
|
+
"renderkey",
|
|
83
|
+
"render_api_key",
|
|
84
|
+
"postmarktoken",
|
|
85
|
+
"postmark_server_token",
|
|
86
|
+
"postmark_api_token",
|
|
87
|
+
"lemonsqueezyapikey",
|
|
88
|
+
"lemon_squeezy_api_key",
|
|
89
|
+
"pineconeapikey",
|
|
90
|
+
"pinecone_api_key",
|
|
91
|
+
"weaviateapikey",
|
|
92
|
+
"weaviate_api_key",
|
|
93
|
+
"flyapitoken",
|
|
94
|
+
"fly_api_token",
|
|
95
|
+
]);
|
|
96
|
+
exports.SENSITIVE_KEYS = SENSITIVE_KEYS;
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Value-based patterns (regex detection on string values)
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
const SENSITIVE_VALUE_PATTERNS = [
|
|
101
|
+
// --- AI / LLM Providers ---
|
|
102
|
+
/^sk-[a-zA-Z0-9]{20,}/, // OpenAI keys
|
|
103
|
+
/sk-ant-api03-[a-zA-Z0-9_-]{93}AA/, // Anthropic API key
|
|
104
|
+
/sk-ant-admin01-[a-zA-Z0-9_-]{93}AA/, // Anthropic admin key
|
|
105
|
+
/AIza[0-9A-Za-z_-]{35}/, // Google/GCP API key
|
|
106
|
+
/GOCSPX-[a-zA-Z0-9_-]+/, // Google OAuth client secret
|
|
107
|
+
/^co-[a-zA-Z0-9]{40}$/, // Cohere API key
|
|
108
|
+
/^r8_[a-zA-Z0-9]{40}$/, // Replicate API key
|
|
109
|
+
/^hf_[a-zA-Z0-9]{34}$/, // HuggingFace token
|
|
110
|
+
// --- Auth / Identity Providers ---
|
|
111
|
+
/^sk_live_[a-zA-Z0-9]+/, // Clerk/Stripe live secret
|
|
112
|
+
/^pk_live_[a-zA-Z0-9]+/, // Clerk/Stripe live public
|
|
113
|
+
/^sk_test_[a-zA-Z0-9]+/, // Clerk/Stripe test secret
|
|
114
|
+
/^pk_test_[a-zA-Z0-9]+/, // Clerk/Stripe test public
|
|
115
|
+
/^sbp_[a-zA-Z0-9]+/, // Supabase project token
|
|
116
|
+
/^eyJ[a-zA-Z0-9._-]{50,}/, // JWT tokens (also catches Supabase service role JWTs)
|
|
117
|
+
// --- Cloud / Infrastructure ---
|
|
118
|
+
/^AKIA[A-Z0-9]{16}/, // AWS access key (permanent)
|
|
119
|
+
/^ASIA[A-Z0-9]{16}/, // AWS access key (temporary/STS)
|
|
120
|
+
/^ABIA[A-Z0-9]{16}/, // AWS access key (STS for billing)
|
|
121
|
+
/^vercel_[a-zA-Z0-9_]+/, // Vercel token
|
|
122
|
+
/^hvs\.[a-zA-Z0-9_-]+/, // Hashicorp Vault token
|
|
123
|
+
/^dp\.st\.[a-zA-Z0-9_-]+/, // Doppler service token
|
|
124
|
+
/[a-zA-Z0-9]{14}\.atlasv1\.[a-zA-Z0-9_-]{60,}/, // Terraform Cloud token
|
|
125
|
+
// --- Database / Connection Strings (CRITICAL) ---
|
|
126
|
+
/postgres(?:ql)?:\/\/[^:]+:[^@]+@[^\s]+/, // Postgres connection string
|
|
127
|
+
/mysql:\/\/[^:]+:[^@]+@[^\s]+/, // MySQL connection string
|
|
128
|
+
/mongodb(?:\+srv)?:\/\/[^:]+:[^@]+@[^\s]+/, // MongoDB connection string
|
|
129
|
+
/redis:\/\/[^:]+:[^@]+@[^\s]+/, // Redis connection string
|
|
130
|
+
/[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^:]+:[^@]+@/, // Any URI with embedded credentials
|
|
131
|
+
// --- Communication ---
|
|
132
|
+
/^xoxb-[0-9]+-[0-9A-Za-z]+/, // Slack bot token
|
|
133
|
+
/^xoxp-[0-9]+-[0-9A-Za-z]+/, // Slack user token
|
|
134
|
+
/^xapp-[0-9]+-[0-9A-Za-z]+/, // Slack app token
|
|
135
|
+
/^SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}$/, // SendGrid API key
|
|
136
|
+
/^SK[a-f0-9]{32}$/, // Twilio API key
|
|
137
|
+
/[0-9]+:AA[a-zA-Z0-9_-]{33}/, // Telegram bot token
|
|
138
|
+
// --- Package Registries ---
|
|
139
|
+
/^npm_[a-zA-Z0-9]{36}$/, // npm token
|
|
140
|
+
/^pypi-[a-zA-Z0-9_-]{100,}/, // PyPI token
|
|
141
|
+
// --- Secret Management ---
|
|
142
|
+
/^ops_eyJ[a-zA-Z0-9+/]{250,}={0,3}$/, // 1Password service token
|
|
143
|
+
/^A3-[A-Z0-9]{6}-[A-Z0-9]{6,11}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$/, // 1Password secret key
|
|
144
|
+
// --- Crypto ---
|
|
145
|
+
/^AGE-SECRET-KEY-1[A-Z0-9]{58}$/, // Age encryption key
|
|
146
|
+
// --- SSH / Certificates ---
|
|
147
|
+
/-----BEGIN\s+PRIVATE\s+KEY/, // PKCS8 generic
|
|
148
|
+
/-----BEGIN\s+RSA\s+PRIVATE\s+KEY/, // RSA
|
|
149
|
+
/-----BEGIN\s+OPENSSH\s+PRIVATE\s+KEY/, // OpenSSH
|
|
150
|
+
/-----BEGIN\s+EC\s+PRIVATE\s+KEY/, // EC
|
|
151
|
+
/-----BEGIN\s+DSA\s+PRIVATE\s+KEY/, // DSA
|
|
152
|
+
/-----BEGIN\s+ENCRYPTED\s+PRIVATE\s+KEY/, // Encrypted PKCS8
|
|
153
|
+
/-----BEGIN\s+CERTIFICATE/, // X.509 certificate
|
|
154
|
+
// --- Auth headers ---
|
|
155
|
+
/^Bearer\s+[a-zA-Z0-9._-]{20,}/i, // Bearer tokens
|
|
156
|
+
/^Basic\s+[a-zA-Z0-9+/=]{20,}/i, // Basic auth
|
|
157
|
+
// --- GitHub ---
|
|
158
|
+
/^ghp_[a-zA-Z0-9]{36,}/, // GitHub PAT
|
|
159
|
+
/^gho_[a-zA-Z0-9]{36,}/, // GitHub OAuth
|
|
160
|
+
/^ghs_[a-zA-Z0-9]{36,}/, // GitHub App installation
|
|
161
|
+
/^ghr_[a-zA-Z0-9]{36,}/, // GitHub refresh token
|
|
162
|
+
// --- Podwatch ---
|
|
163
|
+
/^pw_[a-zA-Z0-9]{20,}/, // Podwatch keys
|
|
164
|
+
// --- Tavily ---
|
|
165
|
+
/^tvly-[a-zA-Z0-9]{20,}/, // Tavily keys
|
|
166
|
+
// --- Discord ---
|
|
167
|
+
/[MN][A-Za-z0-9]{23,}\.[A-Za-z0-9_-]{6}\.[A-Za-z0-9_-]{27,}/, // Discord bot token
|
|
168
|
+
// --- Resend ---
|
|
169
|
+
/^re_[a-zA-Z0-9]{20,}/, // Resend API key
|
|
170
|
+
// --- PlanetScale ---
|
|
171
|
+
/^pscale_(?:tkn|pw|oauth)_[a-zA-Z0-9_-]{20,}/, // PlanetScale token/password
|
|
172
|
+
// --- Fly.io ---
|
|
173
|
+
/^fo1_[a-zA-Z0-9_-]{20,}/, // Fly.io token
|
|
174
|
+
// --- Render ---
|
|
175
|
+
/^rnd_[a-zA-Z0-9]{20,}/, // Render API key
|
|
176
|
+
// --- Inngest ---
|
|
177
|
+
/^signkey-[a-zA-Z0-9_-]{20,}/, // Inngest signing key
|
|
178
|
+
// --- Pinecone ---
|
|
179
|
+
/^pcsk_[a-zA-Z0-9_-]{20,}/, // Pinecone API key
|
|
180
|
+
];
|
|
181
|
+
exports.SENSITIVE_VALUE_PATTERNS = SENSITIVE_VALUE_PATTERNS;
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Shannon entropy for high-entropy catch-all
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
/**
|
|
186
|
+
* Calculate Shannon entropy of a string.
|
|
187
|
+
* Higher values indicate more randomness (potential secrets).
|
|
188
|
+
*/
|
|
189
|
+
function shannonEntropy(s) {
|
|
190
|
+
const freq = new Map();
|
|
191
|
+
for (const c of s) {
|
|
192
|
+
freq.set(c, (freq.get(c) ?? 0) + 1);
|
|
193
|
+
}
|
|
194
|
+
const len = s.length;
|
|
195
|
+
let entropy = 0;
|
|
196
|
+
for (const count of freq.values()) {
|
|
197
|
+
const p = count / len;
|
|
198
|
+
entropy -= p * Math.log2(p);
|
|
199
|
+
}
|
|
200
|
+
return entropy;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Heuristic: does this string look like a random token/secret?
|
|
204
|
+
* - No spaces
|
|
205
|
+
* - Primarily alphanumeric + limited special chars (-_=+/.)
|
|
206
|
+
* - Not a common word or path-like string
|
|
207
|
+
*/
|
|
208
|
+
const TOKEN_CHARS_RE = /^[a-zA-Z0-9_+/=.-]+$/;
|
|
209
|
+
const COMMON_WORD_RE = /^[a-z]+$/i; // pure alpha could be a word
|
|
210
|
+
const PATH_LIKE_RE = /^(\/[a-zA-Z0-9._-]+)+\/?$/; // e.g. /usr/bin/node
|
|
211
|
+
const HEX_LIKE_RE = /^(0x)?[0-9a-fA-F]+$/; // plain hex number
|
|
212
|
+
const URL_LIKE_NO_CREDS = /^https?:\/\/[^@]+$/; // URL without embedded creds
|
|
213
|
+
function looksLikeToken(s) {
|
|
214
|
+
// Must match token character set (no spaces, no weird chars)
|
|
215
|
+
if (!TOKEN_CHARS_RE.test(s))
|
|
216
|
+
return false;
|
|
217
|
+
// Skip pure alphabetic (could be a word/identifier)
|
|
218
|
+
if (COMMON_WORD_RE.test(s) && s.length < 40)
|
|
219
|
+
return false;
|
|
220
|
+
// Skip path-like strings
|
|
221
|
+
if (PATH_LIKE_RE.test(s))
|
|
222
|
+
return false;
|
|
223
|
+
// Skip plain hex numbers (hashes, IDs)
|
|
224
|
+
if (HEX_LIKE_RE.test(s) && s.length < 40)
|
|
225
|
+
return false;
|
|
226
|
+
// Skip normal URLs without credentials
|
|
227
|
+
if (URL_LIKE_NO_CREDS.test(s))
|
|
228
|
+
return false;
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
const ENTROPY_MIN_LENGTH = 20;
|
|
232
|
+
/**
|
|
233
|
+
* Length-based entropy thresholds.
|
|
234
|
+
* Short high-entropy strings (20-32 chars) are often UUIDs/hashes, not secrets.
|
|
235
|
+
* Longer strings need less entropy to be suspicious.
|
|
236
|
+
*/
|
|
237
|
+
function getEntropyThreshold(length) {
|
|
238
|
+
if (length <= 32)
|
|
239
|
+
return 4.8; // Short: stricter (avoid UUID false positives)
|
|
240
|
+
if (length <= 64)
|
|
241
|
+
return 4.5; // Medium: standard
|
|
242
|
+
return 4.2; // Long: slightly relaxed (long random tokens)
|
|
243
|
+
}
|
|
244
|
+
function isHighEntropySecret(s) {
|
|
245
|
+
if (s.length < ENTROPY_MIN_LENGTH)
|
|
246
|
+
return false;
|
|
247
|
+
if (!looksLikeToken(s))
|
|
248
|
+
return false;
|
|
249
|
+
return shannonEntropy(s) >= getEntropyThreshold(s.length);
|
|
250
|
+
}
|
|
251
|
+
// ---------------------------------------------------------------------------
|
|
252
|
+
// Constants
|
|
253
|
+
// ---------------------------------------------------------------------------
|
|
254
|
+
const MAX_VALUE_LENGTH = 500;
|
|
255
|
+
const REDACTED = "[REDACTED]";
|
|
256
|
+
// ---------------------------------------------------------------------------
|
|
257
|
+
// Redaction audit mode (opt-in via PODWATCH_REDACTION_AUDIT env var)
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
const REDACTION_AUDIT = !!process.env.PODWATCH_REDACTION_AUDIT;
|
|
260
|
+
/**
|
|
261
|
+
* Log fields that were NOT redacted so we can spot gaps.
|
|
262
|
+
* Shows field name + first 4 chars + entropy score without exposing actual values.
|
|
263
|
+
*/
|
|
264
|
+
function auditUnredactedFields(obj, prefix = '') {
|
|
265
|
+
if (!REDACTION_AUDIT)
|
|
266
|
+
return;
|
|
267
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
268
|
+
const fieldPath = prefix ? `${prefix}.${key}` : key;
|
|
269
|
+
if (typeof value === 'string') {
|
|
270
|
+
if (value !== REDACTED && !value.startsWith('[truncated]')) {
|
|
271
|
+
const preview = value.slice(0, 4);
|
|
272
|
+
const entropy = shannonEntropy(value).toFixed(2);
|
|
273
|
+
console.log(`[podwatch:audit] PASS field="${fieldPath}" preview="${preview}…" len=${value.length} entropy=${entropy}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
|
|
277
|
+
auditUnredactedFields(value, fieldPath);
|
|
278
|
+
}
|
|
279
|
+
else if (Array.isArray(value)) {
|
|
280
|
+
value.forEach((item, i) => {
|
|
281
|
+
if (typeof item === 'string' && item !== REDACTED) {
|
|
282
|
+
const preview = item.slice(0, 4);
|
|
283
|
+
const entropy = shannonEntropy(item).toFixed(2);
|
|
284
|
+
console.log(`[podwatch:audit] PASS field="${fieldPath}[${i}]" preview="${preview}…" len=${item.length} entropy=${entropy}`);
|
|
285
|
+
}
|
|
286
|
+
else if (item !== null && typeof item === 'object') {
|
|
287
|
+
auditUnredactedFields(item, `${fieldPath}[${i}]`);
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// Public API
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
/**
|
|
297
|
+
* Redact sensitive values from tool call params.
|
|
298
|
+
* Returns the scrubbed object and a count of how many values were redacted.
|
|
299
|
+
*/
|
|
300
|
+
function redactParams(params) {
|
|
301
|
+
const counter = { count: 0 };
|
|
302
|
+
const result = redactObject(params, 0, counter);
|
|
303
|
+
auditUnredactedFields(result);
|
|
304
|
+
return { result, redactedCount: counter.count };
|
|
305
|
+
}
|
|
306
|
+
// ---------------------------------------------------------------------------
|
|
307
|
+
// Internal helpers
|
|
308
|
+
// ---------------------------------------------------------------------------
|
|
309
|
+
function isSensitiveValue(value) {
|
|
310
|
+
if (SENSITIVE_VALUE_PATTERNS.some((p) => p.test(value)))
|
|
311
|
+
return true;
|
|
312
|
+
if (isHighEntropySecret(value))
|
|
313
|
+
return true;
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
function redactObject(obj, depth, counter) {
|
|
317
|
+
if (depth > 5)
|
|
318
|
+
return { "[truncated]": "nested too deep" };
|
|
319
|
+
const result = {};
|
|
320
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
321
|
+
const keyLower = key.toLowerCase().replace(/[-_]/g, "");
|
|
322
|
+
// Key-based redaction
|
|
323
|
+
if (SENSITIVE_KEYS.has(key.toLowerCase()) || SENSITIVE_KEYS.has(keyLower)) {
|
|
324
|
+
result[key] = REDACTED;
|
|
325
|
+
counter.count++;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
// Value-based redaction + truncation
|
|
329
|
+
if (typeof value === "string") {
|
|
330
|
+
if (isSensitiveValue(value)) {
|
|
331
|
+
result[key] = REDACTED;
|
|
332
|
+
counter.count++;
|
|
333
|
+
}
|
|
334
|
+
else if (value.length > MAX_VALUE_LENGTH) {
|
|
335
|
+
result[key] = value.slice(0, MAX_VALUE_LENGTH) + `… [${value.length} chars]`;
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
result[key] = value;
|
|
339
|
+
}
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
// Recurse into nested objects
|
|
343
|
+
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
344
|
+
result[key] = redactObject(value, depth + 1, counter);
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
// Arrays — redact string elements, recurse into objects
|
|
348
|
+
if (Array.isArray(value)) {
|
|
349
|
+
result[key] = value.map((item) => {
|
|
350
|
+
if (typeof item === "string") {
|
|
351
|
+
if (isSensitiveValue(item)) {
|
|
352
|
+
counter.count++;
|
|
353
|
+
return REDACTED;
|
|
354
|
+
}
|
|
355
|
+
if (item.length > MAX_VALUE_LENGTH) {
|
|
356
|
+
return item.slice(0, MAX_VALUE_LENGTH) + `… [${item.length} chars]`;
|
|
357
|
+
}
|
|
358
|
+
return item;
|
|
359
|
+
}
|
|
360
|
+
if (item !== null && typeof item === "object" && !Array.isArray(item)) {
|
|
361
|
+
return redactObject(item, depth + 1, counter);
|
|
362
|
+
}
|
|
363
|
+
return item;
|
|
364
|
+
});
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
// Primitives pass through
|
|
368
|
+
result[key] = value;
|
|
369
|
+
}
|
|
370
|
+
return result;
|
|
371
|
+
}
|
|
372
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill/plugin scanner — scans installed skills and plugins.
|
|
3
|
+
*
|
|
4
|
+
* Scans:
|
|
5
|
+
* - ~/.openclaw/skills/ (managed skills)
|
|
6
|
+
* - <workspace>/skills/ (workspace skills)
|
|
7
|
+
* - ~/.openclaw/extensions/ (installed plugins)
|
|
8
|
+
*
|
|
9
|
+
* Reports: name, version, source, permissions, risk indicators.
|
|
10
|
+
*/
|
|
11
|
+
interface ScannedItem {
|
|
12
|
+
name: string;
|
|
13
|
+
type: "skill" | "plugin";
|
|
14
|
+
source: string;
|
|
15
|
+
version?: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
permissions?: string[];
|
|
18
|
+
riskIndicators?: string[];
|
|
19
|
+
}
|
|
20
|
+
interface ScanResults {
|
|
21
|
+
skills: ScannedItem[];
|
|
22
|
+
plugins: ScannedItem[];
|
|
23
|
+
scannedAt: number;
|
|
24
|
+
}
|
|
25
|
+
export declare function scanSkillsAndPlugins(workspaceDir?: string): Promise<ScanResults>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAUH,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,UAAU,WAAW;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,wBAAsB,oBAAoB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAoCtF"}
|