{"record":{"id":"5cd40cc1972ecf17","repo":"theonedev/onedev","slug":"unauthorized-5cd40c","errorCode":null,"errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"http","errorClass":"UnauthorizedException","httpStatus":401,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/rest/resource/CodeCommentResource.java","lineNumber":45,"sourceCode":"public class CodeCommentResource {\n\n\tprivate final CodeCommentService commentService;\n\n\tprivate final AuditService auditService;\n\n\t@Inject\n\tpublic CodeCommentResource(CodeCommentService commentService, AuditService auditService) {\n\t\tthis.commentService = commentService;\n\t\tthis.auditService = auditService;\n\t}\n\n\t@Api(order=100)\n\t@Path(\"/{commentId}\")\n\t@GET\n\tpublic CodeComment getComment(@PathParam(\"commentId\") Long commentId) {\n\t\tvar comment = commentService.load(commentId);\n    \tif (!SecurityUtils.canReadCode(comment.getProject()))  \n\t\t\tthrow new UnauthorizedException();\n    \treturn comment;\n\t}\n\t\n\t@Api(order=200)\n\t@Path(\"/{commentId}\")\n\t@DELETE\n\tpublic Response deleteComment(@PathParam(\"commentId\") Long commentId) {\n\t\tvar comment = commentService.load(commentId);\n    \tif (!SecurityUtils.canModifyOrDelete(comment)) \n\t\t\tthrow new UnauthorizedException();\n\t\tcommentService.delete(comment);\n\t\tvar oldAuditContent = VersionedXmlDoc.fromBean(comment).toXML();\n\t\tauditService.audit(comment.getProject(), \"deleted code comment on file \\\"\" + comment.getMark().getPath() + \"\\\" via RESTful API\", oldAuditContent, null);\n\t\treturn Response.ok().build();\n\t}\n\t\n}\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/rest/resource/CodeCommentResource.java#L27-L63","documentation":"OneDev's CodeCommentResource.getComment throws UnauthorizedException when the authenticated caller is not allowed to read code in the project that owns the code comment (SecurityUtils.canReadCode(comment.getProject())). The REST endpoint refuses to return the comment, surfacing HTTP 401/403 with message \"Unauthorized\".","triggerScenarios":"Calling GET /~api/code-comments/{commentId} with a token of a user who has no read access (e.g. not a project member, project is private) to the project containing the commented file; using an access token whose user was removed from the project; querying a comment in a public project while the effective security context is anonymous with anonymous access disabled.","commonSituations":"Scripts listing code comments with a personal token of a user outside the project; linking a comment ID to a teammate who lacks project access; after project visibility changed from public to private, previously working integrations start failing.","solutions":["Add the token's user to the project (or a group with at least Read Code permission) via Project -> Access Management.","Make the project readable if appropriate (public project or grant Read access to the relevant group).","Use an access token belonging to a member with read access instead.","Verify the commentId belongs to the project the user can access; a wrong ID pointing at a private project's comment is a common mix-up."],"exampleFix":"// before: request with token of non-member user\nGET /~api/code-comments/456 (user: guest, no project membership) -> 401 Unauthorized\n\n// after: grant 'Read Code' to guest's role in the project, then retry\nGET /~api/code-comments/456 -> 200","handlingStrategy":"try-catch","validationCode":"// ensure the authenticated user has read access before fetching the comment\nconst hasAccess = project.isPublic || project.memberships.some(m => m.user.id === currentUserId);\nif (!hasAccess) return null; // skip fetch entirely","typeGuard":"function canRead(project, user) {\n  return !!project && (project.isPublic || (project.members ?? []).some(m => m.userId === user?.id));\n}","tryCatchPattern":"try {\n  const resp = await fetch(`/~api/code-comments/${commentId}`, {headers:authHeaders});\n  if (resp.status === 401 || resp.status === 403) return null; // treat as unreadable\n  return await resp.json();\n} catch (e) {\n  console.warn('Failed to load code comment', commentId, e);\n  return null;\n}","preventionTips":["Grant 'Read Code' permission to groups/users that need API access to comments in private projects.","Use tokens of project members for comment queries.","After changing a project from public to private, update all integrations' credentials.","Validate that comment IDs come from projects the token's user can access."],"tags":["rest-api","authorization","code-comment","onedev","access-control"],"backgroundTag":"permission-denied","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}