{"record":{"id":"f153af8763aae142","repo":"theonedev/onedev","slug":"access-denied","errorCode":null,"errorMessage":"Access denied","messagePattern":"Access denied","errorType":"exception","errorClass":"UnauthorizedException","httpStatus":403,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/CodeCommentHelper.java","lineNumber":35,"sourceCode":"import com.fasterxml.jackson.databind.ObjectMapper;\n\nimport io.onedev.server.OneDev;\nimport io.onedev.server.model.CodeComment;\nimport io.onedev.server.model.CodeCommentReply;\nimport io.onedev.server.model.CodeCommentStatusChange;\nimport io.onedev.server.security.SecurityUtils;\nimport io.onedev.server.service.CodeCommentReplyService;\nimport io.onedev.server.service.CodeCommentStatusChangeService;\n\npublic class CodeCommentHelper {\n    \n    public static Map<String, Object> addReply(Subject subject, CodeComment comment, String content) {\n        var user = SecurityUtils.getUser(subject);\n        if (user == null)\n            throw new UnauthenticatedException();\n\n        if (!SecurityUtils.canReadCode(subject, comment.getProject()))\n            throw new UnauthorizedException();\n\n        var reply = new CodeCommentReply();\n        reply.setComment(comment);\n        reply.setContent(content);\n        reply.setUser(user);\n        reply.setDate(new Date());\n        reply.setCompareContext(comment.getCompareContext());\n        getCodeCommentReplyService().create(reply);\n\n        return getDetail(reply);\n    }\n\n    public static Map<String, Object> changeStatus(Subject subject, CodeComment comment, \n                boolean resolved, @Nullable String note) {\n        if (!SecurityUtils.canChangeStatus(subject, comment))\n            throw new UnauthorizedException();\n            \n        if (comment.isResolved() != resolved) {","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/CodeCommentHelper.java#L17-L53","documentation":"addReply throws UnauthorizedException ('Access denied') when the authenticated user exists but lacks read access to the code of the project the comment belongs to. This is an authorization check, not authentication.","triggerScenarios":"Calling addReply as a valid user who cannot read the target project's code (SecurityUtils.canReadCode returns false), e.g. non-member or guest role without code read permission.","commonSituations":"Users replying to comments in private projects they are not members of, role changes that removed code-read permission, or using a token scoped to a different project.","solutions":["Grant the user at least code-read permission on the project (project role/permission settings).","Verify the comment's project and use an account/token with access to that project.","If the project is public-expected, check project visibility settings."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!SecurityUtils.canReadCode(subject, comment.getProject()))\n    throw new IllegalStateException(\"User lacks code read access to project \" + comment.getProject().getPath());","typeGuard":null,"tryCatchPattern":"try {\n    CodeCommentHelper.addReply(subject, comment, content);\n} catch (UnauthorizedException e) {\n    // request project access or use an account with code-read permission\n}","preventionTips":["Check project membership/permissions before calling comment APIs.","Grant code-read role to users who need comment access.","Use tokens created by accounts with access to the target project."],"tags":["authorization","permissions","security","project"],"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"}