shreemaan-abhishek commented on code in PR #14154:
URL: https://github.com/apache/apisix/pull/14154#discussion_r4479505755


##########
apisix/plugins/openapi-to-mcp/tools/handler.lua:
##########
@@ -124,20 +125,133 @@ local function apply_query_defaults(tool, query)
 end
 
 
-local function build_path(template, path_params)
+-- A separator in a path parameter is percent-encoded, but servers disagree on
+-- whether to preserve it as data or decode it into path syntax. The secure
+-- default is to reject it; a Route may opt in for an API that deliberately
+-- accepts encoded separators.
+local function has_separator(value)
+    -- core.string.find is a plain search; this is a pattern, so it needs
+    -- string.find itself. A backslash is a separator on some servers.
+    return str_find(value, "[/\\]") ~= nil
+end
+
+
+-- Even with encoded separators enabled, refuse values whose components would
+-- be resolved away after a server decodes them. Empty components cover 
leading,
+-- trailing and repeated separators. Both slash spellings are considered: a
+-- backslash is a separator on some servers.
+local function resolved_away(segment)
+    return segment == "" or segment == "." or segment == ".."
+end
+
+
+local function separator_creates_unsafe_component(value)
+    if not has_separator(value) then
+        return false
+    end
+
+    for component in str_gmatch(value .. "/", "([^/\\]*)[/\\]") do
+        if resolved_away(component) then
+            return true
+        end
+    end
+    return false
+end
+
+
+-- Return everything before one of the given URI delimiters. A template
+-- expression name may itself contain a delimiter, so only one outside braces
+-- counts. Parameter values cannot introduce one: escape_uri encodes them.
+local function before_uri_delimiter(value, delimiters)
+    local in_expression = false
+    for index = 1, #value do
+        local char = str_sub(value, index, index)
+        if char == "{" then
+            in_expression = true
+        elseif char == "}" then
+            in_expression = false
+        elseif not in_expression and str_find(delimiters, char, 1, true) then
+            return str_sub(value, 1, index - 1)
+        end
+    end
+    return value
+end
+
+
+local function uri_path(value)
+    return before_uri_delimiter(value, "?#")
+end
+
+
+local function without_fragment(value)
+    return before_uri_delimiter(value, "#")
+end
+
+
+-- The segments of a path, with the empty one a leading or trailing slash
+-- leaves: "/items/x" is { "", "items", "x" }.
+local function path_segments(value)
+    local segments = {}
+    local path = uri_path(value)
+    for segment in str_gmatch(path .. "/", "([^/]*)/") do

Review Comment:
   You are right on both counts, and I had the spec backwards. Fixed in 972d9fb.
   
   I had taken the name restriction from RFC 6570's `varname` rule, which does 
not apply here:
   OAS 3.2.1 derives `path-template` from RFC 3986 section 3.3 and defines the 
name as
   `1*( %x00-7A / %x7C / %x7E-10FFFF )`, every Unicode character except a 
brace. `/` is `%x2F`,
   so it is admitted, and the slash prohibition in that section governs 
parameter values
   instead.
   
   All four rows reproduce, the first one included. `template_segments` now 
splits only on a
   slash outside braces, with the same scan `before_uri_delimiter` uses for `?` 
and `#`. The
   substituted path keeps `path_segments` as it was, for the reason you gave: a 
separator in a
   value is either refused or percent-encoded, so it cannot change the segment 
count.
   
   Regressions added for your table, all four failing without the change:
   
   - `/x/{scope/key}/{id}/..` with `safe`, `ok` is sent as `/x/safe/ok/..`, 
since the literal
     tail is the template's own segment
   - `/x/{a/b}/{c}` with `..`, with `""`, and `/x/{a/b}/{c}/y` with `..` are 
each refused,
     naming `{c}`
   - plus a safe pair, to pin that the splitter did not simply start refusing 
everything
   
   500 cases in `t/plugin/openapi-to-mcp.t` pass and luacheck is clean. The 
same fix is on the
   other implementation as c4fc61c.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to