theonedev/onedev · error · ExplicitException

Invalid artifact path

Error message

Invalid artifact path

What it means

normalizeArtifactPath throws this ExplicitException when the supplied artifact path contains '..', which could allow directory traversal outside the build's artifact directory. It is a deliberate safety check rejecting any path that escapes the artifact root.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/ArtifactResource.java:54

@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Singleton
public class ArtifactResource {
	
	private final BuildService buildService;
	
	@Inject
	public ArtifactResource(BuildService buildService) {
		this.buildService = buildService;
	}
	
	@Nullable
	private String normalizeArtifactPath(@Nullable String artifactPath) {
		if (StringUtils.isNotBlank(artifactPath)) {
			artifactPath = StringUtils.stripStart(artifactPath, "/");
			if (StringUtils.isNotBlank(artifactPath)) {
				if (artifactPath.contains(".."))
					throw new ExplicitException("Invalid artifact path");
				return artifactPath;
			}
		} 
		return null;
	}
	
	@Api(order=100, description = "Get artifact info of specified path")
	@Path("/{buildId}/infos{artifactPath:(/.*)?}")
    @GET
    public ArtifactInfo getArtifactInfo(@PathParam("buildId") Long buildId, 
										@PathParam("artifactPath") @Api(example = "/path/to/directoryOrFile") String artifactPath) {
		Build build = buildService.load(buildId);
		if (!SecurityUtils.canAccessProject(build.getProject()))
			throw new UnauthorizedException();
		return buildService.getArtifactInfo(build, normalizeArtifactPath(artifactPath));
    }

	@Api(order=200, description = "Download artifact of specified path")

View on GitHub (pinned to d44925c47c)

Solutions

  1. Remove '..' from the artifact path and address artifacts by their path under the build root
  2. Validate/canonicalize the path in the calling script before calling the API
  3. Reference the artifact via its exact published path shown in the build's artifacts tab

Example fix

// before
path="../../secrets/key.jar"
// after
path="target/app.jar"
Defensive patterns

Strategy: validation

Validate before calling

if (artifactPath && artifactPath.includes('..')) throw new Error('artifactPath must not contain ..');

Type guard

const isSafeArtifactPath = (p) => typeof p === 'string' && !p.includes('..');

Try / catch

try { upload(path) } catch (e) { if (/Invalid artifact path/.test(e.message)) { console.error('Path rejected: remove any ".." segments'); } else { throw e } }

Prevention

When it happens

Trigger: Passing a path containing '..' (e.g. '../../etc/passwd', 'a/../../b') as artifactPath to getArtifactInfo, downloadArtifact, uploadArtifact, or deleteArtifact.

Common situations: Concatenating user-supplied file paths into artifact URLs; misconfigured CI variables that resolve to relative paths with '..'; path templates built with build-number placeholders inserted incorrectly.

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