theonedev/onedev · warning · ExplicitException
Invalid request path
Error message
Invalid request path
What it means
OneDev's markdown report download resource rejects a report name URL parameter that contains ".." by throwing ExplicitException("Invalid request path"). This is a path-traversal guard: the report name is joined into a filesystem path under the build's report directory, and ".." segments could escape that directory and read arbitrary files. The error is intentional and user-facing, meaning the URL itself is malformed/malicious, not that the server is broken.
Source
Thrown at server-plugin/server-plugin-report-markdown/src/main/java/io/onedev/server/plugin/report/markdown/MarkdownReportDownloadResource.java:61
Long buildNumber = params.get(PARAM_BUILD).toOptionalLong();
if (buildNumber == null)
throw new IllegalArgumentException("build number has to be specified");
Build build = OneDev.getInstance(BuildService.class).find(project, buildNumber);
if (build == null) {
String message = String.format("Unable to find build (project: %s, build number: %d)",
project.getPath(), buildNumber);
throw new EntityNotFoundException(message);
}
String reportName = params.get(PARAM_REPORT).toOptionalString();
if (reportName == null)
throw new IllegalArgumentException("Markdown report name has to be specified");
if (reportName.contains(".."))
throw new ExplicitException("Invalid request path");
if (!SecurityUtils.canAccessReport(build, reportName))
throw new UnauthorizedException();
List<String> pathSegments = new ArrayList<>();
for (int i = 0; i < params.getIndexedCount(); i++) {
String pathSegment = params.get(i).toString();
if (pathSegment.contains(".."))
throw new ExplicitException("Invalid request path");
if (pathSegment.length() != 0)
pathSegments.add(pathSegment);
}
String markdownPath = Joiner.on("/").join(pathSegments);
File buildDir = build.getDir();
File reportDir = new File(buildDir, PublishMarkdownReportStep.CATEGORY + "/" + reportName);
View on GitHub (pinned to d44925c47c)
Solutions
- Remove any '..' sequences from the report name used to build the URL.
- Use the exact report name configured in the Publish Markdown Report build step.
- URL-encode path parameters in scripts so '..' segments are not silently introduced.
- If a legitimate report is being blocked, rename the report so it contains no dots-pairs.
Example fix
// before
String url = baseUrl + "/~builds/" + buildId + "/markdown-reports/" + relativeDir + "/report.md";
// after
String safeReport = relativeDir.replace("..", "");
String url = baseUrl + "/~builds/" + buildId + "/markdown-reports/" + URLEncoder.encode(safeReport, StandardCharsets.UTF_8) + "/report.md"; Defensive patterns
Strategy: validation
Validate before calling
function validateReportName(reportName) {
if (!reportName || reportName.includes('..')) throw new Error('invalid report name: ' + reportName);
return reportName;
} Type guard
function isSafeSegment(s) {
return typeof s === 'string' && s.length > 0 && !s.includes('..');
} Prevention
- Never interpolate raw path values into report URLs.
- URL-encode all path parameters when building links.
- Keep report names simple identifiers without dots-pairs.
When it happens
Trigger: Hitting the markdown report download resource (e.g. /~builds/<id>/markdown-reports/...) with a 'report' URL parameter containing a '..' sequence, such as report=..%2Fsecret or report=foo/../../etc/passwd.
Common situations: Hand-crafted or bookmarked download URLs with wrong report paths; scripts that build the URL by concatenating untrusted path values; browser-encoded traversal attempts; typos where '..' is accidentally left in a generated link.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/18b74623b9ccf2d4.
Report an issue: GitHub.