From db560286e3a63dfab5fb251cc7094524031e685d Mon Sep 17 00:00:00 2001 From: AlinsRan Date: Mon, 22 Jun 2026 14:06:35 +0800 Subject: [PATCH] fix(response-rewrite): do not empty body when base64 secret is invalid When body is a secret reference and body_base64 is true, the config-time base64 validation is skipped because the value is unknown until runtime. If the resolved secret is not valid base64, ngx.decode_base64 returned nil and the response body was silently emptied. Log an error and leave the upstream response body unchanged instead. Add a test using an $env:// reference resolving to a non-base64 value. Signed-off-by: AlinsRan --- apisix/plugins/response-rewrite.lua | 17 +++++++--- t/secret/central-secret-refs.t | 52 +++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/apisix/plugins/response-rewrite.lua b/apisix/plugins/response-rewrite.lua index b86604a36d60..61390e9104ad 100644 --- a/apisix/plugins/response-rewrite.lua +++ b/apisix/plugins/response-rewrite.lua @@ -294,12 +294,21 @@ function _M.body_filter(conf, ctx) end if conf.body then - ngx.arg[2] = true + local body = conf.body if conf.body_base64 then - ngx.arg[1] = ngx.decode_base64(conf.body) - else - ngx.arg[1] = conf.body + body = ngx.decode_base64(conf.body) + if not body then + -- conf.body may be a resolved secret reference whose value is + -- not valid base64; the config-time check is skipped for secret + -- references, so guard here instead of silently emptying the body. + core.log.error("response-rewrite: body is configured with ", + "body_base64 = true but its value is not valid ", + "base64; leaving the response body unchanged") + return + end end + ngx.arg[2] = true + ngx.arg[1] = body end end diff --git a/t/secret/central-secret-refs.t b/t/secret/central-secret-refs.t index 47f99675cf0d..55cc759148ad 100644 --- a/t/secret/central-secret-refs.t +++ b/t/secret/central-secret-refs.t @@ -18,6 +18,7 @@ BEGIN { $ENV{TEST_HOST} = "test.example.com"; $ENV{TEST_URI} = "/hello"; $ENV{TEST_HEADER_VALUE} = "from-env"; + $ENV{TEST_NOT_BASE64} = "@@@ not valid base64 @@@"; } use t::APISIX 'no_plan'; @@ -374,3 +375,54 @@ openid-connect has required field client_secret that must be a string. } --- response_body success + + + +=== TEST 13: response-rewrite body_base64 with a secret-ref resolving to non-base64 +The config-time base64 check is skipped for secret references, so this only +fails at runtime; the response body must be left unchanged rather than emptied. +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "uri": "/rr-b64-secret", + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + }, + "response-rewrite": { + "body": "$env://TEST_NOT_BASE64", + "body_base64": true + } + }, + "upstream": { + "type": "roundrobin", + "nodes": { + "127.0.0.1:1980": 1 + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + return ngx.say(body) + end + ngx.say("success") + } + } +--- response_body +success + + + +=== TEST 14: invalid base64 secret leaves the upstream body unchanged and logs an error +--- request +GET /rr-b64-secret +--- response_body +hello world +--- error_log +its value is not valid base64