{"record":{"id":"d1a992465dfd9e20","repo":"crowdsecurity/crowdsec","slug":"schema-filename-q-must-be-relative-to-s-and-stay","errorCode":null,"errorMessage":"schema filename %q must be relative to %s and stay within it","messagePattern":"schema filename %q must be relative to (.+?) and stay within it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/appsec/appsec.go","lineNumber":1879,"sourceCode":"\t\t// Custom remediations use the same status code logic as ban/captcha\n\t\tresp.HTTPStatus = response.UserHTTPResponseCode\n\t\tif resp.HTTPStatus == 0 {\n\t\t\tresp.HTTPStatus = w.Config.UserBlockedHTTPCode\n\t\t}\n\t\tbouncerStatusCode = response.BouncerHTTPResponseCode\n\t\tif bouncerStatusCode == 0 {\n\t\t\tbouncerStatusCode = w.Config.BouncerBlockedHTTPCode\n\t\t}\n\t}\n\n\treturn bouncerStatusCode, resp\n}\n\nconst schemasSubDir = \"schemas\"\n\nfunc (w *AppsecRuntimeConfig) loadAPISchema(ref, filename string, opts *apivalidation.SchemaOptions) error {\n\tif !filepath.IsLocal(filename) {\n\t\treturn fmt.Errorf(\"schema filename %q must be relative to %s and stay within it\", filename, schemasSubDir)\n\t}\n\tschemaPath := filepath.Join(w.DataDir, schemasSubDir, filename)\n\tw.Logger.Debugf(\"loading schema %s for ref %s\", schemaPath, ref)\n\tschema, err := os.ReadFile(schemaPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to read schema file %s : %w\", schemaPath, err)\n\t}\n\treturn w.RequestValidator.LoadSchema(ref, string(schema), opts)\n}\n\nfunc (w *AppsecRuntimeConfig) LoadAPISchemaWithName(ref string, filename string) error {\n\treturn w.loadAPISchema(ref, filename, nil)\n}\n\n// LoadAPISchemaWithOptions behaves like LoadAPISchemaWithName but accepts a\n// map of policy overrides. Supported keys:\n//   - \"on_route_not_found\":             \"drop\" | \"ignore\"  (default: \"drop\")\n//   - \"on_method_not_allowed\":          \"drop\" | \"ignore\"  (default: \"drop\")","sourceCodeStart":1861,"sourceCodeEnd":1897,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/appsec/appsec.go#L1861-L1897","documentation":"loadAPISchema validates that the schema filename is a local, relative path (filepath.IsLocal) before joining it under <data_dir>/schemas. Absolute paths or paths escaping the schemas directory (../ traversal) are rejected with this error to prevent reading arbitrary files. It is a security guard on user-supplied schema references in API validation config.","triggerScenarios":"Configuring an API validation schema with an absolute path (/etc/crowdsec/schemas/x.json), a filename containing `..`, or a path starting with `/` or a drive letter.","commonSituations":"User puts the full path to a schema file instead of just the name; templating injects a leading slash; a malicious or buggy config attempts path traversal.","solutions":["Place the schema file under /var/lib/crowdsec/data/schemas/ (or your data dir's schemas subdir) and reference it by bare relative filename","Remove any leading `/` or `../` from the configured filename","Keep the file within the schemas directory — subdirectories are fine as long as the path stays inside","If you need schemas elsewhere, this is intentionally unsupported; move the file"],"exampleFix":"// before\napi_validation:\n  schema: /etc/crowdsec/schemas/user.json\n// after (file at <data_dir>/schemas/user.json)\napi_validation:\n  schema: user.json","handlingStrategy":"validation","validationCode":"func isSafeSchemaName(name string) bool {\n    return filepath.IsLocal(name) && name != \".\" && !strings.Contains(name, \"..\")\n}","typeGuard":null,"tryCatchPattern":"if err := rt.LoadAPISchema(ref, filename); err != nil {\n    if strings.Contains(err.Error(), \"must be relative to\") {\n        log.Fatalf(\"move schema into %s and use a relative name: %v\", schemasDir, err)\n    }\n    return err\n}","preventionTips":["Always reference schemas by bare filename relative to the schemas dir","Never template absolute paths into schema config","Sanitize any user/externally supplied schema names before passing them"],"tags":["appsec","path","security"],"backgroundTag":"path-traversal-blocked","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"}