{"record":{"id":"150386f3f2b2db13","repo":"caddyserver/caddy","slug":"illegal-ads-path","errorCode":null,"errorMessage":"illegal ADS path","messagePattern":"illegal ADS path","errorType":"http","errorClass":"caddyhttp.Error","httpStatus":400,"severity":"warning","filePath":"modules/caddyhttp/fileserver/staticfiles.go","lineNumber":275,"sourceCode":"\t\t\t\tif sortOption != sortOrderAsc && sortOption != sortOrderDesc {\n\t\t\t\t\treturn fmt.Errorf(\"the second option must be one of the following: %s, %s, but got %s\", sortOrderAsc, sortOrderDesc, sortOption)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\treturn fmt.Errorf(\"only max 2 sort options are allowed, but got %d\", idx+1)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (fsrv *FileServer) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {\n\trepl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)\n\n\tif runtime.GOOS == \"windows\" {\n\t\t// reject paths with Alternate Data Streams (ADS)\n\t\tif strings.Contains(r.URL.Path, \":\") {\n\t\t\treturn caddyhttp.Error(http.StatusBadRequest, fmt.Errorf(\"illegal ADS path\"))\n\t\t}\n\t\t// reject paths with \"8.3\" short names\n\t\ttrimmedPath := strings.TrimRight(r.URL.Path, \". \") // Windows ignores trailing dots and spaces, sigh\n\t\tif len(path.Base(trimmedPath)) <= 12 && strings.Contains(trimmedPath, \"~\") {\n\t\t\treturn caddyhttp.Error(http.StatusBadRequest, fmt.Errorf(\"illegal short name\"))\n\t\t}\n\t\t// both of those could bypass file hiding or possibly leak information even if the file is not hidden\n\t}\n\n\tfilesToHide := fsrv.transformHidePaths(repl)\n\n\troot := repl.ReplaceAll(fsrv.Root, \".\")\n\tfsName := repl.ReplaceAll(fsrv.FileSystem, \"\")\n\n\tfileSystem, ok := fsrv.fsmap.Get(fsName)\n\tif !ok {\n\t\treturn caddyhttp.Error(http.StatusNotFound, fmt.Errorf(\"filesystem not found\"))\n\t}","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/caddyserver/caddy/blob/50e54ee279aa1e504fe218ca49ab6ae16c100410/modules/caddyhttp/fileserver/staticfiles.go#L257-L293","documentation":"Returned by FileServer.ServeHTTP on Windows only: the request URL path contains a colon, which Windows interprets as an Alternate Data Stream (ADS) separator (e.g. 'file.txt:stream'). Serving such paths could bypass file hiding or expose hidden stream data, so Caddy rejects them with HTTP 400 before touching the filesystem.","triggerScenarios":"Any request whose URL path contains ':' while running Caddy on Windows — e.g. GET /secret.txt:hidden or /C:/path — during normal request serving.","commonSituations":"Security probing/scanners on Windows deployments; clients sending URLs with absolute Windows paths; legitimate apps that use colons in path segments and must be re-designed when fronted by Caddy on Windows.","solutions":["Change the client URLs to not contain colons in the path (use a different separator).","If a colon is legitimately needed, encode it (%3A) only if downstream handling is safe — note the raw path check may still reject after decode; prefer renaming.","On Windows, ensure sensitive files rely on `hide` plus this built-in guard rather than ADS obscurity."],"exampleFix":"# before (client requests a path with ADS syntax)\nGET /report.txt:stream\n# after\nGET /report.txt  (store the stream data as a separate file)","handlingStrategy":"validation","validationCode":"// Upstream/reverse-proxy guard: rewrite or reject colon-containing paths before they reach clients\ncaddyhttp.HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {\n    if runtime.GOOS == \"windows\" && strings.Contains(r.URL.Path, \":\") {\n        return caddyhttp.Error(http.StatusBadRequest, fmt.Errorf(\"illegal ADS path\"))\n    }\n    return next.ServeHTTP(w, r)\n})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["On Windows deployments, never publish URLs with ':' in the path.","Monitor 400s with 'illegal ADS path' as potential probing.","Front-ending legacy apps that use colons? Map them to different URL shapes via rewrite."],"tags":["caddy","fileserver","windows","ads","security","http-400"],"backgroundTag":null,"analyzedSha":"50e54ee279aa1e504fe218ca49ab6ae16c100410","analyzedAt":"2026-08-15T09:20:21.641Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}