@solongate/proxy 0.2.5 → 0.2.7

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.
Files changed (3) hide show
  1. package/dist/index.js +15 -12
  2. package/dist/init.js +15 -12
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -493,6 +493,7 @@ const PATH_ARGS = ['file_path', 'path', 'pattern', 'directory', 'url', 'uri', 'n
493
493
  function checkBashCommand(cmd) {
494
494
  if (typeof cmd !== 'string') return null;
495
495
  for (const p of DANGEROUS_COMMANDS) if (p.test(cmd)) return 'Dangerous command blocked: ' + cmd.slice(0, 80);
496
+ for (const p of SSRF) if (p.test(cmd)) return 'SSRF attempt blocked in command: ' + cmd.slice(0, 80);
496
497
  return null;
497
498
  }
498
499
 
@@ -529,19 +530,21 @@ process.stdin.on('end', async () => {
529
530
  const ms = Date.now() - start;
530
531
 
531
532
  if (threat) {
532
- // Send DENY audit log
533
+ // Send DENY audit log \u2014 MUST await before exit or fetch dies
533
534
  if (API_KEY && API_KEY.startsWith('sg_live_')) {
534
- fetch(API_URL + '/api/v1/audit-logs', {
535
- method: 'POST',
536
- headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
537
- body: JSON.stringify({
538
- tool, arguments: Object.fromEntries(Object.entries(args).map(([k,v]) =>
539
- [k, typeof v === 'string' && v.length > 200 ? v.slice(0,200)+'...' : v])),
540
- decision: 'DENY', reason: threat, source: 'claude-code-guard',
541
- evaluationTimeMs: ms,
542
- }),
543
- signal: AbortSignal.timeout(5000),
544
- }).catch(() => {});
535
+ try {
536
+ await fetch(API_URL + '/api/v1/audit-logs', {
537
+ method: 'POST',
538
+ headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
539
+ body: JSON.stringify({
540
+ tool, arguments: Object.fromEntries(Object.entries(args).map(([k,v]) =>
541
+ [k, typeof v === 'string' && v.length > 200 ? v.slice(0,200)+'...' : v])),
542
+ decision: 'DENY', reason: threat, source: 'claude-code-guard',
543
+ evaluationTimeMs: ms,
544
+ }),
545
+ signal: AbortSignal.timeout(3000),
546
+ });
547
+ } catch {}
545
548
  }
546
549
  // Exit 2 = BLOCK. Write to both stdout and stderr for visibility.
547
550
  const msg = 'SOLONGATE BLOCKED: ' + threat;
package/dist/init.js CHANGED
@@ -212,6 +212,7 @@ const PATH_ARGS = ['file_path', 'path', 'pattern', 'directory', 'url', 'uri', 'n
212
212
  function checkBashCommand(cmd) {
213
213
  if (typeof cmd !== 'string') return null;
214
214
  for (const p of DANGEROUS_COMMANDS) if (p.test(cmd)) return 'Dangerous command blocked: ' + cmd.slice(0, 80);
215
+ for (const p of SSRF) if (p.test(cmd)) return 'SSRF attempt blocked in command: ' + cmd.slice(0, 80);
215
216
  return null;
216
217
  }
217
218
 
@@ -248,19 +249,21 @@ process.stdin.on('end', async () => {
248
249
  const ms = Date.now() - start;
249
250
 
250
251
  if (threat) {
251
- // Send DENY audit log
252
+ // Send DENY audit log \u2014 MUST await before exit or fetch dies
252
253
  if (API_KEY && API_KEY.startsWith('sg_live_')) {
253
- fetch(API_URL + '/api/v1/audit-logs', {
254
- method: 'POST',
255
- headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
256
- body: JSON.stringify({
257
- tool, arguments: Object.fromEntries(Object.entries(args).map(([k,v]) =>
258
- [k, typeof v === 'string' && v.length > 200 ? v.slice(0,200)+'...' : v])),
259
- decision: 'DENY', reason: threat, source: 'claude-code-guard',
260
- evaluationTimeMs: ms,
261
- }),
262
- signal: AbortSignal.timeout(5000),
263
- }).catch(() => {});
254
+ try {
255
+ await fetch(API_URL + '/api/v1/audit-logs', {
256
+ method: 'POST',
257
+ headers: { 'Authorization': 'Bearer ' + API_KEY, 'Content-Type': 'application/json' },
258
+ body: JSON.stringify({
259
+ tool, arguments: Object.fromEntries(Object.entries(args).map(([k,v]) =>
260
+ [k, typeof v === 'string' && v.length > 200 ? v.slice(0,200)+'...' : v])),
261
+ decision: 'DENY', reason: threat, source: 'claude-code-guard',
262
+ evaluationTimeMs: ms,
263
+ }),
264
+ signal: AbortSignal.timeout(3000),
265
+ });
266
+ } catch {}
264
267
  }
265
268
  // Exit 2 = BLOCK. Write to both stdout and stderr for visibility.
266
269
  const msg = 'SOLONGATE BLOCKED: ' + threat;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solongate/proxy",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "MCP security proxy \u00e2\u20ac\u201d protect any MCP server with policies, input validation, rate limiting, and audit logging. Zero code changes required.",
5
5
  "type": "module",
6
6
  "bin": {