Technical write-up · Apache DolphinScheduler
Cross-project task definition update authorization bypass
Analysis of CVE-2026-66084, the missing relationship between task definitions and authorized projects, and the removal of DolphinScheduler's obsolete update-with-upstream API.
Permission over a project is not permission over every task
An authenticated DolphinScheduler user with write permission in one project could modify a task definition belonging to a project outside that user’s authority. Apache published the task definition with-upstream authorization bypass as CVE-2026-66084 on October 8, 2026. The public advisory identifies a missing check that the selected task belongs to the authorized project. Apache advisory.
The research question was whether the project checked for permission was also the project owning the task being changed. Consider Alice’s protected project and Mallory, a non-administrator with legitimate write permission in a separate project. Mallory uses her own authenticated account. Her authority to edit tasks in her project should not extend to Alice’s task definitions. The original assessment assumed a known target task identifier; it did not establish an independent discovery route.
The application observations came from a locally built DolphinScheduler 3.4.2 standalone Docker environment using in-memory H2. Earlier service-level checks used a development snapshot, not the released 3.4.2 package. For this article, I reviewed the preserved observations, the 3.4.2 source and the removal present in 3.4.3. I did not perform a new reproduction or run the patched release.
Following the task beyond the permission check
In 3.4.2, TaskDefinitionController.updateTaskWithUpstream delegates to the service, which calls updateTask. That helper begins with these decisions in dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskDefinitionServiceImpl.java:
Project project = projectDao.queryByCode(projectCode);
// check if user have write perm for project
projectService.checkHasProjectWritePermissionThrowException(loginUser, project);
TaskDefinition taskDefinition = taskDefinitionDao.queryByCode(taskCode);
The permission check and lookup concern independently supplied values. The first establishes write permission for the requested project. The second resolves the task by its code. The underlying mapper does not constrain that lookup by project.
We therefore need one more relationship: does the task belong to the project for which permission was granted? The inspected method does not establish that relationship before reaching taskDefinitionDao.updateById(taskDefinitionToUpdate). The task selected by code can reach the persistence operation even though permission was checked against a different project. Update implementation.
Several guards remain significant. The task must exist; online state and execution type can prevent an update; the submitted definition must pass task-parameter checks; and version information must exist. These checks constrain which updates can succeed. None establishes the missing relationship between the authorized project and the selected task. Valid task input and an updateable lifecycle state remain prerequisites.
What the original application observations distinguish
A success response could have been misleading if the application ignored the update. The original local assessment checked the task before and after the operation:
| Historical comparison | Recorded observation | What it establishes |
|---|---|---|
| Ordinary project-scoped lookup by the non-administrator | The protected task was not returned. | The task was unavailable through that project context. |
| Administrator baseline | The target task existed and its definition was readable. | The rejection was not explained by a nonexistent target. |
| Update followed by application inspection | The operation succeeded and the changed definition was subsequently visible. | The result included a persisted task modification, beyond a success message. |
These summarize preserved application responses; they are not new runtime results or independently collected database-row diffs. Their narrow conclusion is an unauthorized task-definition change.
Another explanation would be intentional cross-project editing authority. The ordinary lookup alone could not settle that policy question. Apache’s published CVE record identifies the missing task-to-project check as incorrect authorization, confirming that the project restriction should apply to this operation.
Integrity impact without assuming task execution
Apache describes unauthorized changes to task definitions and upstream dependencies, with possible workflow integrity loss and disrupted task execution. The local observations support unauthorized modification; they do not demonstrate execution of the changed task, remote code execution, or system takeover. Suitable permissions and known identifiers were part of the assessment, and their prevalence in production deployments was not measured.
Apache rates the issue Moderate, without a numeric score. CISA-ADP assigns High 8.1 (CVSS 3.1). These are separate assessments in the published CVE data; the numerical assessment does not expand the local observations.
Removing the obsolete update path
Apache lists versions before 3.4.3 as affected and recommends upgrading to 3.4.3. Source review gives a concrete explanation of the change: the upstream removal deletes the update-with-upstream controller method and its supporting service implementation. The 3.4.3 upgrade notes record the API retirement, and the released source contains that removal.
This closes the inspected entry point by removing it. It should not be described as adding a project-equality guard to the old method. Source verification establishes the removal in 3.4.3; patched-release runtime behavior has not been independently tested here. This review directly compared 3.4.2 and 3.4.3, without independently establishing the first affected release or validating older release branches.
Useful follow-up regression checks would confirm that the retired route cannot modify state, that supported editing operations preserve legitimate same-project updates, and that cross-project task identifiers leave protected definitions and dependencies unchanged. These are proposed checks, not executed results. The enduring requirement is to authorize the actual task and its project before any supported operation changes them.