reitit 2025-02-27

Hi there. I am wondering if someone might have a quick answer for me. When I enter certain random strings as query parameters instead of failing validation, as I would expect, the router simply drops the query parameters when parsing the query string. Is there a reason for this and there is there a way to get the router to rather return a validation error response in the cases where this happens?

Thanks again, I have created a issue for the community to discuss: https://github.com/ring-clojure/ring/issues/522

👍 1

whats the route definition?

are you using malli or something else for coercion?

I am using spec, I will get the route definition now

(s/def ::query-ref-4 (s/keys :opt-un [::agencyids
                                      ::ids
                                      ::versions
                                      ::relations]))

["/datasets"
 {:get {:tags ["Data sets"]
        :summary "Get data sets"
        :parameters {:query ::spec/query-ref-4}
        :handler (partial dataset/read-data-sets connection)}}]

(s/def ::ids (s/or :agencyids ::ids-type
                   :all ::sdmx/all))

(s/def ::ids-type (s/and string? #(re-matches comma-sep-ids-regex %)))

(def comma-sep-ids-regex (re-pattern (str "^(" sdmx/id-regex ")?(," sdmx/id-regex ")*$")))

(def id-regex #"[A-Z0-9](_?[A-Z0-9]+)*")

(s/def ::all (partial = "all"))

Do you think its a regex stuff up? If it is I don't understand why it is dropped when parsing the query string?

:data {:coercion reitit.coercion.spec/coercion
              :muuntaja muuntaja-sdmx-codera
              :middleware [parameters/parameters-middleware
                           muuntaja/format-negotiate-middleware
                           muuntaja/format-response-middleware
                           custom-exception-middleware
                           muuntaja/format-request-middleware
                           coercion/coerce-response-middleware
                           coercion/coerce-request-middleware
                           multipart/multipart-middleware]}

so an optional key gets dropped if it's value doesn't match the schema, hmm

that might just be how spec-tools coercion works, let me check

Thanks, much appreciated

no, I can't get the same behaviour just by playing around with st/coerce and st/conform

let me try to reproduce this more directly

I can also try reproduce a complete example if that would be useful?

yeah, that would help

Perfect, will post when I have something

ah but that is only for body params

... string-transformer includes strip-extra-keys

Good morning @juhoteperi, to confirm, the observed behaviour in this case is the expected behaviour?

But this isn't an extra key in this case, it's specified in ::query-ref-4. Thanks for the example Byron, I'm looking into it now.

Yeah, I can reproduce the problem. Interesting! With

?agencyids=MY_AGENCY&ids=id_1 
I get "Request coercion failed", but with
?agencyids=MY_AGENCY&ids=%3c%%3d77%2a77%%3e
the coercion succeeds and :ids is missing from :query-params

Yep, it is strange, I wonder if this is what is intended

Thanks for reproducing!

I think this is caused by some earlier stage, not reitit coercion. Reitit coercion reads :query-params and writes into :parameters :query

Makes sense

and :query-params is missing the weird :ids even when I comment out

;;:coercion reitit.coercion.spec/coercion

reproduced:

user=> (require '[ring.middleware.params :as p])
nil
user=> (p/assoc-query-params {:query-string "agencyids=MY_AGENCY&ids=ID_1,ID_2"} "UTF-8")
{:query-string "agencyids=MY_AGENCY&ids=ID_1,ID_2", :query-params {"agencyids" "MY_AGENCY", "ids" "ID_1,ID_2"}, :params {"agencyids" "MY_AGENCY", "ids" "ID_1,ID_2"}}
user=> (p/assoc-query-params {:query-string "agencyids=MY_AGENCY&ids=%3c%%3d77%2a77%%3e"} "UTF-8")
{:query-string "agencyids=MY_AGENCY&ids=%3c%%3d77%2a77%%3e", :query-params {"agencyids" "MY_AGENCY"}, :params {"agencyids" "MY_AGENCY"}}

could the problem be that the garbage is not valid UTF-8 so it's being discarded?

In your opinion this is not the behaviour that one would want right?

user=> (java.net.URLDecoder/decode "agencyids=MY_AGENCY&ids=%3c%%3d77%2a77%%3e" (java.nio.charset.Charset/forName "UTF-8"))
Execution error (IllegalArgumentException) at java.net.URLDecoder/decode (URLDecoder.java:237).
URLDecoder: Illegal hex characters in escape (%) pattern - Error at index 0 in: "%3"

that's the exception that gets swallowed

it's hard to say what's the right behaviour here, but yeah, I think I would prefer the params-middleware to return a HTTP 400 Bad Request in cases like this

you could consider filing a bug against ring

Thanks a lot for you help with this, I will think about it

bsless (the maintainer) might have some opinions on this

Great, thanks

Did you encounter this with real use (ring-jetty-adapter, http-kit or such) or only when calling the handler function directly?

And do http clients allow making such a request?

the data looked to me like it was generated by a security audit tool

@joel.kaasinen is exactly right, this issue came up during a penetration test. I can confirm that Firefox allows this request

The backend uses ring-jetty-adapter