@@ -82,7 +82,9 @@ check_echo_notifier() {
8282 local plugin=" $1 " path=" $2 " shape=" $3 " site found=" ko" code r=0
8383 site=" ${plugin} .example.com"
8484 echo " ℹ️ [$plugin ] provoking deny on http://$site /blocked ..."
85- code=" $( curl -s -o /dev/null -w " %{http_code}" -H " Host: $site " http://localhost/blocked) "
85+ # Send a credential header: the notifier must redact it (see redact_header in
86+ # each plugin's *_helpers.lua) before forwarding the request to the sink.
87+ code=" $( curl -s -o /dev/null -w " %{http_code}" -H " Host: $site " -H " Cookie: redactme-supersecret" http://localhost/blocked) "
8688 if [ " $code " != " 403" ] ; then
8789 echo " ❌ [$plugin ] expected 403 on /blocked, got $code "
8890 fail=1
@@ -120,7 +122,7 @@ check_echo_notifier matrix "/_matrix/client" '"formatted_body"'
120122# DISCORD_RETRY_IF_LIMITED=yes the plugin retries once, so the mock should see
121123# two requests to /discord.
122124echo " ℹ️ [discord] provoking deny (retry path) ..."
123- code=" $( curl -s -o /dev/null -w " %{http_code}" -H " Host: discord.example.com" http://localhost/blocked) "
125+ code=" $( curl -s -o /dev/null -w " %{http_code}" -H " Host: discord.example.com" -H " Cookie: redactme-supersecret " http://localhost/blocked) "
124126if [ " $code " != " 403" ] ; then
125127 echo " ❌ [discord] expected 403 on /blocked, got $code "
126128 fail=1
@@ -149,12 +151,38 @@ else
149151 fail=1
150152fi
151153
154+ # discord posts to the ratelimit sink (not the echo mock), so assert its
155+ # header redaction separately: the Cookie sent on the deny must be [REDACTED].
156+ if docker compose logs ratelimit 2> /dev/null | grep -qF " redactme-supersecret" ; then
157+ echo " ❌ [discord] sensitive header value leaked to the notifier payload"
158+ fail=1
159+ elif docker compose logs ratelimit 2> /dev/null | grep -qF " [REDACTED]" ; then
160+ echo " ✔️ [discord] sensitive header redacted in the notifier payload"
161+ else
162+ echo " ❌ [discord] expected [REDACTED] marker missing from the notifier payload"
163+ fail=1
164+ fi
165+
152166# Cross-check the denied payload reached the echo mock (slack/webhook).
153167if ! docker compose logs mock 2> /dev/null | grep -qF " Denied request for IP" ; then
154168 echo " ❌ echo mock never received a denied-request payload"
155169 fail=1
156170fi
157171
172+ # Sensitive-header redaction: the Cookie value sent on the denied requests must
173+ # never reach the notification sink — it is replaced by [REDACTED]. This guards
174+ # the redact_header() logic shared by all notifier plugins (slack/webhook/matrix
175+ # post their header table to the echo mock).
176+ if docker compose logs mock 2> /dev/null | grep -qF " redactme-supersecret" ; then
177+ echo " ❌ sensitive header value leaked to the notifier payload"
178+ fail=1
179+ elif docker compose logs mock 2> /dev/null | grep -qF " [REDACTED]" ; then
180+ echo " ✔️ sensitive header redacted in the notifier payload"
181+ else
182+ echo " ❌ expected [REDACTED] marker missing from the notifier payload"
183+ fail=1
184+ fi
185+
158186if [ " $fail " -ne 0 ] ; then
159187 docker compose logs
160188 docker compose down -v
0 commit comments