Skip to content

Validate resolved nested-param locations before emitting them #150

Description

@numbata

Problem

#149 replaced a hardcoded next unless ... == "query" check in RequestParams#extract_non_body_params with root_location = location_resolver.resolve(...); next if root_location == "body", so any nested Hash root's resolved location that isn't literally "body" now gets stamped directly onto the emitted Parameter — an allowlist became a denylist.

ParamLocationResolver#explicit_location returns whatever string the user typed in documentation: { in: ... } or param_type: ..., downcased, with no further validation, and ApiModel::Parameter doesn't validate location either (@location = location.to_s). Three concrete cases where this now emits an invalid document instead of the previous silent drop:

# 1. Typo'd location — emitted verbatim
optional :filter, type: Hash, documentation: { in: "quer" } do
  optional :kind, type: String
end
# => "in": "quer" in the generated OAS document

# 2. grape-swagger-style formData — emitted, but wrongly lowercased
optional :filter, type: Hash, documentation: { param_type: "formData" } do
  optional :kind, type: String
end
# => "in": "formdata" — wrong even for OAS 2.0, where lib/grape_oas/exporter/oas2/parameter.rb
# correctly writes camelCase "formData" elsewhere

# 3. path on a route with no matching template segment
optional :filter, type: Hash, documentation: { in: "path" } do
  optional :min, type: Integer
end
post("items") { {} }
# => filter[min] emitted with in: "path", required: true (forced by build_parameter),
# but /items has no {filter[min]} path template — invalid per the OAS spec

grape-swagger migrants are called out in AGENTS.md as a worse-informed user segment likely to write param_type: 'formData' by reflex, so case 2 is not just theoretical.

Fix

Restore an allowlist instead of inverting to a denylist in lib/grape_oas/api_model_builders/request_params.rb's nested-param branch:

next unless %w[query header path cookie].include?(root_location)

cookie is valid in OAS 3 and was previously unreachable through this path — worth a regression test alongside the allowlist fix, along with a case for a typo'd/unrecognized location being dropped rather than emitted.

Scope note

This isn't a #149 regression in the sense of "worked before, broken now" — pre-#149 behavior for all three inputs above was a silent drop of the parameter, which was already the bug #149 fixed for the legitimate query/header/path cases. This follow-up narrows the fix so malformed input degrades back to a silent drop instead of an invalid emitted document.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions