{"record":{"id":"69e5efd950dc6369","repo":"theonedev/onedev","slug":"no-permission-to-update-issue-confidential","errorCode":null,"errorMessage":"No permission to update issue confidential","messagePattern":"No permission to update issue confidential","errorType":"http","errorClass":"UnauthorizedException","httpStatus":403,"severity":"error","filePath":"server-core/src/main/java/io/onedev/server/ai/TodResource.java","lineNumber":617,"sourceCode":"        IssueHelper.normalizeData(data);\n\n        var title = (String) data.remove(\"title\");\n        if (title != null) { \n            if (!SecurityUtils.canModifyIssue(subject, issue))\n                throw new UnauthorizedException(\"No permission to update issue title\");\n            issueChangeService.changeTitle(user, issue, title);\n        }\n\n        if (data.containsKey(\"description\")) {\n            if (!SecurityUtils.canModifyIssue(subject, issue))\n                throw new UnauthorizedException(\"No permission to update issue description\");\n            issueChangeService.changeDescription(user, issue, (String) data.remove(\"description\"));\n        }\n\n        var confidential = (Boolean) data.remove(\"confidential\");\n        if (confidential != null) {\n            if (!SecurityUtils.canModifyIssue(subject, issue))\n                throw new UnauthorizedException(\"No permission to update issue confidential\");\n            issueChangeService.changeConfidential(user, issue, confidential);\n        }\n\n        Integer ownEstimatedTime = (Integer) data.remove(\"ownEstimatedTime\");\n        if (ownEstimatedTime != null) {\n            if (!subscriptionService.isSubscriptionActive())\n                throw new NotAcceptableException(\"An active subscription is required for this feature\");\n            if (!issue.getProject().isTimeTracking())\n                throw new NotAcceptableException(\"Time tracking needs to be enabled for the project\");\n            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))\n                throw new UnauthorizedException(\"Issue schedule permission required to set own estimated time\");\n            issueChangeService.changeOwnEstimatedTime(user, issue, ownEstimatedTime*60);\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        List<String> iterationNames = (List<String>) data.remove(\"iterations\");\n        if (iterationNames != null) {\n            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-core/src/main/java/io/onedev/server/ai/TodResource.java#L599-L635","documentation":"Setting the \"confidential\" flag via editIssue requires canModifyIssue(subject, issue); otherwise UnauthorizedException(\"No permission to update issue confidential\") is thrown. Confidentiality changes are treated like any other issue modification, plus the issue's own visibility rules apply.","triggerScenarios":"Passing {\"confidential\": true|false} in the edit-issue payload as a user who cannot modify the issue (insufficient project role, or the confidential issue hides modification from them).","commonSituations":"Automation marking issues confidential without proper role; agents replaying edits of other users' issues; cross-project bulk operations under a single low-privilege token.","solutions":["Grant the user Edit Issue permission on the project before toggling confidentiality.","Use an account/token with the necessary rights for confidentiality changes.","Drop the \"confidential\" key from the payload if it's not intended.","Have an admin perform the change via the web UI if API-level permission can't be elevated."],"exampleFix":"// before\neditIssue(project, ref, {confidential: true}) // 403\n// after\n// performed by user with Edit Issue permission\neditIssue(project, ref, {confidential: true})","handlingStrategy":"validation","validationCode":"if ('confidential' in payload && !canModifyIssue) {\n  delete payload.confidential;\n  console.warn('Confidentiality change skipped: requires Edit Issue permission');\n}","typeGuard":null,"tryCatchPattern":"try { await editIssue(project, ref, {confidential}); } catch (e) { if (e.status === 403 && /confidential/.test(e.message)) { escalateToAdmin(); } else throw e; }","preventionTips":["Only toggle confidentiality from accounts with Edit Issue permission","Remember confidential issues add an extra visibility restriction","Validate intended field set against user permissions before sending","Document required roles for automation that changes confidentiality"],"tags":["authorization","permissions","http-403","confidential-issues"],"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"}