Add missing authorization to workflow step link subresources - #1385
Add missing authorization to workflow step link subresources#1385MatusBeke wants to merge 3 commits into
Conversation
The getStep() link methods on WorkflowItemStepLinkRepository, PoolTaskStepLinkRepository and ClaimedTaskStepLinkRepository had no @PreAuthorize, unlike the sibling workflowitem link repositories (collection/item/submitter) and the parent findOne endpoints. Because @LinkRest methods are invoked directly on the link repository, the parent's authorization is never evaluated, so an unauthenticated caller reaches the handler and can disclose task existence and workflow step state (404-vs-401 divergence on a non-existent id; 200 with step state for a real task). Apply the same READ permission check the parent repositories already use, so each /step subresource enforces the same authorization as its parent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR closes an authorization gap in the REST “link repository” layer by adding missing @PreAuthorize checks to the /step subresources for workflow items and tasks, ensuring these subresources enforce the same READ permissions as their parent endpoints.
Changes:
- Add
@PreAuthorizeguard toWorkflowItemStepLinkRepository#getStep()usingWORKFLOWITEMREAD permission. - Add
@PreAuthorizeguard toPoolTaskStepLinkRepository#getStep()usingPOOLTASKREAD permission. - Add
@PreAuthorizeguard toClaimedTaskStepLinkRepository#getStep()usingCLAIMEDTASKREAD permission.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemStepLinkRepository.java | Adds missing method-level authorization to protect the /step link for workflow items. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java | Adds missing method-level authorization to protect the /step link for pool tasks. |
| dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java | Adds missing method-level authorization to protect the /step link for claimed tasks. |
Comments suppressed due to low confidence (3)
dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/WorkflowItemStepLinkRepository.java:64
- This new authorization behavior on the
/steplink is security-critical, but there doesn’t appear to be any integration test coverage ensuring the endpoint returns 401/403 when accessed without the required WORKFLOWITEM READ permission (and succeeds when authorized). Please add an IT similar toWorkflowItemRestLinkRepositoryIT’s existing submitter/collection/item link tests.
@PreAuthorize("hasPermission(#workflowItemId, 'WORKFLOWITEM', 'READ')")
public WorkflowStepRest getStep(@Nullable HttpServletRequest request,
Integer workflowItemId,
@Nullable Pageable optionalPageable,
Projection projection) {
dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/PoolTaskStepLinkRepository.java:52
- This adds the missing authorization guard on the pooltask
/steplink, but there are no integration tests asserting unauthorized/forbidden access is blocked for this subresource (only the parent/pooltasks/{id}endpoints appear to be tested). Please add IT coverage for/api/workflow/pooltasks/{id}/stepfor 401 (anonymous) and 403 (logged-in user without READ permission) cases.
@PreAuthorize("hasPermission(#poolTaskId, 'POOLTASK', 'READ')")
public WorkflowStepRest getStep(@Nullable HttpServletRequest request,
Integer poolTaskId,
@Nullable Pageable optionalPageable,
Projection projection) {
dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/ClaimedTaskStepLinkRepository.java:52
- This adds the missing authorization guard on the claimedtask
/steplink, but there are no integration tests asserting unauthorized/forbidden access is blocked for this subresource (only the parent/claimedtasks/{id}endpoints appear to be tested). Please add IT coverage for/api/workflow/claimedtasks/{id}/stepfor 401 (anonymous) and 403 (logged-in user without READ permission) cases.
@PreAuthorize("hasPermission(#claimedTaskId, 'CLAIMEDTASK', 'READ')")
public WorkflowStepRest getStep(@Nullable HttpServletRequest request,
Integer claimedTaskId,
@Nullable Pageable optionalPageable,
Projection projection) {
Cover the /step subresource of pooltasks, claimedtasks and workflowitems: anonymous -> 401, authenticated user without READ permission -> 403, task owner / administrator -> 200. Guards against regressing the missing @PreAuthorize checks (internal security audit 2026_07_20_dq). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@MatusBeke
|
…ator WorkflowRestPermissionEvaluatorPlugin dereferenced the result of workflowItemService.find() without a null check, so an unknown id from an authenticated non-admin threw a NullPointerException (HTTP 500) instead of 404. The sibling PoolTask/ClaimedTask evaluators already guard this case; mirror them by returning true for a null item so the handler can produce the proper 404. Now reachable via the newly authorized /step subresource. Add a regression test asserting an unknown workflowitem /step id yields 404. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Correction on my point 3 above — I overstated it. Re-reading It's still a different severity/shape from the |
Summary
The
getStep()link methods onWorkflowItemStepLinkRepository,PoolTaskStepLinkRepositoryandClaimedTaskStepLinkRepositorywere missing a@PreAuthorizecheck — unlike their sibling workflowitem link repositories(collection / item / submitter) and the parent endpoints.
Because
@LinkRestmethods are invoked directly on the link repository, theparent's authorization is never evaluated, so the
/stepsubresource is reachablewithout the access control its parent enforces.
Change
Apply the same READ permission check the parent repositories already use, so each
/stepsubresource enforces the same authorization as its parent:WorkflowItemStepLinkRepositoryhasPermission(#workflowItemId, 'WORKFLOWITEM', 'READ')PoolTaskStepLinkRepositoryhasPermission(#poolTaskId, 'POOLTASK', 'READ')ClaimedTaskStepLinkRepositoryhasPermission(#claimedTaskId, 'CLAIMEDTASK', 'READ')Origin
Found during internal security audit (2026_07_20_dq).