Skip to content

A base-level $ref silently drops the referenced schema's object-level constraints #182

Description

@wol-soft

Summary

When a schema file's entire top level is a single {"$ref": "..."}, only the referenced schema's
properties are transferred onto the referencing schema. Its own object-level constraints are
dropped and never validated:

  • additionalProperties
  • minProperties / maxProperties
  • propertyNames
  • any root-level composition (allOf / anyOf / oneOf / if)

Input that violates those constraints is accepted.

Why this is worse than a missing check

For the composition case the generated object can be constructed in a state its own type contract
forbids. The failure then surfaces later, at an arbitrary call site, as a plain PHP TypeError
rather than a validation exception at construction time.

Reproduction

Root.json:

{
  "$ref": "Composed.json"
}

Composed.json:

{
  "type": "object",
  "allOf": [
    {
      "type": "object",
      "required": ["name"],
      "properties": {
        "name": {
          "type": "string"
        }
      }
    }
  ]
}

new Root([]) violates the allOf branch's required: ["name"].

Expected: a validation exception at construction.

Actual: the constructor succeeds. name was promoted to a non-nullable string because it is
required, but nothing populated it, so the first call to the getter throws:

TypeError: Root::getName(): Return value must be of type string, null returned

A second reproduction for the non-composition constraints — referenced schema with
"additionalProperties": false and "minProperties": 2:

new Root(['name' => 'Hannes', 'extra' => 1]);  // accepted, additionalProperties not enforced
new Root(['name' => 'Hannes']);                // accepted, minProperties not enforced

Cause

The referenced schema enforces these through its own base validators, not through validators
attached to the individual properties — those are merged/redirected and carry no validation of
their own. The base-level reference transfer copied only the properties.

Affected versions

Present in 0.26.2 (BasereferenceProcessor) and on master after the processor rework
(PropertyFactory::processBaseReference()), so this has been present across the refactor rather
than introduced by it.

Fix

Fixed in #166: the referenced schema's base validators are now transferred alongside its
properties. Covered by tests for both the composition case and the
additionalProperties/minProperties/propertyNames case.

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