theonedev/onedev · error · ExplicitException

Invalid request path

Error message

Invalid request path

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/web/resource/ProjectSiteFileResource.java:76

	
	private static final Logger logger = LoggerFactory.getLogger(ProjectSiteFileResource.class);

	@Override
	protected ResourceResponse newResourceResponse(Attributes attributes) {
		PageParameters params = attributes.getParameters();

		String projectPath = params.get(ProjectMapperUtils.PARAM_PROJECT).toString();
		Project project = getProjectService().findByPath(projectPath);
		if (project == null)
			throw new EntityNotFoundException();
		
		Long projectId = project.getId();
		
		List<String> filePathSegments = new ArrayList<>();
		for (int i = 0; i < params.getIndexedCount(); i++) {
			String segment = params.get(i).toString();
			if (segment.contains(".."))
				throw new ExplicitException("Invalid request path");
			if (segment.length() != 0)
				filePathSegments.add(segment);
		}
		
		FileInfo fileInfo;
		String filePath = Joiner.on("/").join(filePathSegments);
		if (filePathSegments.contains(FILE_VERSION))
			return newNotFoundResponse(filePath);
		if (filePath.length() != 0) {
			ArtifactInfo artifactInfo = getProjectService().getSiteArtifactInfo(projectId, filePath);
			if (artifactInfo instanceof DirectoryInfo) {
				if (attributes.getRequest().getUrl().getPath().endsWith("/")) {
					DirectoryInfo directoryInfo = (DirectoryInfo) artifactInfo;
					String indexFilePath = filePath + "/index.html";
					artifactInfo = getProjectService().getSiteArtifactInfo(projectId, indexFilePath);
					if (artifactInfo instanceof FileInfo)
						fileInfo = (FileInfo) artifactInfo;
					else

View on GitHub (pinned to d44925c47c)

Solutions

  1. Use absolute-from-site-root URLs in the site content (e.g. /assets/x.css) instead of relative ../ paths.
  2. Request the file via its real path under the site root without any ".." segments.
  3. If seen in logs from unknown clients, treat as probing and block the source.

Example fix

// before: relative link produces traversal segment
GET /site/my-app/..%2F..%2Fsecrets.txt -> Invalid request path
// after: reference files within the site root
GET /site/my-app/assets/app.css
Defensive patterns

Strategy: validation

Validate before calling

const segments = new URL(url).pathname.split('/').filter(Boolean);
if (segments.some(s => s === '..' || decodeURIComponent(s).includes('..'))) {
  throw new Error('site file URLs must not contain .. path segments');
}

Type guard

function isSafeSitePath(url) {
  return url.split('/').every(s => !decodeURIComponent(s).includes('..'));
}

Try / catch

try { await fetch(siteFileUrl); } catch (e) { if (String(e.message).includes('Invalid request path')) rewriteToAbsoluteLinks(); else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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