@dotsetlabs/tollgate 0.2.2 → 0.3.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/README.md +138 -0
- package/dist/analyzers/filesystem.d.ts +5 -0
- package/dist/analyzers/filesystem.d.ts.map +1 -1
- package/dist/analyzers/filesystem.js +61 -7
- package/dist/analyzers/filesystem.js.map +1 -1
- package/dist/analyzers/loader.d.ts +5 -0
- package/dist/analyzers/loader.d.ts.map +1 -1
- package/dist/analyzers/loader.js +112 -6
- package/dist/analyzers/loader.js.map +1 -1
- package/dist/analyzers/prompt-injection.d.ts +1 -0
- package/dist/analyzers/prompt-injection.d.ts.map +1 -1
- package/dist/analyzers/prompt-injection.js +48 -2
- package/dist/analyzers/prompt-injection.js.map +1 -1
- package/dist/analyzers/shell.d.ts +8 -0
- package/dist/analyzers/shell.d.ts.map +1 -1
- package/dist/analyzers/shell.js +109 -8
- package/dist/analyzers/shell.js.map +1 -1
- package/dist/analyzers/sql.d.ts.map +1 -1
- package/dist/analyzers/sql.js +8 -7
- package/dist/analyzers/sql.js.map +1 -1
- package/dist/approval/interactive.d.ts +1 -1
- package/dist/approval/interactive.d.ts.map +1 -1
- package/dist/approval/interactive.js +13 -1
- package/dist/approval/interactive.js.map +1 -1
- package/dist/approval/rate-limiter.d.ts +115 -0
- package/dist/approval/rate-limiter.d.ts.map +1 -0
- package/dist/approval/rate-limiter.js +200 -0
- package/dist/approval/rate-limiter.js.map +1 -0
- package/dist/approval/url-validator.d.ts +51 -0
- package/dist/approval/url-validator.d.ts.map +1 -0
- package/dist/approval/url-validator.js +184 -0
- package/dist/approval/url-validator.js.map +1 -0
- package/dist/approval/webhook.d.ts +48 -0
- package/dist/approval/webhook.d.ts.map +1 -1
- package/dist/approval/webhook.js +89 -0
- package/dist/approval/webhook.js.map +1 -1
- package/dist/audit/integrity.d.ts +107 -0
- package/dist/audit/integrity.d.ts.map +1 -0
- package/dist/audit/integrity.js +191 -0
- package/dist/audit/integrity.js.map +1 -0
- package/dist/audit/logger.d.ts.map +1 -1
- package/dist/audit/logger.js +6 -5
- package/dist/audit/logger.js.map +1 -1
- package/dist/audit/redaction.js +6 -4
- package/dist/audit/redaction.js.map +1 -1
- package/dist/cli/commands/guard.d.ts +97 -0
- package/dist/cli/commands/guard.d.ts.map +1 -0
- package/dist/cli/commands/guard.js +456 -0
- package/dist/cli/commands/guard.js.map +1 -0
- package/dist/cli/commands/serve.js +1 -1
- package/dist/cli/commands/serve.js.map +1 -1
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/input-validation.d.ts +83 -0
- package/dist/cli/input-validation.d.ts.map +1 -0
- package/dist/cli/input-validation.js +237 -0
- package/dist/cli/input-validation.js.map +1 -0
- package/dist/cli/ui.js +2 -2
- package/dist/cli/ui.js.map +1 -1
- package/dist/guard/alternatives/index.d.ts +68 -0
- package/dist/guard/alternatives/index.d.ts.map +1 -0
- package/dist/guard/alternatives/index.js +224 -0
- package/dist/guard/alternatives/index.js.map +1 -0
- package/dist/guard/alternatives/registry.d.ts +16 -0
- package/dist/guard/alternatives/registry.d.ts.map +1 -0
- package/dist/guard/alternatives/registry.js +518 -0
- package/dist/guard/alternatives/registry.js.map +1 -0
- package/dist/guard/alternatives/types.d.ts +86 -0
- package/dist/guard/alternatives/types.d.ts.map +1 -0
- package/dist/guard/alternatives/types.js +5 -0
- package/dist/guard/alternatives/types.js.map +1 -0
- package/dist/guard/approval/enhanced-terminal.d.ts +110 -0
- package/dist/guard/approval/enhanced-terminal.d.ts.map +1 -0
- package/dist/guard/approval/enhanced-terminal.js +387 -0
- package/dist/guard/approval/enhanced-terminal.js.map +1 -0
- package/dist/guard/config.d.ts +80 -0
- package/dist/guard/config.d.ts.map +1 -0
- package/dist/guard/config.js +260 -0
- package/dist/guard/config.js.map +1 -0
- package/dist/guard/context/directory.d.ts +35 -0
- package/dist/guard/context/directory.d.ts.map +1 -0
- package/dist/guard/context/directory.js +243 -0
- package/dist/guard/context/directory.js.map +1 -0
- package/dist/guard/context/environment.d.ts +31 -0
- package/dist/guard/context/environment.d.ts.map +1 -0
- package/dist/guard/context/environment.js +204 -0
- package/dist/guard/context/environment.js.map +1 -0
- package/dist/guard/context/git.d.ts +52 -0
- package/dist/guard/context/git.d.ts.map +1 -0
- package/dist/guard/context/git.js +278 -0
- package/dist/guard/context/git.js.map +1 -0
- package/dist/guard/context/index.d.ts +64 -0
- package/dist/guard/context/index.d.ts.map +1 -0
- package/dist/guard/context/index.js +227 -0
- package/dist/guard/context/index.js.map +1 -0
- package/dist/guard/context/project.d.ts +47 -0
- package/dist/guard/context/project.d.ts.map +1 -0
- package/dist/guard/context/project.js +281 -0
- package/dist/guard/context/project.js.map +1 -0
- package/dist/guard/context/types.d.ts +152 -0
- package/dist/guard/context/types.d.ts.map +1 -0
- package/dist/guard/context/types.js +7 -0
- package/dist/guard/context/types.js.map +1 -0
- package/dist/guard/engine.d.ts +107 -0
- package/dist/guard/engine.d.ts.map +1 -0
- package/dist/guard/engine.js +430 -0
- package/dist/guard/engine.js.map +1 -0
- package/dist/guard/enhanced-engine.d.ts +151 -0
- package/dist/guard/enhanced-engine.d.ts.map +1 -0
- package/dist/guard/enhanced-engine.js +622 -0
- package/dist/guard/enhanced-engine.js.map +1 -0
- package/dist/guard/hooks/index.d.ts +50 -0
- package/dist/guard/hooks/index.d.ts.map +1 -0
- package/dist/guard/hooks/index.js +325 -0
- package/dist/guard/hooks/index.js.map +1 -0
- package/dist/guard/index.d.ts +29 -0
- package/dist/guard/index.d.ts.map +1 -0
- package/dist/guard/index.js +31 -0
- package/dist/guard/index.js.map +1 -0
- package/dist/guard/learning/index.d.ts +136 -0
- package/dist/guard/learning/index.d.ts.map +1 -0
- package/dist/guard/learning/index.js +314 -0
- package/dist/guard/learning/index.js.map +1 -0
- package/dist/guard/learning/pattern-extractor.d.ts +50 -0
- package/dist/guard/learning/pattern-extractor.d.ts.map +1 -0
- package/dist/guard/learning/pattern-extractor.js +372 -0
- package/dist/guard/learning/pattern-extractor.js.map +1 -0
- package/dist/guard/learning/rule-suggester.d.ts +67 -0
- package/dist/guard/learning/rule-suggester.d.ts.map +1 -0
- package/dist/guard/learning/rule-suggester.js +345 -0
- package/dist/guard/learning/rule-suggester.js.map +1 -0
- package/dist/guard/learning/types.d.ts +211 -0
- package/dist/guard/learning/types.d.ts.map +1 -0
- package/dist/guard/learning/types.js +18 -0
- package/dist/guard/learning/types.js.map +1 -0
- package/dist/guard/preview/effects.d.ts +15 -0
- package/dist/guard/preview/effects.d.ts.map +1 -0
- package/dist/guard/preview/effects.js +413 -0
- package/dist/guard/preview/effects.js.map +1 -0
- package/dist/guard/preview/index.d.ts +49 -0
- package/dist/guard/preview/index.d.ts.map +1 -0
- package/dist/guard/preview/index.js +196 -0
- package/dist/guard/preview/index.js.map +1 -0
- package/dist/guard/preview/parser.d.ts +34 -0
- package/dist/guard/preview/parser.d.ts.map +1 -0
- package/dist/guard/preview/parser.js +292 -0
- package/dist/guard/preview/parser.js.map +1 -0
- package/dist/guard/preview/types.d.ts +140 -0
- package/dist/guard/preview/types.d.ts.map +1 -0
- package/dist/guard/preview/types.js +5 -0
- package/dist/guard/preview/types.js.map +1 -0
- package/dist/guard/reversibility/index.d.ts +88 -0
- package/dist/guard/reversibility/index.d.ts.map +1 -0
- package/dist/guard/reversibility/index.js +310 -0
- package/dist/guard/reversibility/index.js.map +1 -0
- package/dist/guard/types.d.ts +192 -0
- package/dist/guard/types.d.ts.map +1 -0
- package/dist/guard/types.js +8 -0
- package/dist/guard/types.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/manager.d.ts.map +1 -1
- package/dist/orchestrator/manager.js +6 -1
- package/dist/orchestrator/manager.js.map +1 -1
- package/dist/policy/engine.d.ts.map +1 -1
- package/dist/policy/engine.js +11 -3
- package/dist/policy/engine.js.map +1 -1
- package/dist/policy/parser.d.ts.map +1 -1
- package/dist/policy/parser.js +3 -0
- package/dist/policy/parser.js.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/server.js +8 -6
- package/dist/proxy/server.js.map +1 -1
- package/dist/session/manager.d.ts +2 -2
- package/dist/session/manager.d.ts.map +1 -1
- package/dist/session/manager.js +106 -88
- package/dist/session/manager.js.map +1 -1
- package/dist/session/signing.d.ts +88 -0
- package/dist/session/signing.d.ts.map +1 -0
- package/dist/session/signing.js +166 -0
- package/dist/session/signing.js.map +1 -0
- package/dist/session/types.d.ts +2 -0
- package/dist/session/types.d.ts.map +1 -1
- package/dist/session/types.js.map +1 -1
- package/dist/utils/security-logger.d.ts +146 -0
- package/dist/utils/security-logger.d.ts.map +1 -0
- package/dist/utils/security-logger.js +222 -0
- package/dist/utils/security-logger.js.map +1 -0
- package/dist/wizard.d.ts.map +1 -1
- package/dist/wizard.js +7 -1
- package/dist/wizard.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rate Limiter for Tollgate Approval Requests
|
|
3
|
+
*
|
|
4
|
+
* Prevents DoS and approval fatigue attacks by limiting the rate of
|
|
5
|
+
* approval prompts per server/tool combination.
|
|
6
|
+
*
|
|
7
|
+
* Uses a sliding window algorithm for accurate rate limiting.
|
|
8
|
+
*
|
|
9
|
+
* @module approval/rate-limiter
|
|
10
|
+
*/
|
|
11
|
+
import { approvalLogger as logger } from '../utils/logger.js';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Rate Limiter Implementation
|
|
14
|
+
// =============================================================================
|
|
15
|
+
/**
|
|
16
|
+
* Sliding window rate limiter for approval requests.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const limiter = new RateLimiter({ maxPerMinute: 30, maxPerHour: 300 });
|
|
21
|
+
*
|
|
22
|
+
* const result = limiter.check('postgres:query');
|
|
23
|
+
* if (!result.allowed) {
|
|
24
|
+
* console.log(`Rate limited: ${result.reason}`);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export class RateLimiter {
|
|
29
|
+
config;
|
|
30
|
+
requests = new Map();
|
|
31
|
+
stats = {
|
|
32
|
+
totalRequests: 0,
|
|
33
|
+
allowedRequests: 0,
|
|
34
|
+
deniedRequests: 0,
|
|
35
|
+
activeKeys: 0,
|
|
36
|
+
deniedByKey: {},
|
|
37
|
+
};
|
|
38
|
+
cleanupInterval = null;
|
|
39
|
+
constructor(config = {}) {
|
|
40
|
+
this.config = {
|
|
41
|
+
maxPerMinute: config.maxPerMinute ?? 30,
|
|
42
|
+
maxPerHour: config.maxPerHour ?? 300,
|
|
43
|
+
autoDeny: config.autoDeny ?? true,
|
|
44
|
+
windowMs: config.windowMs ?? 3600000, // 1 hour
|
|
45
|
+
};
|
|
46
|
+
// Start cleanup interval
|
|
47
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60000);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a request is allowed for the given key.
|
|
51
|
+
*
|
|
52
|
+
* @param key - Unique key for rate limiting (e.g., "server:tool")
|
|
53
|
+
* @returns Rate limit result
|
|
54
|
+
*/
|
|
55
|
+
check(key) {
|
|
56
|
+
const now = Date.now();
|
|
57
|
+
const oneMinuteAgo = now - 60000;
|
|
58
|
+
const oneHourAgo = now - 3600000;
|
|
59
|
+
this.stats.totalRequests++;
|
|
60
|
+
// Get or create request history for this key
|
|
61
|
+
const history = this.requests.get(key) ?? [];
|
|
62
|
+
// Filter to requests within the window
|
|
63
|
+
const recentMinute = history.filter((t) => t > oneMinuteAgo);
|
|
64
|
+
const recentHour = history.filter((t) => t > oneHourAgo);
|
|
65
|
+
const remainingPerMinute = Math.max(0, this.config.maxPerMinute - recentMinute.length);
|
|
66
|
+
const remainingPerHour = Math.max(0, this.config.maxPerHour - recentHour.length);
|
|
67
|
+
// Check if rate exceeded
|
|
68
|
+
if (recentMinute.length >= this.config.maxPerMinute) {
|
|
69
|
+
this.stats.deniedRequests++;
|
|
70
|
+
this.stats.deniedByKey[key] = (this.stats.deniedByKey[key] ?? 0) + 1;
|
|
71
|
+
const oldestInMinute = Math.min(...recentMinute);
|
|
72
|
+
const retryAfterMs = oldestInMinute + 60000 - now;
|
|
73
|
+
logger.warn('Rate limit exceeded (per minute)', {
|
|
74
|
+
key,
|
|
75
|
+
count: recentMinute.length,
|
|
76
|
+
limit: this.config.maxPerMinute,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
allowed: false,
|
|
80
|
+
reason: `Rate limit exceeded: ${recentMinute.length}/${this.config.maxPerMinute} requests per minute`,
|
|
81
|
+
remainingPerMinute: 0,
|
|
82
|
+
remainingPerHour,
|
|
83
|
+
retryAfterMs: Math.max(0, retryAfterMs),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (recentHour.length >= this.config.maxPerHour) {
|
|
87
|
+
this.stats.deniedRequests++;
|
|
88
|
+
this.stats.deniedByKey[key] = (this.stats.deniedByKey[key] ?? 0) + 1;
|
|
89
|
+
const oldestInHour = Math.min(...recentHour);
|
|
90
|
+
const retryAfterMs = oldestInHour + 3600000 - now;
|
|
91
|
+
logger.warn('Rate limit exceeded (per hour)', {
|
|
92
|
+
key,
|
|
93
|
+
count: recentHour.length,
|
|
94
|
+
limit: this.config.maxPerHour,
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
allowed: false,
|
|
98
|
+
reason: `Rate limit exceeded: ${recentHour.length}/${this.config.maxPerHour} requests per hour`,
|
|
99
|
+
remainingPerMinute,
|
|
100
|
+
remainingPerHour: 0,
|
|
101
|
+
retryAfterMs: Math.max(0, retryAfterMs),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Request allowed - record it
|
|
105
|
+
recentHour.push(now);
|
|
106
|
+
this.requests.set(key, recentHour);
|
|
107
|
+
this.stats.allowedRequests++;
|
|
108
|
+
this.stats.activeKeys = this.requests.size;
|
|
109
|
+
return {
|
|
110
|
+
allowed: true,
|
|
111
|
+
remainingPerMinute: remainingPerMinute - 1,
|
|
112
|
+
remainingPerHour: remainingPerHour - 1,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Record a request without checking limits.
|
|
117
|
+
* Useful for tracking requests that bypass rate limiting.
|
|
118
|
+
*/
|
|
119
|
+
record(key) {
|
|
120
|
+
const now = Date.now();
|
|
121
|
+
const history = this.requests.get(key) ?? [];
|
|
122
|
+
history.push(now);
|
|
123
|
+
this.requests.set(key, history);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Reset rate limiting for a specific key.
|
|
127
|
+
*/
|
|
128
|
+
reset(key) {
|
|
129
|
+
this.requests.delete(key);
|
|
130
|
+
delete this.stats.deniedByKey[key];
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Reset all rate limiting.
|
|
134
|
+
*/
|
|
135
|
+
resetAll() {
|
|
136
|
+
this.requests.clear();
|
|
137
|
+
this.stats = {
|
|
138
|
+
totalRequests: 0,
|
|
139
|
+
allowedRequests: 0,
|
|
140
|
+
deniedRequests: 0,
|
|
141
|
+
activeKeys: 0,
|
|
142
|
+
deniedByKey: {},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get current statistics.
|
|
147
|
+
*/
|
|
148
|
+
getStats() {
|
|
149
|
+
return { ...this.stats, activeKeys: this.requests.size };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Clean up old entries to prevent memory leaks.
|
|
153
|
+
*/
|
|
154
|
+
cleanup() {
|
|
155
|
+
const cutoff = Date.now() - this.config.windowMs;
|
|
156
|
+
for (const [key, history] of this.requests.entries()) {
|
|
157
|
+
const recent = history.filter((t) => t > cutoff);
|
|
158
|
+
if (recent.length === 0) {
|
|
159
|
+
this.requests.delete(key);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.requests.set(key, recent);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
this.stats.activeKeys = this.requests.size;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Close the rate limiter and stop cleanup interval.
|
|
169
|
+
*/
|
|
170
|
+
close() {
|
|
171
|
+
if (this.cleanupInterval) {
|
|
172
|
+
clearInterval(this.cleanupInterval);
|
|
173
|
+
this.cleanupInterval = null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// =============================================================================
|
|
178
|
+
// Global Rate Limiter Instance
|
|
179
|
+
// =============================================================================
|
|
180
|
+
let globalRateLimiter = null;
|
|
181
|
+
/**
|
|
182
|
+
* Get the global rate limiter instance.
|
|
183
|
+
* Creates one if it doesn't exist.
|
|
184
|
+
*/
|
|
185
|
+
export function getRateLimiter(config) {
|
|
186
|
+
if (!globalRateLimiter) {
|
|
187
|
+
globalRateLimiter = new RateLimiter(config);
|
|
188
|
+
}
|
|
189
|
+
return globalRateLimiter;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Reset the global rate limiter.
|
|
193
|
+
*/
|
|
194
|
+
export function resetGlobalRateLimiter() {
|
|
195
|
+
if (globalRateLimiter) {
|
|
196
|
+
globalRateLimiter.close();
|
|
197
|
+
globalRateLimiter = null;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../../src/approval/rate-limiter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook URL Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates webhook URLs to prevent SSRF attacks via configuration.
|
|
5
|
+
* Blocks localhost, private IPs, and dangerous protocols.
|
|
6
|
+
*
|
|
7
|
+
* @module approval/url-validator
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Options for URL validation.
|
|
11
|
+
*/
|
|
12
|
+
export interface UrlValidationOptions {
|
|
13
|
+
/** Allow localhost URLs (default: false) */
|
|
14
|
+
allowLocalhost?: boolean;
|
|
15
|
+
/** Allow private IP ranges (default: false) */
|
|
16
|
+
allowPrivateIps?: boolean;
|
|
17
|
+
/** Require HTTPS (default: true in production) */
|
|
18
|
+
requireHttps?: boolean;
|
|
19
|
+
/** Additional blocked hosts */
|
|
20
|
+
blockedHosts?: string[];
|
|
21
|
+
/** Additional allowed hosts (overrides blocks) */
|
|
22
|
+
allowedHosts?: string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Result of URL validation.
|
|
26
|
+
*/
|
|
27
|
+
export interface UrlValidationResult {
|
|
28
|
+
/** Whether the URL is valid */
|
|
29
|
+
valid: boolean;
|
|
30
|
+
/** Reason if invalid */
|
|
31
|
+
reason?: string;
|
|
32
|
+
/** Parsed URL (if valid) */
|
|
33
|
+
url?: URL;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validate a webhook URL.
|
|
37
|
+
*
|
|
38
|
+
* @param urlString - URL to validate
|
|
39
|
+
* @param options - Validation options
|
|
40
|
+
* @returns Validation result
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateWebhookUrl(urlString: string, options?: UrlValidationOptions): UrlValidationResult;
|
|
43
|
+
/**
|
|
44
|
+
* Validate URL and throw on invalid.
|
|
45
|
+
*
|
|
46
|
+
* @param urlString - URL to validate
|
|
47
|
+
* @param options - Validation options
|
|
48
|
+
* @throws Error if URL is invalid
|
|
49
|
+
*/
|
|
50
|
+
export declare function assertValidWebhookUrl(urlString: string, options?: UrlValidationOptions): URL;
|
|
51
|
+
//# sourceMappingURL=url-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-validator.d.ts","sourceRoot":"","sources":["../../src/approval/url-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,4CAA4C;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,kDAAkD;IAClD,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC,+BAA+B;IAC/B,KAAK,EAAE,OAAO,CAAC;IAEf,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,4BAA4B;IAC5B,GAAG,CAAC,EAAE,GAAG,CAAC;CACb;AAyDD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,oBAAyB,GACnC,mBAAmB,CAyFrB;AAsCD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,oBAAyB,GACnC,GAAG,CAML"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook URL Validator
|
|
3
|
+
*
|
|
4
|
+
* Validates webhook URLs to prevent SSRF attacks via configuration.
|
|
5
|
+
* Blocks localhost, private IPs, and dangerous protocols.
|
|
6
|
+
*
|
|
7
|
+
* @module approval/url-validator
|
|
8
|
+
*/
|
|
9
|
+
import { approvalLogger as logger } from '../utils/logger.js';
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// URL Validation Patterns
|
|
12
|
+
// =============================================================================
|
|
13
|
+
/**
|
|
14
|
+
* Localhost patterns.
|
|
15
|
+
*/
|
|
16
|
+
const LOCALHOST_PATTERNS = [
|
|
17
|
+
'localhost',
|
|
18
|
+
'127.0.0.1',
|
|
19
|
+
'::1',
|
|
20
|
+
'0.0.0.0',
|
|
21
|
+
'[::1]',
|
|
22
|
+
'0:0:0:0:0:0:0:1',
|
|
23
|
+
'[0:0:0:0:0:0:0:1]',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Private IP ranges (RFC 1918).
|
|
27
|
+
*/
|
|
28
|
+
const PRIVATE_IP_PATTERNS = [
|
|
29
|
+
/^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
|
|
30
|
+
/^172\.(1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}$/,
|
|
31
|
+
/^192\.168\.\d{1,3}\.\d{1,3}$/,
|
|
32
|
+
/^169\.254\.\d{1,3}\.\d{1,3}$/, // Link-local
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Cloud metadata endpoints.
|
|
36
|
+
*/
|
|
37
|
+
const METADATA_HOSTS = [
|
|
38
|
+
'169.254.169.254',
|
|
39
|
+
'metadata.google.internal',
|
|
40
|
+
'100.100.100.200',
|
|
41
|
+
'169.254.170.2',
|
|
42
|
+
];
|
|
43
|
+
/**
|
|
44
|
+
* Dangerous protocols.
|
|
45
|
+
*/
|
|
46
|
+
const DANGEROUS_PROTOCOLS = [
|
|
47
|
+
'file:',
|
|
48
|
+
'ftp:',
|
|
49
|
+
'gopher:',
|
|
50
|
+
'ldap:',
|
|
51
|
+
'dict:',
|
|
52
|
+
'sftp:',
|
|
53
|
+
'data:',
|
|
54
|
+
'javascript:',
|
|
55
|
+
];
|
|
56
|
+
// =============================================================================
|
|
57
|
+
// URL Validator
|
|
58
|
+
// =============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Validate a webhook URL.
|
|
61
|
+
*
|
|
62
|
+
* @param urlString - URL to validate
|
|
63
|
+
* @param options - Validation options
|
|
64
|
+
* @returns Validation result
|
|
65
|
+
*/
|
|
66
|
+
export function validateWebhookUrl(urlString, options = {}) {
|
|
67
|
+
const { allowLocalhost = false, allowPrivateIps = false, requireHttps = process.env.NODE_ENV === 'production', blockedHosts = [], allowedHosts = [], } = options;
|
|
68
|
+
// Parse URL
|
|
69
|
+
let url;
|
|
70
|
+
try {
|
|
71
|
+
url = new URL(urlString);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return {
|
|
75
|
+
valid: false,
|
|
76
|
+
reason: 'Invalid URL format',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const hostname = url.hostname.toLowerCase();
|
|
80
|
+
// Check allowed hosts first (whitelist takes precedence)
|
|
81
|
+
if (allowedHosts.some((h) => h.toLowerCase() === hostname)) {
|
|
82
|
+
return { valid: true, url };
|
|
83
|
+
}
|
|
84
|
+
// Check protocol
|
|
85
|
+
if (DANGEROUS_PROTOCOLS.includes(url.protocol)) {
|
|
86
|
+
logger.warn('Webhook URL uses dangerous protocol', { url: urlString, protocol: url.protocol });
|
|
87
|
+
return {
|
|
88
|
+
valid: false,
|
|
89
|
+
reason: `Dangerous protocol: ${url.protocol}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Check HTTPS requirement
|
|
93
|
+
if (requireHttps && url.protocol !== 'https:') {
|
|
94
|
+
return {
|
|
95
|
+
valid: false,
|
|
96
|
+
reason: 'Webhook URL must use HTTPS in production',
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Check localhost
|
|
100
|
+
if (!allowLocalhost && isLocalhost(hostname)) {
|
|
101
|
+
logger.warn('Webhook URL targets localhost', { url: urlString });
|
|
102
|
+
return {
|
|
103
|
+
valid: false,
|
|
104
|
+
reason: 'Webhook URL cannot target localhost',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Check private IPs
|
|
108
|
+
if (!allowPrivateIps && isPrivateIp(hostname)) {
|
|
109
|
+
logger.warn('Webhook URL targets private IP', { url: urlString });
|
|
110
|
+
return {
|
|
111
|
+
valid: false,
|
|
112
|
+
reason: 'Webhook URL cannot target private IP ranges',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Check metadata endpoints
|
|
116
|
+
if (METADATA_HOSTS.some((h) => hostname === h || hostname.includes(h))) {
|
|
117
|
+
logger.warn('Webhook URL targets cloud metadata', { url: urlString });
|
|
118
|
+
return {
|
|
119
|
+
valid: false,
|
|
120
|
+
reason: 'Webhook URL cannot target cloud metadata endpoints',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Check custom blocked hosts
|
|
124
|
+
if (blockedHosts.some((h) => h.toLowerCase() === hostname)) {
|
|
125
|
+
return {
|
|
126
|
+
valid: false,
|
|
127
|
+
reason: `Host is blocked: ${hostname}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
// Check for IP obfuscation (octal, hex, decimal)
|
|
131
|
+
if (isObfuscatedIp(hostname)) {
|
|
132
|
+
logger.warn('Webhook URL uses obfuscated IP', { url: urlString });
|
|
133
|
+
return {
|
|
134
|
+
valid: false,
|
|
135
|
+
reason: 'Webhook URL appears to use obfuscated IP notation',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return { valid: true, url };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Check if hostname is localhost.
|
|
142
|
+
*/
|
|
143
|
+
function isLocalhost(hostname) {
|
|
144
|
+
return LOCALHOST_PATTERNS.some((p) => hostname === p || hostname === `[${p}]`);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if hostname is a private IP.
|
|
148
|
+
*/
|
|
149
|
+
function isPrivateIp(hostname) {
|
|
150
|
+
return PRIVATE_IP_PATTERNS.some((p) => p.test(hostname));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check for obfuscated IP notation.
|
|
154
|
+
*/
|
|
155
|
+
function isObfuscatedIp(hostname) {
|
|
156
|
+
// Octal notation (e.g., 0177.0.0.1)
|
|
157
|
+
if (/^0[0-7]+\./.test(hostname)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
// Hex notation (e.g., 0x7f.0x0.0x0.0x1)
|
|
161
|
+
if (/^0x[0-9a-f]+/i.test(hostname)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
// Decimal notation (e.g., 2130706433)
|
|
165
|
+
if (/^\d{8,10}$/.test(hostname)) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Validate URL and throw on invalid.
|
|
172
|
+
*
|
|
173
|
+
* @param urlString - URL to validate
|
|
174
|
+
* @param options - Validation options
|
|
175
|
+
* @throws Error if URL is invalid
|
|
176
|
+
*/
|
|
177
|
+
export function assertValidWebhookUrl(urlString, options = {}) {
|
|
178
|
+
const result = validateWebhookUrl(urlString, options);
|
|
179
|
+
if (!result.valid) {
|
|
180
|
+
throw new Error(`Invalid webhook URL: ${result.reason}`);
|
|
181
|
+
}
|
|
182
|
+
return result.url;
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=url-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-validator.js","sourceRoot":"","sources":["../../src/approval/url-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -71,4 +71,52 @@ export declare class WebhookApprovalHandler implements ApprovalHandler {
|
|
|
71
71
|
private computeSignature;
|
|
72
72
|
close(): void;
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Verify a webhook signature from Tollgate.
|
|
76
|
+
*
|
|
77
|
+
* Use this function in your webhook receiver to validate that requests
|
|
78
|
+
* are authentic and haven't been tampered with.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { verifyWebhookSignature } from '@dotsetlabs/tollgate';
|
|
83
|
+
*
|
|
84
|
+
* app.post('/webhook/tollgate', async (req, res) => {
|
|
85
|
+
* const signature = req.headers['x-tollgate-signature'];
|
|
86
|
+
* const body = JSON.stringify(req.body);
|
|
87
|
+
*
|
|
88
|
+
* const isValid = await verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET);
|
|
89
|
+
*
|
|
90
|
+
* if (!isValid) {
|
|
91
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
92
|
+
* }
|
|
93
|
+
*
|
|
94
|
+
* // Process the webhook...
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*
|
|
98
|
+
* @param body - The raw request body as a string
|
|
99
|
+
* @param signature - The X-Tollgate-Signature header value
|
|
100
|
+
* @param secret - Your webhook secret
|
|
101
|
+
* @returns Promise<boolean> - True if signature is valid
|
|
102
|
+
*/
|
|
103
|
+
export declare function verifyWebhookSignature(body: string, signature: string | null | undefined, secret: string): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Result type for webhook signature verification.
|
|
106
|
+
*/
|
|
107
|
+
export interface WebhookVerificationResult {
|
|
108
|
+
/** Whether the signature is valid */
|
|
109
|
+
valid: boolean;
|
|
110
|
+
/** Reason for invalid signature */
|
|
111
|
+
reason?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Verify a webhook signature with detailed result.
|
|
115
|
+
*
|
|
116
|
+
* @param body - The raw request body as a string
|
|
117
|
+
* @param signature - The X-Tollgate-Signature header value
|
|
118
|
+
* @param secret - Your webhook secret
|
|
119
|
+
* @returns Promise<WebhookVerificationResult>
|
|
120
|
+
*/
|
|
121
|
+
export declare function verifyWebhookSignatureDetailed(body: string, signature: string | null | undefined, secret: string): Promise<WebhookVerificationResult>;
|
|
74
122
|
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/approval/webhook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAInF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IAEZ,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAElB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAE3B,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,eAAe,CAAgC;gBAE3C,MAAM,EAAE,qBAAqB;IAOnC,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0CjE;;OAEG;YACW,kBAAkB;IAqEhC;;OAEG;YACW,gBAAgB;IAmB9B,KAAK,IAAI,IAAI;CAId"}
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/approval/webhook.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAInF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,mDAAmD;IACnD,GAAG,EAAE,MAAM,CAAC;IAEZ,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,gDAAgD;IAChD,QAAQ,EAAE,OAAO,CAAC;IAElB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAE3B,mCAAmC;IACnC,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,eAAe,CAAgC;gBAE3C,MAAM,EAAE,qBAAqB;IAOnC,MAAM,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA0CjE;;OAEG;YACW,kBAAkB;IAqEhC;;OAEG;YACW,gBAAgB;IAmB9B,KAAK,IAAI,IAAI;CAId;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CA2ClB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAC;IAEf,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACpC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,yBAAyB,CAAC,CAoBpC"}
|
package/dist/approval/webhook.js
CHANGED
|
@@ -157,4 +157,93 @@ export class WebhookApprovalHandler {
|
|
|
157
157
|
this.abortController = null;
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
|
+
// =============================================================================
|
|
161
|
+
// Webhook Signature Verification Helper
|
|
162
|
+
// =============================================================================
|
|
163
|
+
/**
|
|
164
|
+
* Verify a webhook signature from Tollgate.
|
|
165
|
+
*
|
|
166
|
+
* Use this function in your webhook receiver to validate that requests
|
|
167
|
+
* are authentic and haven't been tampered with.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* import { verifyWebhookSignature } from '@dotsetlabs/tollgate';
|
|
172
|
+
*
|
|
173
|
+
* app.post('/webhook/tollgate', async (req, res) => {
|
|
174
|
+
* const signature = req.headers['x-tollgate-signature'];
|
|
175
|
+
* const body = JSON.stringify(req.body);
|
|
176
|
+
*
|
|
177
|
+
* const isValid = await verifyWebhookSignature(body, signature, process.env.WEBHOOK_SECRET);
|
|
178
|
+
*
|
|
179
|
+
* if (!isValid) {
|
|
180
|
+
* return res.status(401).json({ error: 'Invalid signature' });
|
|
181
|
+
* }
|
|
182
|
+
*
|
|
183
|
+
* // Process the webhook...
|
|
184
|
+
* });
|
|
185
|
+
* ```
|
|
186
|
+
*
|
|
187
|
+
* @param body - The raw request body as a string
|
|
188
|
+
* @param signature - The X-Tollgate-Signature header value
|
|
189
|
+
* @param secret - Your webhook secret
|
|
190
|
+
* @returns Promise<boolean> - True if signature is valid
|
|
191
|
+
*/
|
|
192
|
+
export async function verifyWebhookSignature(body, signature, secret) {
|
|
193
|
+
if (!signature || !secret) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
// Remove 'sha256=' prefix if present
|
|
197
|
+
const providedSig = signature.startsWith('sha256=')
|
|
198
|
+
? signature.slice(7)
|
|
199
|
+
: signature;
|
|
200
|
+
try {
|
|
201
|
+
// Compute expected signature
|
|
202
|
+
const encoder = new TextEncoder();
|
|
203
|
+
const key = await crypto.subtle.importKey('raw', encoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
204
|
+
const computed = await crypto.subtle.sign('HMAC', key, encoder.encode(body));
|
|
205
|
+
const expectedSig = Array.from(new Uint8Array(computed))
|
|
206
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
207
|
+
.join('');
|
|
208
|
+
// Timing-safe comparison to prevent timing attacks
|
|
209
|
+
if (providedSig.length !== expectedSig.length) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
// Use subtle timing-safe comparison
|
|
213
|
+
// Convert to buffers for comparison
|
|
214
|
+
let mismatch = 0;
|
|
215
|
+
for (let i = 0; i < providedSig.length; i++) {
|
|
216
|
+
mismatch |= providedSig.charCodeAt(i) ^ expectedSig.charCodeAt(i);
|
|
217
|
+
}
|
|
218
|
+
return mismatch === 0;
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
logger.error('Webhook signature verification error', { error });
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Verify a webhook signature with detailed result.
|
|
227
|
+
*
|
|
228
|
+
* @param body - The raw request body as a string
|
|
229
|
+
* @param signature - The X-Tollgate-Signature header value
|
|
230
|
+
* @param secret - Your webhook secret
|
|
231
|
+
* @returns Promise<WebhookVerificationResult>
|
|
232
|
+
*/
|
|
233
|
+
export async function verifyWebhookSignatureDetailed(body, signature, secret) {
|
|
234
|
+
if (!signature) {
|
|
235
|
+
return { valid: false, reason: 'Missing signature header' };
|
|
236
|
+
}
|
|
237
|
+
if (!secret) {
|
|
238
|
+
return { valid: false, reason: 'Missing webhook secret' };
|
|
239
|
+
}
|
|
240
|
+
if (!signature.startsWith('sha256=')) {
|
|
241
|
+
return { valid: false, reason: 'Invalid signature format (expected sha256=...)' };
|
|
242
|
+
}
|
|
243
|
+
const isValid = await verifyWebhookSignature(body, signature, secret);
|
|
244
|
+
if (isValid) {
|
|
245
|
+
return { valid: true };
|
|
246
|
+
}
|
|
247
|
+
return { valid: false, reason: 'Signature mismatch' };
|
|
248
|
+
}
|
|
160
249
|
//# sourceMappingURL=webhook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/approval/webhook.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/approval/webhook.ts"],"names":[],"mappings":"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"}
|