{"record":{"id":"c4c3b8ffab94950d","repo":"crowdsecurity/crowdsec","slug":"rule-has-no-zones-and-or-or-children","errorCode":null,"errorMessage":"rule has no zones, 'and', or 'or' children","messagePattern":"rule has no zones, 'and', or 'or' children","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/appsec_rule/modsecurity.go","lineNumber":182,"sourceCode":"\n\t// All Or children's DNFs are concatenated into one, then treated as a single AND term\n\tif len(rule.Or) > 0 {\n\t\tvar orDNF [][]*CustomRule\n\n\t\tfor i := range rule.Or {\n\t\t\tchildDNF, err := flattenToDNF(&rule.Or[i])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\n\t\t\torDNF = append(orDNF, childDNF...)\n\t\t}\n\n\t\tparts = append(parts, orDNF)\n\t}\n\n\tif len(parts) == 0 {\n\t\treturn nil, errors.New(\"rule has no zones, 'and', or 'or' children\")\n\t}\n\n\tif len(parts) == 1 {\n\t\treturn parts[0], nil\n\t}\n\n\t// Multiple parts: cross-product them all\n\tresult := parts[0]\n\n\tfor i := 1; i < len(parts); i++ {\n\t\tvar err error\n\n\t\tresult, err = crossProduct(result, parts[i])\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/appsec_rule/modsecurity.go#L164-L200","documentation":"flattenToDNF collects the DNF parts from a rule's zones and its and/or children; if the resulting parts list is empty, the rule contained nothing matchable at all (no zones and no children producing groups). Compiling such a rule would produce an empty or invalid modsecurity rule, so the build is aborted with this error.","triggerScenarios":"Calling Build/flattenToDNF with a CustomRule whose zones is empty/non-nil in a way that yields no leaf groups, or whose and/or children all expand to empty groups (e.g. `and: []` or `or: []` with no zones).","commonSituations":"A rule with only `and: []` or `or: []` keys and no zones; a programmatically built rule with zero-length child slices; a generator emitting empty group containers.","solutions":["Give the rule real content: zones plus a match, or non-empty and/or children","Remove empty `and: []` / `or: []` scaffolding that has no children","Validate rules before compiling: each leaf must have zones, each group must have at least one child"],"exampleFix":"// before\nrule := &CustomRule{And: []*CustomRule{}}\n\n// after\nrule := &CustomRule{And: []*CustomRule{{Zones: []string{\"URI\"}, Match: Match{Type: \"contains\", Value: \"x\"}}}}","handlingStrategy":"validation","validationCode":"if len(rule.Zones) == 0 && len(rule.And) == 0 && len(rule.Or) == 0 {\n    return fmt.Errorf(\"rule is empty: no zones, and, or children\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject empty and/or containers in generators instead of emitting them","Sanity-check compiled rule counts after loading a collection"],"tags":["appsec","rules","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}