Skip to content

Design Guide: explicit guidance on additionalProperties in request body schemas #3

Description

@hdamker

Problem description

The Design Guide does not say how request bodies should handle JSON fields that a client supplies but the schema does not declare. Two sections point in opposite directions:

  • §6.1 (Good practices for securing REST APIs) says: "Validate the request parameters as the first step before they reach the application logic. Implement strong validation checks and immediately reject the request if validation fails."
  • §7 (Compatibility Management) endorses Postel's Law: "Be conservative in what you do, be liberal in what you accept from others" — in the immediate context of fields that have been removed from the spec.

Two further pieces of the existing framework matter here:

  • §3.2 already defines 400 INVALID_ARGUMENT with the message "Request body does not comply with the schema". The error response exists; what's missing is guidance on when servers are expected to raise it for unknown fields.
  • OAS 3.0.3 default for additionalProperties is true. Any object schema that does not explicitly set the keyword is implicitly permissive.

Today this combination leaves the policy undefined at the Design Guide level. The OWASP API3:2023 (Broken Object Property Level Authorization) Spectral rules owasp:api3:2023-no-additionalProperties and owasp:api3:2023-constrained-additionalProperties were added per camaraproject#539, but both are currently set to off in .spectral-r4.yaml pending the resolution of camaraproject#615.

A practical observation about the rules themselves: their given JSONPath matches only object schemas where additionalProperties is explicitly truthy. Schemas that omit the keyword (relying on the OAS 3.0.3 default of true) are not matched. I verified this by re-enabling both rules locally and linting QualityOnDemand's three API specs — 0 findings, because QualityOnDemand never sets additionalProperties explicitly. So even un-muted, the rules would not nudge the current default-permissive practice; they would only flag schemas where someone wrote additionalProperties: true or a non-boolean schema (the HTTPSettings.headers case in CAMARA_event_common.yaml).

That's the gap I'd like to discuss: the Design Guide doesn't take a position, and the existing rule layer can't substitute for one.

Possible evolution

I'd propose adding explicit guidance with this shape (open to refinement):

  1. Default for new CAMARA APIs: request body schemas SHOULD set additionalProperties: false. Unknown fields are rejected with 400 INVALID_ARGUMENT per §3.2.
  2. Documented exceptions where permissive additionalProperties is justified: each case must (a) cite an external spec it inherits from, or (b) document an explicit API-level extensibility requirement. In both cases, the schema should constrain the size with maxProperties to reduce mass-assignment surface.
  3. Reconciling with the §7 Postel reference: scope the Postel framing to value tolerance (e.g., accept multiple date formats) rather than field-set tolerance. The existing §7 "tolerant reader" guidance for consumers (clients tolerating server responses) is unaffected.

Alternative solution

Document the existing permissive default explicitly — recommend that request bodies leave additionalProperties unset, matching the OAS 3.0.3 default — and read §6.1's "strong validation" as applying only to declared parameters. This aligns with §7's existing Postel framing but leaves the OWASP API3:2023 surface unmitigated and means the S-314 / S-316 rules can't be un-muted. Listed here for completeness; I think the strict direction is the right one.

Additional context

  • CAMARA's versioning contract does not need permissiveness. Semver backwards compatibility in CAMARA is "old client + new server": adding optional fields server-side is fine because old clients don't send them. Strict request validation does not interfere with that — strict rejects fields the client should not have sent in the first place against the version they're targeting. The opposite direction (new client + old server) is a version-negotiation question, not a Postel-vs-strict question, and is unchanged here.
  • Transition for existing APIs. Adding additionalProperties: false to an API that previously left it implicit is technically a tightening of validation. Same pattern as the OWASP rules introduced via Review of checks for the OWASP API Security Top 10 2023 for CAMARA camaraproject/Commonalities#539 — start as warnings, tighten over time. Existing APIs would adopt strict at the next MAJOR version bump; new APIs from day one.
  • Current practice across CAMARA (sampled 10 API repos): roughly a quarter use explicit additionalProperties: false on at least some request schemas (CapabilitiesAndRuntimeRestrictions, ApplicationEndpointRegistration, OptimalEdgeDiscovery, SimpleEdgeDiscovery, TrafficInfluence, WebRTC); the rest leave it default-permissive (QualityOnDemand, DeviceLocation, NumberVerification, others). The one explicit permissive case is HTTPSettings.headers, which inherits from the CloudEvents HTTP Protocol Binding spec — already being separately worked on in HTTPSettings.headers in CAMARA_event_common.yaml: remove or constrain? camaraproject/Commonalities#615.
  • Related closed work: Discussion on owasp:api3:2023 (Broken Object Property Level Authorization) rules camaraproject/Commonalities#549 (per-rule inventory follow-up to Review of checks for the OWASP API Security Top 10 2023 for CAMARA camaraproject/Commonalities#539), Align event-subscription-template.yaml with OWASP requirements camaraproject/Commonalities#585 (event-subscription-template OWASP alignment).
  • Ask to implementations: if you operate a CAMARA API in production or pilot, please comment with how your server currently handles unknown JSON fields on request bodies — strict reject, silent ignore, log + accept, other. This will help calibrate whether existing implementations are already aligned with a strict default or whether moving there requires a transition.
  • Mass-assignment background (OWASP API3:2023): the typical exploit is a client sending an extra field (e.g., is_admin: true, price_override: 0.01) that a permissive server deserializes onto an internal object whose property of the same name was never meant to be client-controllable. Schema-level additionalProperties: false is the first wall, with framework-level allowlists as defence in depth.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions