{"record":{"id":"b02552611b3e1bca","repo":"theonedev/onedev","slug":"unauthorized-b02552","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/AgentLogResource.java","lineNumber":36,"sourceCode":"\nimport com.google.common.base.Joiner;\n\nimport io.onedev.commons.utils.ExplicitException;\nimport io.onedev.server.OneDev;\nimport io.onedev.server.service.AgentService;\nimport io.onedev.server.model.Agent;\nimport io.onedev.server.security.SecurityUtils;\n\npublic class AgentLogResource extends AbstractResource {\n\n\tprivate static final long serialVersionUID = 1L;\n\n\tprivate static final String PARAM_AGENT = \"agent\";\n\t\n\t@Override\n\tprotected ResourceResponse newResourceResponse(Attributes attributes) {\n\t\tif (!SecurityUtils.isAdministrator()) \n\t\t\tthrow new UnauthorizedException();\n\n\t\tString agentName = attributes.getParameters().get(PARAM_AGENT).toString();\n\t\tAgent agent = OneDev.getInstance(AgentService.class).findByName(agentName);\n\t\tif (agent == null)\n\t\t\tthrow new EntityNotFoundException(\"Unable to find agent: \" + agentName);\n\t\t\n\t\tif (!agent.isOnline())\n\t\t\tthrow new ExplicitException(\"Unable to read log: agent is offline\");\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(\"agent-log.txt\", StandardCharsets.UTF_8.name()));\n\t\t} catch (UnsupportedEncodingException e) {\n\t\t\tthrow new RuntimeException(e);","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/web/resource/AgentLogResource.java#L18-L54","documentation":"AgentLogResource streams an agent's log file and is restricted to server administrators. newResourceResponse first checks SecurityUtils.isAdministrator() and throws UnauthorizedException for anyone else, so only admins may download agent logs via this resource.","triggerScenarios":"An authenticated non-admin user (or anonymous request) requests the agent log resource for any agent name.","commonSituations":"A CI/automation script calling the log endpoint with a non-admin API credential; a regular user opening an agent log URL shared by an admin; missing login session leading to anonymous access.","solutions":["Log in or use credentials of a user with OneDev administrator role.","Grant the 'Administrator' role to the account the request runs under (Admin > Users > role), if appropriate.","Instead of scraping the resource, view agent logs through the admin UI (Admin > Agents > agent > Logs)."],"exampleFix":"// before: non-admin token\ncurl -u developer:xxx https://onedev/~agentlog/build-1\n\n// after: admin credential\ncurl -u admin:yyy https://onedev/~agentlog/build-1","handlingStrategy":"validation","validationCode":"// Ensure the credential used is an administrator before calling\nif (!currentUser.isAdmin())\n    throw new SecurityException(\"agent log endpoint requires administrator role\");","typeGuard":null,"tryCatchPattern":"try {\n    downloadAgentLog(agent);\n} catch (UnauthorizedException e) {\n    // fall back to admin credential or direct user to Admin > Agents > Logs\n}","preventionTips":["Use admin-scoped service accounts for automation touching agent resources.","Point regular users to the admin UI instead of raw resource URLs.","Keep sessions alive; anonymous requests will always be rejected."],"tags":["authorization","agent","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"}