Chore: simplify sanitizeErrorURL

This commit is contained in:
shamoon
2026-08-07 08:15:09 -07:00
parent d8b2a33d5b
commit 162593c0e9
9 changed files with 30 additions and 38 deletions
+1 -7
View File
@@ -69,11 +69,5 @@ export function jsonArrayFilter(data, filter) {
}
export function sanitizeErrorURL(errorURL) {
// Dont display sensitive params on frontend
const url = new URL(errorURL);
["apikey", "api_key", "token", "t", "access_token", "auth"].forEach((key) => {
if (url.searchParams.has(key)) url.searchParams.set(key, "***");
if (url.hash.includes(key)) url.hash = url.hash.replace(new RegExp(`${key}=[^&]+`), `${key}=***`);
});
return url.toString();
return `${new URL(errorURL).hostname} (see logs for details)`;
}
+7 -18
View File
@@ -83,25 +83,14 @@ describe("utils/proxy/api-helpers", () => {
expect(jsonArrayFilter(data, (item) => item.a > 1)).toEqual([{ a: 2 }]);
});
it("sanitizeErrorURL redacts sensitive query params and hash fragments", () => {
const input = "https://example.com/path?apikey=123&token=abc#access_token=xyz&other=1";
const output = sanitizeErrorURL(input);
const url = new URL(output);
expect(url.searchParams.get("apikey")).toBe("***");
expect(url.searchParams.get("token")).toBe("***");
expect(url.hash).toContain("access_token=***");
expect(url.hash).toContain("other=1");
it("sanitizeErrorURL returns only the hostname regardless of where credentials appear", () => {
const input = "https://user:pass@example.com/secret-path-key/status?custom_secret=abc#token=xyz";
expect(sanitizeErrorURL(input)).toBe("example.com (see logs for details)");
});
it("sanitizeErrorURL only redacts known keys", () => {
const input = "https://example.com/path?api_key=123&safe=ok#auth=abc&safe_hash=1";
const output = sanitizeErrorURL(input);
const url = new URL(output);
expect(url.searchParams.get("api_key")).toBe("***");
expect(url.searchParams.get("safe")).toBe("ok");
expect(url.hash).toContain("auth=***");
expect(url.hash).toContain("safe_hash=1");
it("sanitizeErrorURL accepts URL objects and omits the port", () => {
expect(sanitizeErrorURL(new URL("http://192.168.1.10:8080/api?apikey=123"))).toBe(
"192.168.1.10 (see logs for details)",
);
});
});
@@ -263,7 +263,7 @@ describe("utils/proxy/handlers/credentialed", () => {
expect(res.body).toEqual({
error: {
message: "HTTP Error",
url: "http://x/api/statistics",
url: "x (see logs for details)",
data: { detail: "Invalid token." },
},
});
@@ -414,7 +414,7 @@ describe("utils/proxy/handlers/credentialed", () => {
expect(params.headers["X-Finnhub-Token"]).toBe("finnhub-token");
});
it("sanitizes embedded query params when a downstream error contains a url", async () => {
it("replaces embedded error urls with the hostname when a downstream error contains a url", async () => {
getServiceWidget.mockResolvedValue({ type: "linkwarden", url: "http://example", key: "token" });
httpProxy.mockResolvedValue([500, "application/json", { error: { message: "oops", url: "http://bad" } }]);
@@ -424,7 +424,7 @@ describe("utils/proxy/handlers/credentialed", () => {
await credentialedProxyHandler(req, res);
expect(res.statusCode).toBe(500);
expect(res.body.error.url).toContain("apikey=***");
expect(res.body.error.url).toBe("example (see logs for details)");
});
it("ends the response for 204/304 statuses", async () => {
@@ -451,7 +451,7 @@ describe("utils/proxy/handlers/credentialed", () => {
expect(res.statusCode).toBe(500);
expect(res.body.error.message).toBe("Invalid data");
expect(res.body.error.url).toContain("http://example/api/v1/collections");
expect(res.body.error.url).toBe("example (see logs for details)");
});
it("applies the response mapping function when provided", async () => {
+2 -2
View File
@@ -151,7 +151,7 @@ describe("utils/proxy/handlers/generic", () => {
await genericProxyHandler(req, res);
expect(res.statusCode).toBe(200);
expect(res.body.error.url).toContain("apikey=***");
expect(res.body.error.url).toBe("example (see logs for details)");
});
it("returns an Invalid data error when validation fails", async () => {
@@ -223,7 +223,7 @@ describe("utils/proxy/handlers/generic", () => {
expect(res.statusCode).toBe(500);
expect(res.body.error.message).toBe("HTTP Error");
expect(res.body.error.url).toContain("apikey=***");
expect(res.body.error.url).toBe("example (see logs for details)");
expect(res.body.error.data).toBe("fail");
});
+1 -1
View File
@@ -436,6 +436,6 @@ describe("utils/proxy/http httpProxy", () => {
expect(status).toBe(500);
expect(contentType).toBe("application/json");
expect(data.error.message).toBe("boom");
expect(data.error.url).toContain("apikey=***");
expect(data.error.url).toBe("example.com (see logs for details)");
});
});
+1 -1
View File
@@ -77,7 +77,7 @@ describe("widgets/dockhand/proxy", () => {
expect(res.statusCode).toBe(500);
expect(res.body.error.message).toBe("HTTP Error");
expect(res.body.error.url).toContain("token=***");
expect(res.body.error.url).toBe("dockhand (see logs for details)");
});
it("supports token auth", async () => {
+10 -2
View File
@@ -47,7 +47,14 @@ export default async function frigateProxyHandler(req, res, map) {
});
if (loginStatus !== 200) {
logger.error("HTTP Error %d calling %s", loginStatus, sanitizeErrorURL(loginUrl));
const errorURL = new URL(loginUrl);
logger.error(
"HTTP Error %d calling %s//%s%s...",
loginStatus,
errorURL.protocol,
errorURL.host,
errorURL.pathname,
);
return res.status(status).json({
error: {
message: `HTTP Error ${status} while trying to login to Frigate`,
@@ -63,7 +70,8 @@ export default async function frigateProxyHandler(req, res, map) {
}
if (status >= 400) {
logger.error("HTTP Error %d calling %s", status, sanitizeErrorURL(url));
const errorURL = new URL(url);
logger.error("HTTP Error %d calling %s//%s%s...", status, errorURL.protocol, errorURL.host, errorURL.pathname);
return res.status(status).json({
error: {
message: `HTTP Error ${status} from Frigate`,
+2 -2
View File
@@ -99,7 +99,7 @@ describe("widgets/frigate/proxy", () => {
expect.objectContaining({
error: expect.objectContaining({
message: "HTTP Error 401 from Frigate",
url: "http://frigate/api/stats",
url: "frigate (see logs for details)",
}),
}),
);
@@ -162,7 +162,7 @@ describe("widgets/frigate/proxy", () => {
expect.objectContaining({
error: expect.objectContaining({
message: "HTTP Error 401 while trying to login to Frigate",
url: "http://frigate/api/stats",
url: "frigate (see logs for details)",
}),
}),
);
+2 -1
View File
@@ -34,7 +34,8 @@ export default async function komodoProxyHandler(req, res) {
let resultData = data;
if (status >= 400) {
logger.error("HTTP Error %d calling %s", status, sanitizeErrorURL(url));
const errorURL = new URL(url);
logger.error("HTTP Error %d calling %s//%s%s...", status, errorURL.protocol, errorURL.host, errorURL.pathname);
}
if (status === 200) {