From 079c60ed8e1258f40fa806439e11759a8217afe0 Mon Sep 17 00:00:00 2001 From: tuanaiseo Date: Sat, 16 May 2026 06:04:33 +0700 Subject: [PATCH] fix(security)(hooks): bearer token sent over plaintext http The hook scripts (stop.ts, post-tool-use.ts, etc.) send Bearer tokens in Authorization headers to REST_URL. When AGENTMEMORY_URL defaults to 'http://localhost:3111', tokens are transmitted over plaintext HTTP. While localhost traffic typically doesn't leave the machine, this could be intercepted by local malware or other processes on multi-tenant systems. Affected files: stop.ts Signed-off-by: tuanaiseo <221258316+tuanaiseo@users.noreply.github.com> --- src/hooks/stop.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/hooks/stop.ts b/src/hooks/stop.ts index 1f2f5b8a..fd5ff85e 100644 --- a/src/hooks/stop.ts +++ b/src/hooks/stop.ts @@ -12,6 +12,23 @@ function isSdkChildContext(payload: unknown): boolean { const REST_URL = process.env["AGENTMEMORY_URL"] || "http://localhost:3111"; const SECRET = process.env["AGENTMEMORY_SECRET"] || ""; +function isSecureUrl(url: string): boolean { + try { + const parsed = new URL(url); + if (parsed.protocol === "https:") return true; + const hostname = parsed.hostname.toLowerCase(); + if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1") return true; + return false; + } catch { + return false; + } +} + +if (SECRET && !isSecureUrl(REST_URL)) { + console.error("Error: AGENTMEMORY_SECRET is set but AGENTMEMORY_URL uses insecure http:// protocol. Use https:// or a loopback address."); + process.exit(1); +} + function authHeaders(): Record { const h: Record = { "Content-Type": "application/json" }; if (SECRET) h["Authorization"] = `Bearer ${SECRET}`;