theonedev/onedev · error · ExplicitException
Invalid report name
Error message
Invalid report name
What it means
checkReportName is the shared guard used by readFrom and downloadArtifact to reject report names containing '..'. Unit test report names map directly to directory names on disk, so '..' would allow escaping the reports directory. Any report name containing the two-dot sequence is rejected with 'Invalid report name'.
Source
Thrown at server-core/src/main/java/io/onedev/server/codequality/UnitTestReport.java:187
builder.header(AUTHORIZATION, BEARER + " "
+ clusterService.getCredential());
try (Response response = builder.get()) {
checkStatus(response);
try (var is = response.readEntity(InputStream.class)) {
IOUtils.copy(is, os, BUFFER_SIZE);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} finally {
client.close();
}
}
}
private static void checkReportName(String reportName) {
if (reportName.contains(".."))
throw new ExplicitException("Invalid report name");
}
public void writeTo(File reportDir) {
File reportFile = new File(reportDir, REPORT);
try (OutputStream os = new BufferedOutputStream(new FileOutputStream(reportFile), BUFFER_SIZE)) {
SerializationUtils.serialize(this, os);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public int getTestDuration() {
int testDuration = 0;
for (TestSuite testSuite: getTestSuites())
testDuration += testSuite.getDuration()/1000;
return testDuration;
}
View on GitHub (pinned to d44925c47c)
Solutions
- Sanitize reportName to remove any '..' sequence before passing it to readFrom/downloadArtifact.
- Use only the report name exactly as published by the build's report publisher (no path components).
- Encode path components properly in URLs so '..' is not decoded into the name server-side.
- Reject invalid report names at your own API boundary before calling the library.
Example fix
// before
String reportName = request.getPath().substring(afterPrefix);
UnitTestReport.downloadArtifact(projectId, buildNumber, reportName, artifactPath, os);
// after
String reportName = request.getPath().substring(afterPrefix);
if (reportName.contains(".."))
throw new WebException(400, "Invalid report name");
UnitTestReport.downloadArtifact(projectId, buildNumber, reportName, artifactPath, os); Defensive patterns
Strategy: validation
Validate before calling
if (reportName == null || reportName.contains(".."))
throw new IllegalArgumentException("Invalid report name: " + reportName); Type guard
boolean isSafeReportName(String reportName) {
return reportName != null && !reportName.contains("..");
} Try / catch
try {
UnitTestReport.readFrom(lockName, file);
} catch (ExplicitException e) {
if (e.getMessage().equals("Invalid report name"))
throw new BadRequestException("Report name must not contain path components");
} Prevention
- Sanitize report names taken from URLs before passing them to report APIs.
- Only use report names as published by the build's report publisher.
- Reject path-like names at your own API boundary as defense in depth.
When it happens
Trigger: Calling UnitTestReport.readFrom(...) or UnitTestReport.downloadArtifact(...) with reportName containing '..'; passing a user-supplied report name straight from a URL without validation.
Common situations: Crafted or accidental '..' in the report segment of an HTTP request URL; clients concatenating directory components into the report name; test harnesses generating report names with '..' separators.
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/bc582a2807d1fb0c.
Report an issue: GitHub.