{"record":{"id":"f843fd46aec7ddef","repo":"theonedev/onedev","slug":"not-authorized-f843fd","errorCode":null,"errorMessage":"Not authorized","messagePattern":"Not authorized","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/PackBlobResource.java","lineNumber":54,"sourceCode":"\n\t@Api(order=100, description = \"Find package blob by project id and hash\")\n\t@GET\n\tpublic PackBlob findByHash(@QueryParam(\"projectId\") Long projectId, @QueryParam(\"hash\") String hash) {\n\t\tvar packBlob = packBlobService.findBySha256Hash(projectId, hash);\n\t\tif (packBlob != null) \n\t\t\treturn packBlob;\t\t\t\n\t\telse \n\t\t\treturn null;\t\t\t\n\t}\n\t\n\t@Api(order=100, description = \"Download package blob\")\n\t@Path(\"/{packBlobId}/content\")\n\t@GET\n\t@Produces(APPLICATION_OCTET_STREAM)\n\tpublic StreamingOutput downloadBlob(@PathParam(\"packBlobId\") Long packBlobId) {\n\t\tvar packBlob = packBlobService.load(packBlobId);\n\t\tif (!SecurityUtils.canReadPack(packBlob.getProject()))\n\t\t\tthrow new UnauthorizedException();\n\t\t\n\t\tvar projectId = packBlob.getProject().getId();\n\t\tvar hash = packBlob.getSha256Hash();\n\t\treturn os -> {\n\t\t\tpackBlobService.downloadBlob(projectId, hash, os);\n\t\t};\n\t}\n\n}\n","sourceCodeStart":36,"sourceCodeEnd":64,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/PackBlobResource.java#L36-L64","documentation":"PackBlobResource.downloadBlob (GET /pack-blobs/{id}/content) checks SecurityUtils.canReadPack(project) before streaming the blob and throws UnauthorizedException (HTTP 401) when the authenticated user cannot read the project's packages. Package access follows project read permissions.","triggerScenarios":"Downloading a package blob without read permission on the project that owns the pack (anonymous request, unauthenticated CI job, token of a user outside the project).","commonSituations":"CI job using a token lacking access to a private project's registry; anonymous pull from a private package repository; project permissions changed and broke existing pipelines.","solutions":["Grant the calling user/group read access to the project (Project > Access/Permission settings)","Use an access token belonging to a user with Can Read permission on the project","For CI, configure job token/secret with access to the required project's packages"],"exampleFix":"// before\ncurl /~api/pack-blobs/17/content  # anonymous -> 401 Not authorized\n// after\ncurl -H \"Authorization: Bearer <token-with-read-access>\" /~api/pack-blobs/17/content","handlingStrategy":"validation","validationCode":"// preflight: check read access via a cheap authorized endpoint\nGET /~api/projects/{projectPath} with same credentials; 403/404 => do not attempt blob download","typeGuard":null,"tryCatchPattern":"try { downloadBlob(id); } catch (WebApplicationException e) { if (e.getResponse().getStatus() == 401) fixCredentialsOrPermissions(); else throw e; }","preventionTips":["Provision CI tokens with read access to all projects whose packages are consumed","Re-audit project permissions after access changes","Use authenticated requests, never anonymous, for private packages"],"tags":["rest","authorization","packages","permissions"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}