This is an automated email from the ASF dual-hosted git repository.

shreemaan-abhishek pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new f7139e2ad4 fix(jwe-decrypt,forward-auth): clear forwarded headers when 
skipping (#14096)
f7139e2ad4 is described below

commit f7139e2ad442acc89b36b6a6a92c01bff29e7edd
Author: Shreemaan Abhishek <[email protected]>
AuthorDate: Tue Oct 27 20:22:13 2026 +0800

    fix(jwe-decrypt,forward-auth): clear forwarded headers when skipping 
(#14096)
---
 apisix/plugins/forward-auth.lua        |  4 +++
 apisix/plugins/jwe-decrypt.lua         |  2 ++
 docs/en/latest/plugins/forward-auth.md |  2 +-
 docs/en/latest/plugins/jwe-decrypt.md  |  2 +-
 docs/zh/latest/plugins/forward-auth.md |  2 +-
 docs/zh/latest/plugins/jwe-decrypt.md  |  2 +-
 t/plugin/forward-auth3.t               | 63 ++++++++++++++++++++++++++++++++++
 t/plugin/jwe-decrypt.t                 | 52 ++++++++++++++++++++++++++++
 8 files changed, 125 insertions(+), 4 deletions(-)

diff --git a/apisix/plugins/forward-auth.lua b/apisix/plugins/forward-auth.lua
index d3e965d915..78efc1967f 100644
--- a/apisix/plugins/forward-auth.lua
+++ b/apisix/plugins/forward-auth.lua
@@ -178,6 +178,10 @@ function _M.access(conf, ctx)
 
     local res, err = httpc:request_uri(conf.uri, params)
     if not res and conf.allow_degradation then
+        -- drop client-supplied copies of the configured upstream headers
+        for _, header in ipairs(conf.upstream_headers) do
+            core.request.set_header(ctx, header, nil)
+        end
         return
     elseif not res then
         core.log.warn("failed to process forward auth, err: ", err)
diff --git a/apisix/plugins/jwe-decrypt.lua b/apisix/plugins/jwe-decrypt.lua
index 3a7a150a1f..d9bd91e101 100644
--- a/apisix/plugins/jwe-decrypt.lua
+++ b/apisix/plugins/jwe-decrypt.lua
@@ -217,6 +217,8 @@ end
 function _M.rewrite(conf, ctx)
     -- fetch token and hide credentials if necessary
     local jwe_token, err = fetch_jwe_token(conf, ctx)
+    -- only the decrypted plaintext may reach the upstream in forward_header
+    core.request.set_header(ctx, conf.forward_header, nil)
     if not jwe_token then
         -- If true, throw a 403 error if JWE token is missing from the request.
         -- If false, do not throw an error when JWE token is not found.
diff --git a/docs/en/latest/plugins/forward-auth.md 
b/docs/en/latest/plugins/forward-auth.md
index 1946e4ecae..d099e54c1c 100644
--- a/docs/en/latest/plugins/forward-auth.md
+++ b/docs/en/latest/plugins/forward-auth.md
@@ -72,7 +72,7 @@ If your authorization service decides based on the URI that 
the Upstream service
 | request_method    | string        | False    | GET     | `GET` or `POST`     
      | HTTP method APISIX uses to send requests to the external authorization 
service. When set to `POST`, APISIX will send POST requests along with the 
request body to the external authorization service. If the authorization 
decision depends on request parameters from a POST body, it is recommended to 
extract the necessary fields using `$post_arg.*` and pass them via the 
`extra_headers` field instead. |
 | max_req_body_size | integer       | False    | 67108864 | >= 1               
      | Maximum request body size in bytes buffered and forwarded to the 
external authorization service when `request_method` is `POST`. Requests whose 
body exceeds this limit are rejected with `413`. Prevents unbounded memory 
buffering of large request bodies.                                  |
 | request_headers   | array         | False    |         |                     
      | Client request headers that should be forwarded to the external 
authorization service. If not configured, only headers added by APISIX are 
forwarded, such as `X-Forwarded-*`.                                             
                                                                 |
-| upstream_headers  | array         | False    |         |                     
      | External authorization service response headers that should be 
forwarded to the Upstream service. If not configured, no headers are forwarded 
to the Upstream service.                                                        
                                                              |
+| upstream_headers  | array         | False    |         |                     
      | External authorization service response headers that should be 
forwarded to the Upstream service. If not configured, no headers are forwarded 
to the Upstream service. Client-supplied values of these headers are always 
removed.                                                         |
 | client_headers    | array         | False    |         |                     
      | External authorization service response headers that should be 
forwarded to the client when authentication fails. If not configured, no 
headers are forwarded to the client.                                            
                                                                    |
 | extra_headers     | object        | False    |         |                     
      | Additional headers to send to the authorization service. Support [NGINX 
variables](https://nginx.org/en/docs/http/ngx_http_core_module.html) in values. 
                                                                                
                                                    |
 | timeout           | integer       | False    | 3000    | between 1 and 60000 
inclusive | Timeout for the external authorization service HTTP call in 
milliseconds.                                                                   
                                                                                
                                                            |
diff --git a/docs/en/latest/plugins/jwe-decrypt.md 
b/docs/en/latest/plugins/jwe-decrypt.md
index 135090753d..07144cf31e 100644
--- a/docs/en/latest/plugins/jwe-decrypt.md
+++ b/docs/en/latest/plugins/jwe-decrypt.md
@@ -68,7 +68,7 @@ The decrypted plaintext is forwarded in a request header. For 
sensitive plaintex
 | Name           | Type    | Required | Default       | Valid values | 
Description                                                                     
                                                  |
 | -------------- | ------- | -------- | ------------- | ------------ | 
---------------------------------------------------------------------------------------------------------------------------------
 |
 | header         | string  | True     | Authorization |              | The 
header to get the token from.                                                   
                                              |
-| forward_header | string  | True     | Authorization |              | Name of 
the header that passes the plaintext to the Upstream.                           
                                          |
+| forward_header | string  | True     | Authorization |              | Name of 
the header that passes the plaintext to the Upstream. Any client-supplied value 
of this header is removed.                |
 | strict         | boolean | False    | true          |              | If 
true, return a 403 error when the JWE token is missing. If false, continue when 
the token is not found.                        |
 
 ## Examples
diff --git a/docs/zh/latest/plugins/forward-auth.md 
b/docs/zh/latest/plugins/forward-auth.md
index 6b7117858e..d0983ef4af 100644
--- a/docs/zh/latest/plugins/forward-auth.md
+++ b/docs/zh/latest/plugins/forward-auth.md
@@ -71,7 +71,7 @@ import TabItem from '@theme/TabItem';
 | ssl_verify        | boolean | 否     | true    |                              
 | 如果为 true,则验证授权服务的 SSL 证书。                                                    
                                                                                
                                                                               |
 | request_method    | string  | 否     | GET     | `GET` 或 `POST`               
| APISIX 向外部授权服务发送请求时使用的 HTTP 方法。当设置为 `POST` 时,APISIX 将连同请求体一起向外部授权服务发送 POST 
请求。如果授权决策依赖 POST 正文中的请求参数,建议使用 `$post_arg.*` 提取必要字段并通过 `extra_headers` 
字段传递,而不是发送完整请求体。 |
 | request_headers   | array   | 否     |         |                              
 | 需要转发给外部授权服务的客户端请求头。如果未配置,则只转发 APISIX 添加的请求头,例如 `X-Forwarded-*`。              
                                                                                
                                                       |
-| upstream_headers  | array   | 否     |         |                              
 | 认证通过时,需要转发到 Upstream 服务的外部授权服务响应头。如果未配置,则不转发任何请求头。                           
                                                                                
                                                      |
+| upstream_headers  | array   | 否     |         |                              
 | 认证通过时,需要转发到 Upstream 服务的外部授权服务响应头。如果未配置,则不转发任何请求头。客户端传入的同名请求头总会被移除。          
                                                                                
                                                                       |
 | client_headers    | array   | 否     |         |                              
 | 认证失败时,需要转发给客户端的外部授权服务响应头。如果未配置,则不转发任何响应头。                                    
                                                                                
                                                     |
 | extra_headers     | object  | 否     |         |                              
 | 发送给授权服务的额外请求头,支持在值中使用 [NGINX 
变量](https://nginx.org/en/docs/http/ngx_http_core_module.html)。                  
                                                                                
                                       |
 | timeout           | integer | 否     | 3000    | 1 到 60000 之间(含)         | 
外部授权服务 HTTP 调用的超时时间(毫秒)。                                                        
                                                                                
                                                                         |
diff --git a/docs/zh/latest/plugins/jwe-decrypt.md 
b/docs/zh/latest/plugins/jwe-decrypt.md
index b0cbe51e96..4458873547 100644
--- a/docs/zh/latest/plugins/jwe-decrypt.md
+++ b/docs/zh/latest/plugins/jwe-decrypt.md
@@ -56,7 +56,7 @@ import TabItem from '@theme/TabItem';
 | 名称           | 类型    | 必选项 | 默认值        | 有效值 | 描述                           
                                                                |
 | -------------- | ------- | ------ | ------------- | ------ | 
----------------------------------------------------------------------------------------------
 |
 | header         | string  | 是     | Authorization |        | 用于获取令牌的请求头。      
                                                                   |
-| forward_header | string  | 是     | Authorization |        | 传递明文给上游的请求头名称。   
                                                                |
+| forward_header | string  | 是     | Authorization |        | 
传递明文给上游的请求头名称。客户端传入的同名请求头会被移除。                                   |
 | strict         | boolean | 否     | true          |        | 如果为 true,当请求中缺少 
JWE 令牌时抛出 403 错误。如果为 false,当找不到 JWE 令牌时不抛出错误。 |
 
 ## 使用示例
diff --git a/t/plugin/forward-auth3.t b/t/plugin/forward-auth3.t
index 1bb32c7aaa..afd12d45e7 100644
--- a/t/plugin/forward-auth3.t
+++ b/t/plugin/forward-auth3.t
@@ -105,3 +105,66 @@ GET /hello
 X-User-ID: injected-value
 --- response_body_unlike eval
 qr/x-user-id/
+
+
+
+=== TEST 3: setup route with an unavailable auth server and allow_degradation
+--- config
+    location /t {
+        content_by_lua_block {
+            local data = {
+                {
+                    url = "/apisix/admin/routes/crashed-auth",
+                    data = [[{
+                        "plugins": {
+                            "serverless-pre-function": {
+                                "phase": "rewrite",
+                                "functions" : ["return function() 
require(\"apisix.core\").response.exit(444); end"]
+                            }
+                        },
+                        "upstream_id": "u1",
+                        "uri": "/crashed-auth"
+                    }]],
+                },
+                {
+                    url = "/apisix/admin/routes/2",
+                    data = [[{
+                        "plugins": {
+                            "forward-auth": {
+                                "uri": "http://127.0.0.1:1984/crashed-auth";,
+                                "upstream_headers": ["X-User-ID"],
+                                "allow_degradation": true
+                            },
+                            "serverless-post-function": {
+                                "phase": "access",
+                                "functions": [
+                                    "return function(conf, ctx) local core = 
require(\"apisix.core\"); core.response.exit(200, core.request.headers(ctx)); 
end"
+                                ]
+                            }
+                        },
+                        "upstream_id": "u1",
+                        "uri": "/degraded"
+                    }]],
+                }
+            }
+
+            local t = require("lib.test_admin").test
+
+            for _, data in ipairs(data) do
+                local code, body = t(data.url, ngx.HTTP_PUT, data.data)
+                ngx.say(body)
+            end
+        }
+    }
+--- response_body eval
+"passed\n" x 2
+
+
+
+=== TEST 4: client-supplied upstream_headers are cleared when the auth server 
is unavailable
+--- request
+GET /degraded
+--- more_headers
+X-User-ID: injected-value
+--- response_body_unlike eval
+qr/x-user-id/
diff --git a/t/plugin/jwe-decrypt.t b/t/plugin/jwe-decrypt.t
index deb68a3fb2..cdf843b217 100644
--- a/t/plugin/jwe-decrypt.t
+++ b/t/plugin/jwe-decrypt.t
@@ -929,3 +929,55 @@ status: 200
     }
 --- response_body
 status: 400 body: {"message":"unsupported alg or enc in JWE token"}
+
+
+
+=== TEST 38: enable jwe-decrypt with strict=false and a separate forward_header
+--- config
+    location /t {
+        content_by_lua_block {
+            local t = require("lib.test_admin").test
+            local code, body = t('/apisix/admin/routes/12',
+                ngx.HTTP_PUT,
+                [[{
+                    "plugins": {
+                        "jwe-decrypt": {
+                            "header": "Authorization",
+                            "forward_header": "X-Decrypted-Auth",
+                            "strict": false
+                        },
+                        "serverless-post-function": {
+                            "phase": "access",
+                            "functions": [
+                                "return function(conf, ctx) local core = 
require(\"apisix.core\"); core.response.exit(200, core.request.headers(ctx)); 
end"
+                            ]
+                        }
+                    },
+                    "upstream": {
+                        "nodes": {
+                            "127.0.0.1:1980": 1
+                        },
+                        "type": "roundrobin"
+                    },
+                    "uri": "/hello-forward-header"
+                }]]
+                )
+
+            if code >= 300 then
+                ngx.status = code
+            end
+            ngx.say(body)
+        }
+    }
+--- response_body
+passed
+
+
+
+=== TEST 39: client-supplied forward_header is dropped when the token is 
missing
+--- request
+GET /hello-forward-header
+--- more_headers
+X-Decrypted-Auth: client-value
+--- response_body_unlike eval
+qr/x-decrypted-auth/

Reply via email to