theonedev/onedev · error · UnauthorizedException

Unauthorized

Error message

Unauthorized

What it means

Thrown by ArtifactResource.uploadArtifact when the authenticated user lacks manage-build permission on the build's project. Publishing artifacts requires SecurityUtils.canManageBuild(build), a stronger permission than mere project access.

Source

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

		var projectId = build.getProject().getId();
		var buildNumber = build.getNumber();
		var normalizedPath = normalizeArtifactPath(artifactPath);
		return os -> {
			buildService.downloadArtifact(projectId, buildNumber, normalizedPath, os);
		};
	}

	@Api(order=300, description = "Upload artifact to specified path")
	@Path("/{buildId}/{artifactPath:(.*)}")
	@POST
	@Consumes(APPLICATION_OCTET_STREAM)
	public Response uploadArtifact(
			@PathParam("buildId") Long buildId, 
			@PathParam("artifactPath") @Api(example = "path/to/file") String artifactPath, 
			InputStream input) {
		Build build = buildService.load(buildId);
		if (!SecurityUtils.canManageBuild(build))
			throw new UnauthorizedException();

		buildService.uploadArtifact(build.getProject().getId(), build.getNumber(),
				normalizeArtifactPath(artifactPath), input);
		return ok().build();
	}
	
	@Api(order=400, description = "Delete artifact of specified path, or delete all artifacts " +
			"if artifact path is not specified")
	@Path("/{buildId}{artifactPath:(/.*)?}")
	@DELETE
	public Response deleteArtifact(
			@PathParam("buildId") Long buildId, 
			@PathParam("artifactPath") @Api(example = "/path/to/directoryOrFile") String artifactPath) {
		Build build = buildService.load(buildId);
		if (!SecurityUtils.canManageBuild(build))
			throw new UnauthorizedException();
		
		buildService.deleteArtifact(build, normalizeArtifactPath(artifactPath));

View on GitHub (pinned to d44925c47c)

Solutions

  1. Use credentials with Build Management permission on the project
  2. Assign the job's token/user a role that allows managing builds (e.g. project maintainer)
  3. If running inside a OneDev job, use the built-in build credential rather than a custom one

Example fix

// before
curl -u reader:token -X POST --data-binary @app.jar .../builds/42/artifacts/target/app.jar
// after
curl -u maintainer:token -X POST --data-binary @app.jar .../builds/42/artifacts/target/app.jar
Defensive patterns

Strategy: validation

Validate before calling

if (!canManageBuild(tokenUser, buildId)) throw new Error('manage-build permission required to upload artifacts');

Type guard

function canManage(u, b) { return u?.managedProjectIds?.includes(b?.projectId); }

Try / catch

try { uploadArtifact(buildId, path, stream); } catch (e) { if (/Unauthorized/i.test(e.message)) { throw new Error('Credential lacks Build Management permission'); } throw e; }

Prevention

When it happens

Trigger: POST (upload) to /builds/{buildId}/artifacts/{artifactPath} by a user who can view but not manage the build; build-agent or job token with insufficient project role.

Common situations: Uploading artifacts from an external script with a read-only user; project role downgraded from maintainer to read; using personal access token of a non-member.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/393658676620d37b. Report an issue: GitHub.