A request carries the same parameter name in the path, the query string and the form body — which value reaches the handler, and why is that risky?
answer
- no standard order across frameworks
- some merge query and form into one map
- an explicit marker makes the clash moot
- danger is two layers reading different copies
- bind once and pass the value down
basics
~20 sNo cross-framework standard exists: some order the sources, others merge query and form into one map where one silently overwrites the other. The danger is two layers reading different copies of the name and disagreeing.
solid answer
~50 sWith an **explicit source marker** there is no clash at all — the marker names the source and the other copies are ignored. The ambiguity is a property of **inferred** binding, and its resolution is framework-specific. Common behaviours are a fixed precedence order, a merged parameter map where one source overwrites the other, or taking the first value found. The risk is that a client can always *add* a copy the endpoint's author never anticipated. When one layer — a gateway rule, an audit log, an authorization check — reads a value from one source while the handler binds it from another, the two disagree about what the request said, and the check no longer guards the operation that runs. The fix is to bind each value from exactly one named source and pass the bound value onward instead of re-reading the request.
go deeper
Know that the same name can arrive in more than one part of a request, and that naming the source on the parameter is what stops the framework from having to guess.
Describe the resolution strategies — fixed order, merged map, first or last value — and say why the answer depends on the framework rather than on a standard.
Show the production failure: a gate or log reading one copy while the handler binds another, and the discipline of binding once and passing the value down.
Own the rule for the whole surface: one canonical source per value, duplicates with different values rejected for anything security-relevant, and no convenience aliases added without a removal plan.
## Why a clash is possible at all The sources a framework binds from are separate namespaces. Nothing prevents `id` from being a route-template capture, a query parameter and a form field on the same request — the client controls two of the three, and can add them at will. If the handler's parameter names the source explicitly, the clash is a non-event: the binder reads the stated source and the other copies are just bytes nobody asked for. The question only bites under **inference**, where the parameter says what it is called but not where it comes from. ## How frameworks actually resolve it There is no common standard, and the plausible designs all exist: - **A fixed precedence order** across sources — frequently path first, then query, then form fields, then the parsed body — with the first source that has the name winning. - **A merged map**: query and form parameters are folded into one name-keyed structure before binding, so whichever is merged second silently overwrites the other. - **First value wins within a source** when a name repeats inside one source, with the rest discarded; other implementations keep the last, and others again collect every value. - **Rejection**: a few binders treat an ambiguous name as a client error rather than guessing. The honest interview answer is not to recite an order but to say that the order is an implementation choice, that it is knowable for the stack in front of you, and that a design depending on it is fragile by construction. ## The failure that actually hurts The interesting damage is not "the wrong value was bound" — it is **two layers reading different copies of the same name**: 1. An edge rule, a routing policy or a rate-limit key is computed from the **query** copy of a tenant or resource id. 2. The handler's parameter is inferred from the **path** capture, or the other way round. 3. A request that carries both passes a check computed on one value while the work is performed on the other. The same split shows up in less dramatic forms that are still expensive: an access log or audit record that records one copy while the mutation used the other, so the trail is wrong exactly for the requests that matter; a cache key derived from the merged parameter map while the handler binds the path copy, so two different results share a key; a metrics label that groups requests by a value the handler never saw. Note that the client does not need to be malicious for this to fire. A link builder that appends a filter to an already-parameterised URL, a retry layer that re-adds parameters, or a proxy that rewrites a path into a query string all produce duplicates without anyone intending an attack. ## Designing it out - **Name the source.** An explicit marker on every client-controlled parameter removes the ambiguity at the point where it would otherwise be decided by convention. - **Bind once, pass it down.** After binding, the value is an argument. Any later layer that needs it should receive it, not reach back into the request and re-derive it — re-deriving is what lets a second copy enter the picture. - **Put the checks on the bound value.** An authorization or policy decision made on the same variable the handler uses cannot be split from the work it authorises. - **Reject rather than prefer, where it matters.** For a security- or billing-relevant identifier, a request that supplies the same name in two sources with different values is better answered with 400 than resolved by a precedence rule the client cannot see. - **Keep one canonical place per value.** If an identifier belongs in the path, it should not also be accepted from the query "for convenience"; convenience aliases are exactly the second copy this whole failure needs. ## How to investigate a live case When a report says the handler acted on a value nobody sent, reproduce it at the request level rather than by calling the handler. Send the same name in two sources with distinguishable values and observe which one the handler receives, then repeat with the sources swapped — that pins the precedence empirically instead of from documentation. Then check the layers *around* the handler for anything that reads the request directly: middleware, logging, policy filters, cache-key builders. The bug is usually not in the binder, which behaved exactly as designed; it is in the second reader that made a different, equally reasonable choice.
- Why is a precedence rule that is documented and stable still a poor thing to rely on?Because it is invisible at the call site and at the edge. A reader of the handler cannot see it, a gateway or logging layer does not implement it, and a client can always add the losing copy. Relying on it means every future reader and every surrounding layer has to know the same rule to stay consistent — and one of them eventually will not.
- When should duplicate names be rejected with 400 rather than resolved?When the value drives a security, tenancy or billing decision, and the two copies disagree. There is no reading of the request that is safely "what the client meant", so answering 400 is both correct and diagnosable. For a harmless display parameter, a documented precedence rule is a reasonable and cheaper choice.
- How would you detect this class of bug before it reaches production?Exercise handlers through real requests, and add cases that deliberately send the same name in two sources with different values, asserting the documented outcome. Separately, review every place outside the handler that reads the request directly: each one is a second reader that can disagree with the binder.
saying these in an interview costs you the question
- Claiming all frameworks resolve a name clash the same way
- Assuming a path value can never be shadowed by a query parameter
- Re-reading the request in middleware instead of using the bound value
- Treating duplicate parameters as impossible unless someone is attacking
- Accepting the same identifier from two sources for client convenience