Skip to content

bug: request-validation plugin is buggy when header 'Content-Type: application/x-www-form-urlencoded' has parameters #11687

Description

@bradib0y

Current Behavior

The Content-Type header value has this required format, according to RFC 7231:

  • media-type [; parameters]
  • media-type = type "/" subtype

Valid Examples:
Content-Type: application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded; charset=utf-8

The second example is parameterized. In that case, APISIX request-validation plugin will fail with the following error:
parse error: Invalid numeric literal at line 1, column 8

Removing the plugin is the only solution, if you have a parameterized Content-Type header.

Expected Behavior

It should accept the parameterized content type header.

I found the issue in the source code. The body is treated as JSON by default, then the form data type is check with an exact header value match, so if it is extended by params, the body will be treated as JSON, and failing with the validation on the first character, because it is not { or [ as expected with JSON.

Source from the repo: apisix\plugins\request-validation.lua

local body_is_json = true
if headers["content-type"] == "application/x-www-form-urlencoded" then -- 🔴 the issue is here. It should be a Lua equivalent of "startsWith" not "=="
    -- use 0 to avoid truncated result and keep the behavior as the
    -- same as other platforms
    req_body, err = ngx.decode_args(body, 0)
    body_is_json = false
else -- JSON as default
    req_body, err = core.json.decode(body)
end

Error Logs

Response

parse error: Invalid numeric literal at line 1, column 8

APISIX logs

2024/10/28 17:04:41 [warn] 24#24: *2233722 [lua] utils.lua:418: find_and_log(): Using openid-connect introspection_endpoint with no TLS is a security risk, context: ngx.timer
2024/10/28 17:04:41 [warn] 24#24: *2233722 [lua] utils.lua:458: check_tls_bool(): Keeping ssl_verify disabled in openid-connect configuration is a security risk, context: ngx.timer
2024/10/28 17:04:49 [error] 10#10: *2383148 [lua] request-validation.lua:101: phasefunc(): failed to decode the req body: Expected value but found invalid token at character 1, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
2024/10/28 17:04:49 [warn] 10#10: *2383148 [lua] plugin.lua:1171: runplugin(): request-validation exits with http status code 400, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
10.111.4.1 - apisix-myproject [28/Oct/2024:17:04:47 +0000] apisixmyteam.myteam.mycompany.dev "POST /auth/login HTTP/2.0" 200 2345 0.076 "-" "curl/7.81.0" 10.99.211.21:80 200 0.076 "http://apisixmyteam.myteam.mycompany.dev/auth/realms/myproject-dev/protocol/openid-connect/token"
10.111.4.1 - - [28/Oct/2024:17:04:49 +0000] apisixmyteam.myteam.mycompany.dev "POST /auth/login HTTP/2.0" 400 35 0.000 "-" "curl/7.81.0" - - - "http://apisixmyteam.myteam.mycompany.dev"
10.111.4.1 - apisix-myproject [28/Oct/2024:17:05:45 +0000] apisixmyteam.myteam.mycompany.dev "POST /auth/login HTTP/2.0" 200 2345 0.066 "-" "curl/7.81.0" 10.99.211.21:80 200 0.066 "http://apisixmyteam.myteam.mycompany.dev/auth/realms/myproject-dev/protocol/openid-connect/token"
2024/10/28 17:06:01 [error] 15#15: *2385302 [lua] request-validation.lua:101: phasefunc(): failed to decode the req body: Expected value but found invalid token at character 1, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
2024/10/28 17:06:01 [warn] 15#15: *2385302 [lua] plugin.lua:1171: runplugin(): request-validation exits with http status code 400, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
10.111.4.1 - - [28/Oct/2024:17:06:01 +0000] apisixmyteam.myteam.mycompany.dev "POST /auth/login HTTP/2.0" 400 35 0.000 "-" "curl/7.81.0" - - - "http://apisixmyteam.myteam.mycompany.dev"
2024/10/28 17:06:28 [error] 9#9: *2386078 [lua] request-validation.lua:101: phasefunc(): failed to decode the req body: Expected value but found invalid token at character 1, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
2024/10/28 17:06:28 [warn] 9#9: *2386078 [lua] plugin.lua:1171: runplugin(): request-validation exits with http status code 400, client: 10.111.4.1, server: , request: "POST /auth/login HTTP/2.0", host: "apisixmyteam.myteam.mycompany.dev"
10.111.4.1 - - [28/Oct/2024:17:06:28 +0000] apisixmyteam.myteam.mycompany.dev "POST /auth/login HTTP/2.0" 400 35 0.000 "-" "curl/7.81.0" - - - "http://apisixmyteam.myteam.mycompany.dev"

Steps to Reproduce

  1. create an apisix route
  2. configure request-validation plugin with any settings
  3. send a request with the following header, it will work: Content-Type: application/x-www-form-urlencoded
  4. send a request with the following header, it won't work: Content-Type: application/x-www-form-urlencoded; charset=utf-8

`

Environment

  • APISIX version (run apisix version): 3.11.0
  • Operating system (run uname -a): Linux apisix-data-plane-7cd95bcd7-hm9ss 6.6.28-talos change: added doc of how to load plugin. #1 SMP Thu Apr 18 16:21:02 UTC 2024 x86_64 GNU/Linux
  • OpenResty / Nginx version (run openresty -V or nginx -V): nginx version: openresty/1.25.3.2
  • etcd version, if relevant (run curl http://127.0.0.1:9090/v1/server_info):
  • APISIX Dashboard version, if relevant:
  • Plugin runner version, for issues related to plugin runners:
  • LuaRocks version, for installation issues (run luarocks --version):

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingplugin

Type

No type

Projects

Status
✅ Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions