{"record":{"id":"a92f06dfbf7ed3f4","repo":"theonedev/onedev","slug":"unauthorized-a92f06","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/web/resource/BuildLogResource.java","lineNumber":66,"sourceCode":"\t\tPageParameters params = attributes.getParameters();\n\n\t\tLong projectId = params.get(PARAM_PROJECT).toLong();\n\t\tLong buildNumber = params.get(PARAM_BUILD).toOptionalLong();\n\t\tif (buildNumber == null)\n\t\t\tthrow new IllegalArgumentException(\"build number has to be specified\");\n\n\t\tif (!SecurityUtils.isSystem()) {\n\t\t\tProject project = getProjectService().load(projectId);\t\t\t\n\t\t\tBuild build = getBuildService().find(project, buildNumber);\n\n\t\t\tif (build == null) {\n\t\t\t\tString message = String.format(\"Unable to find build (project: %s, build number: %d)\", \n\t\t\t\t\t\tproject.getPath(), buildNumber);\n\t\t\t\tthrow new EntityNotFoundException(message);\n\t\t\t}\n\t\t\t\n\t\t\tif (!SecurityUtils.canAccessLog(build))\n\t\t\t\tthrow new UnauthorizedException();\n\t\t}\n\t\t\n\t\tResourceResponse response = new ResourceResponse();\n\t\tresponse.setContentType(MimeTypes.OCTET_STREAM);\n\t\t\n\t\tresponse.disableCaching();\n\t\t\n\t\ttry {\n\t\t\tresponse.setFileName(URLEncoder.encode(\"build-log.txt\", StandardCharsets.UTF_8.name()));\n\t\t} catch (UnsupportedEncodingException e) {\n\t\t\tthrow new RuntimeException(e);\n\t\t}\n\t\tresponse.setWriteCallback(new WriteCallback() {\n\n\t\t\t@Override\n\t\t\tpublic void writeData(Attributes attributes) throws IOException {\n\t\t\t\tString activeServer = getProjectService().getActiveServer(projectId, true);\n\t\t\t\tvar clusterService = getClusterService();","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/resource/BuildLogResource.java#L48-L84","documentation":"After the build is found, BuildLogResource enforces SecurityUtils.canAccessLog(build); users who can see the project but not its build logs (e.g. restricted roles) get UnauthorizedException, surfaced as HTTP 401/403 with message \"Unauthorized\".","triggerScenarios":"GET /~resource/buildlogs?project=..&build=.. with an existing build while the authenticated user (or anonymous) lacks log access permission on that build/project.","commonSituations":"Guest users opening direct log links shared by developers; service accounts whose role allows running pipelines but not viewing logs; permission model changes removing 'View build logs' from a role.","solutions":["Request/grant the role that includes access to build logs for the project (Project > Access Control).","Log in with an authorized account instead of anonymous access.","For CI scripts, use an access token whose role permits log access."],"exampleFix":"// before: guest token fetching logs -> 401\ncurl -H \"Authorization: Bearer $GUEST_TOKEN\" .../buildlogs?project=1&build=42\n// after: token role includes log access\ncurl -H \"Authorization: Bearer $CI_TOKEN\" .../buildlogs?project=1&build=42","handlingStrategy":"try-catch","validationCode":"// confirm the caller's role grants log access before attempting\ncanAccessLog = userRoles.some(r => r.project === projectId && r.permissions.includes('VIEW_BUILD_LOGS'));","typeGuard":null,"tryCatchPattern":"try { downloadLog(url); } catch (HttpException e) { if (e.getStatusCode() === 403) { requestLogAccess(project); } else throw e; }","preventionTips":["Grant log-view permission to roles that consume CI output programmatically","Use dedicated CI tokens with the right role","Audit role permissions after access-model changes"],"tags":["onedev","http","authorization","ci","build-logs"],"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"}