From ed9e0bbeb17f5b20bf8e34116472c5872a0fbe65 Mon Sep 17 00:00:00 2001 From: Schnitz <12687466+CptSchnitz@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:02:25 +0300 Subject: [PATCH 1/5] feat: changed opa headers mechanism from whitelist to blacklist --- docker-image/nginx-config/auth.js | 66 ++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/docker-image/nginx-config/auth.js b/docker-image/nginx-config/auth.js index 339af85..1532360 100644 --- a/docker-image/nginx-config/auth.js +++ b/docker-image/nginx-config/auth.js @@ -1,5 +1,51 @@ import qs from "querystring"; +const DENYLIST = { + // Payloads + cookie: true, + authorization: true, + + // Connection / Hop-by-Hop (Network Noise) + connection: true, + "keep-alive": true, + "transfer-encoding": true, + te: true, + trailer: true, + upgrade: true, + + // Cache State (State Noise) + "cache-control": true, + pragma: true, + "if-match": true, + "if-none-match": true, + "if-modified-since": true, + "if-unmodified-since": true, + + // Browser Privacy / Legacy (Unused Bloat) + dnt: true, + "sec-gpc": true, + "upgrade-insecure-requests": true, + "save-data": true, + + // Legacy Tracing (Dropping B3/Zipkin, implicitly keeping Otel W3C) + b3: true, + "x-b3-traceid": true, + "x-b3-spanid": true, + "x-b3-sampled": true, +}; + +function filterHeaders(r) { + let cleanHeaders = {}; + + for (let header in r.headersIn) { + if (!DENYLIST[header.toLowerCase()]) { + cleanHeaders[header] = r.headersIn[header]; + } + } + + return cleanHeaders; +} + async function opaAuth(r) { try { if (r.variables.original_method == "OPTIONS") { @@ -9,25 +55,7 @@ async function opaAuth(r) { const body = { input: { method: r.variables.original_method, - headers: { - 'user-agent': r.headersIn['user-agent'], - 'origin': r.headersIn['origin'], - 'referer': r.headersIn['referer'], - - // --- Custom Authentication --- - 'x-api-key': r.headersIn['x-api-key'], - - // --- Routing & Proxy Context --- - 'host': r.headersIn['host'], - 'x-forwarded-for': r.headersIn['x-forwarded-for'], - 'x-forwarded-host': r.headersIn['x-forwarded-host'], - 'x-forwarded-proto': r.headersIn['x-forwarded-proto'], - 'x-real-ip': r.headersIn['x-real-ip'], - - // --- Payload Context --- - 'content-type': r.headersIn['content-type'], - 'content-length': r.headersIn['content-length'], - }, + headers: filterHeaders(r), query: qs.parse(r.variables.original_args), domain: r.variables.domain, }, From cc3fb212326a2157623b8656c6999d44dfc5e6cb Mon Sep 17 00:00:00 2001 From: Ofer <12687466+CptSchnitz@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:52:10 +0300 Subject: [PATCH 2/5] feat: added proxy-authorization for the block list Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docker-image/nginx-config/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-image/nginx-config/auth.js b/docker-image/nginx-config/auth.js index 1532360..c63f881 100644 --- a/docker-image/nginx-config/auth.js +++ b/docker-image/nginx-config/auth.js @@ -4,7 +4,7 @@ const DENYLIST = { // Payloads cookie: true, authorization: true, - + "proxy-authorization": true, // Connection / Hop-by-Hop (Network Noise) connection: true, "keep-alive": true, From 7061fbee9d851ce58ec363ea8e5157468351ca40 Mon Sep 17 00:00:00 2001 From: Ofer <12687466+CptSchnitz@users.noreply.github.com> Date: Sun, 21 Jun 2026 10:53:08 +0300 Subject: [PATCH 3/5] fix: lowercase and increased security Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docker-image/nginx-config/auth.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docker-image/nginx-config/auth.js b/docker-image/nginx-config/auth.js index c63f881..5d9b778 100644 --- a/docker-image/nginx-config/auth.js +++ b/docker-image/nginx-config/auth.js @@ -35,11 +35,14 @@ const DENYLIST = { }; function filterHeaders(r) { - let cleanHeaders = {}; + const cleanHeaders = Object.create(null); - for (let header in r.headersIn) { - if (!DENYLIST[header.toLowerCase()]) { - cleanHeaders[header] = r.headersIn[header]; + for (const header in r.headersIn) { + if (!Object.prototype.hasOwnProperty.call(r.headersIn, header)) continue; + + const key = header.toLowerCase(); + if (!DENYLIST[key]) { + cleanHeaders[key] = r.headersIn[header]; } } From 3525d345a3efb5a40973811759fbf9be9319efaf Mon Sep 17 00:00:00 2001 From: Schnitz <12687466+CptSchnitz@users.noreply.github.com> Date: Sun, 21 Jun 2026 11:12:18 +0300 Subject: [PATCH 4/5] feat: implement size limit for headers and redact oversized values --- docker-image/nginx-config/auth.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/docker-image/nginx-config/auth.js b/docker-image/nginx-config/auth.js index 5d9b778..6376216 100644 --- a/docker-image/nginx-config/auth.js +++ b/docker-image/nginx-config/auth.js @@ -34,15 +34,36 @@ const DENYLIST = { "x-b3-sampled": true, }; +// 2. Size Limit Configuration +const MAX_HEADER_LENGTH = 2048; + +// 3. Exceptions to the size limit (Headers that are allowed to be large) +const LENGTH_EXCEPTIONS = { + "x-api-key": true, + referer: true, +}; + function filterHeaders(r) { + // Object.create(null) creates a pure dictionary with no prototype chain, + // protecting against prototype pollution/injection attacks. const cleanHeaders = Object.create(null); for (const header in r.headersIn) { - if (!Object.prototype.hasOwnProperty.call(r.headersIn, header)) continue; + // Protect against inherited properties injection + if (!Object.prototype.hasOwnProperty.call(r.headersIn, header)) { + continue; + } const key = header.toLowerCase(); + if (!DENYLIST[key]) { - cleanHeaders[key] = r.headersIn[header]; + const headerValue = r.headersIn[header]; + + if (headerValue.length > MAX_HEADER_LENGTH && !LENGTH_EXCEPTIONS[key]) { + cleanHeaders[key] = "[REDACTED_SIZE_LIMIT]"; + } else { + cleanHeaders[key] = headerValue; + } } } From 3479ee730c2e260f5411bda23b93dec41c41c95f Mon Sep 17 00:00:00 2001 From: Schnitz <12687466+CptSchnitz@users.noreply.github.com> Date: Mon, 22 Jun 2026 10:25:29 +0300 Subject: [PATCH 5/5] feat: handle array headers in filterHeaders and redact oversized values --- docker-image/nginx-config/auth.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-image/nginx-config/auth.js b/docker-image/nginx-config/auth.js index 6376216..ae5855e 100644 --- a/docker-image/nginx-config/auth.js +++ b/docker-image/nginx-config/auth.js @@ -57,7 +57,9 @@ function filterHeaders(r) { const key = header.toLowerCase(); if (!DENYLIST[key]) { - const headerValue = r.headersIn[header]; + const headerValue = Array.isArray(r.headersIn[header]) + ? r.headersIn[header].join(", ") + : r.headersIn[header]; if (headerValue.length > MAX_HEADER_LENGTH && !LENGTH_EXCEPTIONS[key]) { cleanHeaders[key] = "[REDACTED_SIZE_LIMIT]";