Skip to content

Commit

Permalink
fix(core): validation against header regex match
Browse files Browse the repository at this point in the history
Fixup #12365
Fix KAG-4788

Co-authored-by: Qi <[email protected]>
  • Loading branch information
StarlightIbuki and ADD-SP committed Jun 25, 2024
1 parent bd2c233 commit 2fb012c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
5 changes: 1 addition & 4 deletions kong/db/schema/entities/routes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -196,10 +196,7 @@ local routes = {
},
},
},
values = {
type = "array",
elements = typedefs.regex_or_plain_pattern,
}
values = typedefs.header_regex_or_plain_pattern,
} },

{ regex_priority = { description = "A number used to choose which route resolves a given request when several routes match it using regexes simultaneously.", type = "integer", default = 0 }, },
Expand Down
23 changes: 13 additions & 10 deletions kong/db/schema/typedefs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,13 @@ end


local function is_valid_regex_pattern(pattern)
local regex = pattern:sub(2) -- remove the leading "~"
-- the value will be interpreted as a regex by the router; but is it a
-- valid one? Let's dry-run it with the same options as our router.
local _, _, err = ngx.re.find("", regex, "aj")
local _, _, err = ngx.re.find("", pattern, "a")
if err then
return nil,
string.format("invalid regex: '%s' (PCRE returned: %s)",
regex, err)
pattern, err)
end

return true
Expand All @@ -526,7 +525,7 @@ local function validate_path_with_regexes(path)
end

if is_regex_pattern(path) then
return is_valid_regex_pattern(path)
return is_valid_regex_pattern(path:sub(2))
end

-- prefix matching. let's check if it's normalized form
Expand All @@ -539,12 +538,13 @@ local function validate_path_with_regexes(path)
end


local function validate_regex_or_plain_pattern(pattern)
if not is_regex_pattern(pattern) then
local function validate_header_regex_or_plain_pattern(patterns)
-- when there's only 1 pattern and it starts with "~*", it's a regex pattern
if #patterns ~= 1 or patterns[1]:sub(1, 2) ~= "~*" then
return true
end

return is_valid_regex_pattern(pattern)
return is_valid_regex_pattern(patterns[1]:sub(3))
end


Expand Down Expand Up @@ -646,9 +646,12 @@ typedefs.headers = Schema.define {
description = "A map of header names to arrays of header values."
}

typedefs.regex_or_plain_pattern = Schema.define {
type = "string",
custom_validator = validate_regex_or_plain_pattern,
typedefs.header_regex_or_plain_pattern = Schema.define {
type = "array",
elements = {
type = "string",
},
custom_validator = validate_header_regex_or_plain_pattern,
description = "A string representing a regex or plain pattern."
}

Expand Down
13 changes: 12 additions & 1 deletion spec/01-unit/01-db/01-schema/06-routes_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -624,14 +624,25 @@ describe("routes schema (flavor = " .. flavor .. ")", function()

it("value must be a plain pattern or a valid regex pattern", function()
local route = {
headers = { location = { "~[" } },
headers = { location = { "~*[" } },
protocols = { "http" },
}

local ok, err = Routes:validate(route)
assert.falsy(ok)
assert.match("invalid regex", err.headers[1])
end)

it("value must be a plain pattern or a valid regex pattern", function()
local route = {
headers = { location = { "~*[", "~*" } },
protocols = { "http" },
}

local ok, err = Routes:validate(route)
assert.truthy(ok)
assert.match(nil, err)
end)
end)

describe("methods attribute", function()
Expand Down

0 comments on commit 2fb012c

Please sign in to comment.