fix: reject non-mapping entries under networks and models - #932
Merged
ndeloof merged 1 commit intoSep 18, 2026
Merged
Conversation
The compose-spec schema allowed a key under the top-level networks and models blocks to bypass the patternProperties check, since additionalProperties wasn't set to false like volumes/secrets/configs already do. A malformed key such as "/" therefore skipped schema validation entirely and reached transformMaybeExternal with its raw scalar value, which panicked on an unchecked type assertion instead of surfacing a validation error. Align the networks and models schema entries with their siblings, and make transformMaybeExternal return an error instead of panicking if a schema gap lets a non-mapping value through again. Signed-off-by: Guillaume Lours <glours@users.noreply.github.com>
ndeloof
reviewed
Sep 18, 2026
ndeloof
left a comment
Collaborator
There was a problem hiding this comment.
Reviewed with local verification on the head:
The fix is correct and complete.
- Reproduced the failure mode on the base commit with this PR's tests only:
transformMaybeExternal(1, …)panics with the exact interface-conversion described (DDB-706), and the malformed/:key sails through validation. On the head both surface proper errors. - Schema parity verified programmatically: all six top-level resource sections (
services,networks,volumes,secrets,configs,models) now carry the samepatternProperties+additionalProperties: falseshape. - No
x-*regression: extension-style keys match^[a-zA-Z0-9._-]+$and keep validating as resource names, exactly like undervolumestoday. - The test split is right: the loader test locks the schema rejection (its
/:entry carries a valid mapping body, so it exercises the key check, not the panic), while the transform unit test locks the panic→error conversion as defense in depth against future schema gaps. loader,loader/tests,transformandschemasuites all green locally on the head.
One follow-up needed after merge: compose-spec/compose-spec's schema/compose-spec.json does not have these two additionalProperties entries yet — this PR breaks the byte-identity between the two schema copies that compose-spec's CI validates. A companion compose-spec PR should mirror the change.
ndeloof
approved these changes
Sep 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The compose-spec schema allowed a key under the top-level networks and models blocks to bypass the patternProperties check, since additionalProperties wasn't set to false like volumes/secrets/configs already do. A malformed key such as "/" therefore skipped schema validation entirely and reached transformMaybeExternal with its raw scalar value, which panicked on an unchecked type assertion instead of surfacing a validation error.
Align the networks and models schema entries with their siblings, and make transformMaybeExternal return an error instead of panicking if a schema gap lets a non-mapping value through again.
fix https://docker.atlassian.net/browse/DDB-706