fastify / fastify/fast-json-stringify
Sibling required keyword is dropped when a property uses $ref to an external schema
- Dominant language
- JavaScript
- Stars
- 3.7k
- Forks
- 226
- Avg merge
- 1d 59m
- Merged PRs (30d)
- 3
Description
**What's wrong**
When a property both references an external schema with `$ref` and adds its own
sibling keywords (like `required`), the serializer throws away those sibling
keywords. An object that is missing a required field is accepted and serialized
as valid instead of raising a validation error, so incomplete data passes
through silently.
**Where**
`index.js`, in `buildValue`:
https://github.com/fastify/fast-json-stringify/blob/7fad3c2d6305/index.js#L1300-L1303
```javascript
if (schema.$ref) {
location = resolveRef(context, location)
schema = location.schema
}
```
Resolving the reference replaces the local schema wholesale, so any sibling
keywords on the referencing schema (for example `required`) are gone before the
serializer is generated. The `getValidatorSchemaRef` guard added recently
(`index.js:113`, treats a schema with more than one key as non-pure) correctly
protects validator reference selection in `buildOneOf`/`buildIfThenElse`, but it
does not stop `buildValue` from dereferencing and discarding siblings.
**How it manifests**
1. Register an external `Foo` schema that requires `value`.
2. Create a root schema with a property `x` that uses `$ref: Foo` plus a sibling
`required: ['extra']`.
3. Build the serializer with `Foo` registered as an external schema.
4. Serialize `{ x: { value: 1, extra: "x" } }` and then `{ x: { value: 1 } }`.
Both inputs serialize successfully, even though the second is missing the
sibling-required `extra`.
**Expected behavior**
The sibling `required` constraint should still apply. When a `$ref` has sibling
keywords, resolve the reference as the base schema and then apply the sibling
constraints on top, keeping the direct-dereference optimization only for a
schema that contains `$ref` alone.
Found while running [Ito](https://ito.ai) (AI code review, free for open source) against recently merged PRs. Full analysis: https://app.ito.ai/share/29ad67b0-500d-45d1-9ffd-df265504fb5f.
Contributor guide
Research direction
Start in index.js at buildValue around the external $ref resolution and read the getValidatorSchemaRef guard near index.js:113 for related behavior. Reproduce the Foo schema case with a $ref and sibling required keyword, then verify that complete input serializes while input missing extra raises a validation error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100