@@ -55,6 +55,7 @@ const (
55
55
// - ... zero or more
56
56
//
57
57
// * every specified field or array in s is also specified outside of value validation.
58
+ // * additionalProperties at the root is not allowed.
58
59
func ValidateStructural (s * Structural , fldPath * field.Path ) field.ErrorList {
59
60
allErrs := field.ErrorList {}
60
61
@@ -76,7 +77,7 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path)
76
77
for k , v := range s .Properties {
77
78
allErrs = append (allErrs , validateStructuralInvariants (& v , fieldLevel , fldPath .Child ("properties" ).Key (k ))... )
78
79
}
79
- allErrs = append (allErrs , validateGeneric (& s .Generic , fldPath )... )
80
+ allErrs = append (allErrs , validateGeneric (& s .Generic , lvl , fldPath )... )
80
81
allErrs = append (allErrs , validateExtensions (& s .Extensions , fldPath )... )
81
82
82
83
// detect the two IntOrString exceptions:
@@ -129,14 +130,17 @@ func validateStructuralInvariants(s *Structural, lvl level, fldPath *field.Path)
129
130
}
130
131
131
132
// validateGeneric checks the generic fields of a structural schema.
132
- func validateGeneric (g * Generic , fldPath * field.Path ) field.ErrorList {
133
+ func validateGeneric (g * Generic , lvl level , fldPath * field.Path ) field.ErrorList {
133
134
if g == nil {
134
135
return nil
135
136
}
136
137
137
138
allErrs := field.ErrorList {}
138
139
139
140
if g .AdditionalProperties != nil {
141
+ if lvl == rootLevel {
142
+ allErrs = append (allErrs , field .Forbidden (fldPath .Child ("additionalProperties" ), "must not be used at the root" ))
143
+ }
140
144
if g .AdditionalProperties .Structural != nil {
141
145
allErrs = append (allErrs , validateStructuralInvariants (g .AdditionalProperties .Structural , fieldLevel , fldPath .Child ("additionalProperties" ))... )
142
146
}
0 commit comments