theonedev/onedev · error · UnauthorizedException

No permission to update issue confidential

Error message

No permission to update issue confidential

What it means

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.

Source

Thrown at server-core/src/main/java/io/onedev/server/ai/TodResource.java:617

        IssueHelper.normalizeData(data);

        var title = (String) data.remove("title");
        if (title != null) { 
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue title");
            issueChangeService.changeTitle(user, issue, title);
        }

        if (data.containsKey("description")) {
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue description");
            issueChangeService.changeDescription(user, issue, (String) data.remove("description"));
        }

        var confidential = (Boolean) data.remove("confidential");
        if (confidential != null) {
            if (!SecurityUtils.canModifyIssue(subject, issue))
                throw new UnauthorizedException("No permission to update issue confidential");
            issueChangeService.changeConfidential(user, issue, confidential);
        }

        Integer ownEstimatedTime = (Integer) data.remove("ownEstimatedTime");
        if (ownEstimatedTime != null) {
            if (!subscriptionService.isSubscriptionActive())
                throw new NotAcceptableException("An active subscription is required for this feature");
            if (!issue.getProject().isTimeTracking())
                throw new NotAcceptableException("Time tracking needs to be enabled for the project");
            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))
                throw new UnauthorizedException("Issue schedule permission required to set own estimated time");
            issueChangeService.changeOwnEstimatedTime(user, issue, ownEstimatedTime*60);
        }

        @SuppressWarnings("unchecked")
        List<String> iterationNames = (List<String>) data.remove("iterations");
        if (iterationNames != null) {
            if (!SecurityUtils.canScheduleIssues(subject, issue.getProject()))

View on GitHub (pinned to d44925c47c)

Solutions

  1. Grant the user Edit Issue permission on the project before toggling confidentiality.
  2. Use an account/token with the necessary rights for confidentiality changes.
  3. Drop the "confidential" key from the payload if it's not intended.
  4. Have an admin perform the change via the web UI if API-level permission can't be elevated.

Example fix

// before
editIssue(project, ref, {confidential: true}) // 403
// after
// performed by user with Edit Issue permission
editIssue(project, ref, {confidential: true})
Defensive patterns

Strategy: validation

Validate before calling

if ('confidential' in payload && !canModifyIssue) {
  delete payload.confidential;
  console.warn('Confidentiality change skipped: requires Edit Issue permission');
}

Try / catch

try { await editIssue(project, ref, {confidential}); } catch (e) { if (e.status === 403 && /confidential/.test(e.message)) { escalateToAdmin(); } else throw e; }

Prevention

When it happens

Trigger: 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).

Common situations: Automation marking issues confidential without proper role; agents replaying edits of other users' issues; cross-project bulk operations under a single low-privilege token.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/69e5efd950dc6369. Report an issue: GitHub.