theonedev/onedev · warning · ExplicitException

Invalid request path

Error message

Invalid request path

What it means

The unit test artifact download resource validates the 'report' URL parameter and throws ExplicitException("Invalid request path") when it contains "..". Because the report name feeds into a filesystem path under the build directory, traversal segments could expose files outside the report. This is an intentional security rejection of the request URL.

Source

Thrown at server-plugin/server-plugin-report-unittest/src/main/java/io/onedev/server/plugin/report/unittest/TestArtifactResource.java:50

public class TestArtifactResource extends AbstractResource {

	private static final long serialVersionUID = 1L;

	private static final String PARAM_PROJECT = "project";

	private static final String PARAM_BUILD = "build";

	private static final String PARAM_REPORT = "report";

	@Override
	protected ResourceResponse newResourceResponse(Attributes attributes) {
		var params = attributes.getParameters();
		var projectId = params.get(PARAM_PROJECT).toLong();
		var buildNumber = params.get(PARAM_BUILD).toLong();
		String reportName = params.get(PARAM_REPORT).toString();
		if (reportName.contains(".."))
			throw new ExplicitException("Invalid request path");

		if (!SecurityUtils.isSystem()) {
			var project = OneDev.getInstance(ProjectService.class).load(projectId);
			var build = OneDev.getInstance(BuildService.class).find(project, buildNumber);
			if (build == null) {
				throw new EntityNotFoundException(String.format(
						"Unable to find build (project: %s, build number: %d)",
						project.getPath(), buildNumber));
			}
			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");

View on GitHub (pinned to d44925c47c)

Solutions

  1. Remove '..' from the report name in the URL.
  2. Use the exact report name from the Publish Unit Test Report step.
  3. URL-encode report names when constructing links programmatically.
  4. Regenerate the download link from the build's test report page.

Example fix

// before
String url = ".../unittest-artifacts/" + reportDir + "/file.xml"; // reportDir = "../artifacts"

// after
String url = ".../unittest-artifacts/" + URLEncoder.encode(reportName, StandardCharsets.UTF_8) + "/file.xml";
Defensive patterns

Strategy: validation

Validate before calling

function validateUnitTestReportName(reportName) {
  if (!reportName || reportName.includes('..')) throw new Error('invalid request path');
}

Type guard

function isSafeReportParam(v) {
  return typeof v === 'string' && !v.includes('..');
}

Prevention

When it happens

Trigger: Requesting test artifacts from the unittest report resource with a report name parameter containing '..', e.g. report=../artifacts.

Common situations: Scripts generating artifact download URLs from untrusted or concatenated paths; manual URL edits; stale templates building relative report names.

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/e92cf1c5491a49e8. Report an issue: GitHub.