feat: unit tests for security/utility functions (isPrivateIP, isTransientError, markdown, escapeHtml)
All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 12m40s
Promote to Production / Deploy to Production (push) Successful in 8m48s

This commit is contained in:
Hoid 2026-02-25 19:04:59 +00:00
parent 0a002f94ef
commit 50a163b12d
10 changed files with 224 additions and 62 deletions

32
src/utils/errors.ts Normal file
View file

@ -0,0 +1,32 @@
// Transient error codes from PgBouncer / PostgreSQL that warrant retry
const TRANSIENT_ERRORS = new Set([
"ECONNRESET",
"ECONNREFUSED",
"EPIPE",
"ETIMEDOUT",
"CONNECTION_LOST",
"57P01", // admin_shutdown
"57P02", // crash_shutdown
"57P03", // cannot_connect_now
"08006", // connection_failure
"08003", // connection_does_not_exist
"08001", // sqlclient_unable_to_establish_sqlconnection
]);
/**
* Determine if an error is transient (PgBouncer failover, network blip)
*/
export function isTransientError(err: any): boolean {
if (!err) return false;
const code = err.code || "";
const msg = (err.message || "").toLowerCase();
if (TRANSIENT_ERRORS.has(code)) return true;
if (msg.includes("no available server")) return true;
if (msg.includes("connection terminated")) return true;
if (msg.includes("connection refused")) return true;
if (msg.includes("server closed the connection")) return true;
if (msg.includes("timeout expired")) return true;
return false;
}

3
src/utils/html.ts Normal file
View file

@ -0,0 +1,3 @@
export function escapeHtml(s: string): string {
return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
}

27
src/utils/network.ts Normal file
View file

@ -0,0 +1,27 @@
import net from "node:net";
export function isPrivateIP(ip: string): boolean {
// IPv6 loopback/unspecified
if (ip === "::1" || ip === "::") return true;
// IPv6 link-local (fe80::/10)
if (ip.toLowerCase().startsWith("fe8") || ip.toLowerCase().startsWith("fe9") ||
ip.toLowerCase().startsWith("fea") || ip.toLowerCase().startsWith("feb")) return true;
// IPv6 unique local (fc00::/7)
const lower = ip.toLowerCase();
if (lower.startsWith("fc") || lower.startsWith("fd")) return true;
// IPv4-mapped IPv6
if (ip.startsWith("::ffff:")) ip = ip.slice(7);
if (!net.isIPv4(ip)) return false;
const parts = ip.split(".").map(Number);
if (parts[0] === 0) return true; // 0.0.0.0/8
if (parts[0] === 10) return true; // 10.0.0.0/8
if (parts[0] === 127) return true; // 127.0.0.0/8
if (parts[0] === 169 && parts[1] === 254) return true; // 169.254.0.0/16
if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true; // 172.16.0.0/12
if (parts[0] === 192 && parts[1] === 168) return true; // 192.168.0.0/16
return false;
}