{"record":{"id":"6afb6f1a9693cd21","repo":"theonedev/onedev","slug":"invalid-request-path-6afb6f","errorCode":null,"errorMessage":"Invalid request path","messagePattern":"Invalid request path","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/web/resource/ProjectSiteFileResource.java","lineNumber":76,"sourceCode":"\t\n\tprivate static final Logger logger = LoggerFactory.getLogger(ProjectSiteFileResource.class);\n\n\t@Override\n\tprotected ResourceResponse newResourceResponse(Attributes attributes) {\n\t\tPageParameters params = attributes.getParameters();\n\n\t\tString projectPath = params.get(ProjectMapperUtils.PARAM_PROJECT).toString();\n\t\tProject project = getProjectService().findByPath(projectPath);\n\t\tif (project == null)\n\t\t\tthrow new EntityNotFoundException();\n\t\t\n\t\tLong projectId = project.getId();\n\t\t\n\t\tList<String> filePathSegments = new ArrayList<>();\n\t\tfor (int i = 0; i < params.getIndexedCount(); i++) {\n\t\t\tString segment = params.get(i).toString();\n\t\t\tif (segment.contains(\"..\"))\n\t\t\t\tthrow new ExplicitException(\"Invalid request path\");\n\t\t\tif (segment.length() != 0)\n\t\t\t\tfilePathSegments.add(segment);\n\t\t}\n\t\t\n\t\tFileInfo fileInfo;\n\t\tString filePath = Joiner.on(\"/\").join(filePathSegments);\n\t\tif (filePathSegments.contains(FILE_VERSION))\n\t\t\treturn newNotFoundResponse(filePath);\n\t\tif (filePath.length() != 0) {\n\t\t\tArtifactInfo artifactInfo = getProjectService().getSiteArtifactInfo(projectId, filePath);\n\t\t\tif (artifactInfo instanceof DirectoryInfo) {\n\t\t\t\tif (attributes.getRequest().getUrl().getPath().endsWith(\"/\")) {\n\t\t\t\t\tDirectoryInfo directoryInfo = (DirectoryInfo) artifactInfo;\n\t\t\t\t\tString indexFilePath = filePath + \"/index.html\";\n\t\t\t\t\tartifactInfo = getProjectService().getSiteArtifactInfo(projectId, indexFilePath);\n\t\t\t\t\tif (artifactInfo instanceof FileInfo)\n\t\t\t\t\t\tfileInfo = (FileInfo) artifactInfo;\n\t\t\t\t\telse","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/resource/ProjectSiteFileResource.java#L58-L94","documentation":"ProjectSiteFileResource serves static files from a project's site (project website preview) by mapping indexed URL path segments to a file path. Any segment containing \"..\" is rejected with ExplicitException(\"Invalid request path\") to prevent path traversal out of the site root.","triggerScenarios":"GET of a project-site file URL where one indexed path segment contains \"..\" — either deliberate traversal (../../secrets) or an encoded/relative path accidentally included in the URL.","commonSituations":"Relative links inside published site HTML (e.g. href=\"../assets/x.css\") resolved by the client into \"..\" segments hitting the resource; vulnerability scanners probing the endpoint; manually built URLs with extra dot-dot segments.","solutions":["Use absolute-from-site-root URLs in the site content (e.g. /assets/x.css) instead of relative ../ paths.","Request the file via its real path under the site root without any \"..\" segments.","If seen in logs from unknown clients, treat as probing and block the source."],"exampleFix":"// before: relative link produces traversal segment\nGET /site/my-app/..%2F..%2Fsecrets.txt -> Invalid request path\n// after: reference files within the site root\nGET /site/my-app/assets/app.css","handlingStrategy":"validation","validationCode":"const segments = new URL(url).pathname.split('/').filter(Boolean);\nif (segments.some(s => s === '..' || decodeURIComponent(s).includes('..'))) {\n  throw new Error('site file URLs must not contain .. path segments');\n}","typeGuard":"function isSafeSitePath(url) {\n  return url.split('/').every(s => !decodeURIComponent(s).includes('..'));\n}","tryCatchPattern":"try { await fetch(siteFileUrl); } catch (e) { if (String(e.message).includes('Invalid request path')) rewriteToAbsoluteLinks(); else throw e; }","preventionTips":["Publish site content with root-relative links, never ../","Test generated site HTML for relative navigation before publishing","Monitor logs for traversal probes and block offending clients"],"tags":["onedev","http","security","path-traversal","project-site"],"backgroundTag":"path-traversal-blocked","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}