{"record":{"id":"7a1feddbde62728a","repo":"crowdsecurity/crowdsec","slug":"on-challenge-submit-hooks-are-only-valid-in-band","errorCode":null,"errorMessage":"on_challenge_submit hooks are only valid in-band, not under outofband","messagePattern":"on_challenge_submit hooks are only valid in-band, not under outofband","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/appsec.go","lineNumber":1012,"sourceCode":"\tif wc.InBand != nil {\n\t\tif ret.InBandHooks, err = buildPhaseHooks(ctx, \"inband\",\n\t\t\twc.InBand.PreEval, wc.InBand.PostEval, wc.InBand.OnMatch, patcher); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\tif wc.OutOfBand != nil {\n\t\tif ret.OutOfBandHooks, err = buildPhaseHooks(ctx, \"outofband\",\n\t\t\twc.OutOfBand.PreEval, wc.OutOfBand.PostEval, wc.OutOfBand.OnMatch, patcher); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif len(wc.OutOfBand.OnChallenge) > 0 {\n\t\t\treturn nil, errors.New(\"on_challenge hooks are only valid in-band, not under outofband\")\n\t\t}\n\n\t\tif len(wc.OutOfBand.OnChallengeSubmit) > 0 {\n\t\t\treturn nil, errors.New(\"on_challenge_submit hooks are only valid in-band, not under outofband\")\n\t\t}\n\t}\n\n\t// on_challenge hooks: merge top-level and inband-scoped (both are in-band only).\n\tonChallengeHooks := wc.OnChallenge\n\tif wc.InBand != nil {\n\t\tonChallengeHooks = append(onChallengeHooks, wc.InBand.OnChallenge...)\n\t}\n\n\tif ret.CompiledOnChallenge, err = buildHookList(ctx, onChallengeHooks, hookOnChallenge, patcher); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Defining any on_challenge hook implies we need the challenge runtime to\n\t// validate cookies and submissions, even if the hook bodies never call\n\t// SendChallenge() themselves.\n\tif len(ret.CompiledOnChallenge) > 0 {\n\t\tpatcher.NeedWASMVM = true","sourceCodeStart":994,"sourceCodeEnd":1030,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/appsec.go#L994-L1030","documentation":"CrowdSec AppSec component rules support challenge hooks (on_challenge / on_challenge_submit) only for in-band rule collections. The WAF config loader validates the whole WAF config tree and rejects the config if these hook names appear under the `outofband` section, where per-request challenge interaction is meaningless. This is a startup-time configuration validation error: the config fails to load and the AppSec component is not initialized.","triggerScenarios":"Loading a WAF AppSec config YAML where `outofband: on_challenge_submit: [...]` (or `outofband: on_challenge: [...]`) is defined; each hook list under OutOfBand is checked in the WAF-config compilation path in pkg/appsec/appsec.go.","commonSituations":"A user copies an in-band challenge example into their out-of-band collection; a config file merges snippets where challenge hooks ended up at the wrong YAML nesting level; upgrading an older config that predated the in-band/out-of-band hook split.","solutions":["Move the on_challenge / on_challenge_submit hook definitions from the `outofband:` section to the top level or the `inband:` section of the WAF config","If the hook was added by mistake under outofband and is not needed, delete the entry","Re-validate the config indentation: YAML nesting mistakes are the usual root cause"],"exampleFix":"// before (WAF config yaml)\noutofband:\n  on_challenge_submit:\n    - console_log()\n\n// after\ninband:\n  on_challenge_submit:\n    - console_log()","handlingStrategy":"validation","validationCode":"if cfg.OutOfBand != nil && (len(cfg.OutOfBand.OnChallenge) > 0 || len(cfg.OutOfBand.OnChallengeSubmit) > 0) {\n    return fmt.Errorf(\"on_challenge/on_challenge_submit must be defined in-band, not under outofband\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep challenge hooks only in in-band collections; lint WAF configs for hook placement before deployment","cscli hubtool or a CI check can grep configs for `outofband:` blocks containing on_challenge"],"tags":["config","appsec","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}