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

  1. Sanitize reportName to remove any '..' sequence before passing it to readFrom/downloadArtifact.
  2. Use only the report name exactly as published by the build's report publisher (no path components).
  3. Encode path components properly in URLs so '..' is not decoded into the name server-side.
  4. 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

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.