Skip to content

Add missing @PreAuthorize to ProcessRestRepository#delete - #1386

Open
MatusBeke wants to merge 2 commits into
dtq-devfrom
fix/dq-sa-001-process-delete-preauth
Open

Add missing @PreAuthorize to ProcessRestRepository#delete#1386
MatusBeke wants to merge 2 commits into
dtq-devfrom
fix/dq-sa-001-process-delete-preauth

Conversation

@MatusBeke

Copy link
Copy Markdown
Collaborator

Problem

DELETE /api/system/processes/{id} had no method-level authorization check. An anonymous, unauthenticated request could delete any process record.

Root cause

ProcessRestRepository#delete lacked @PreAuthorize, unlike its siblings (findOne, findAll, findByCurrentUser). The only authorization check lived inside ProcessServiceImpl#delete's per-bitstream loop (via bitstreamService.delete()). A process with zero bitstreams (e.g. status SCHEDULED) skips that loop entirely, so the check never runs and the delete proceeds unauthorized.

Change set

Adds @PreAuthorize("hasPermission(#integer, 'PROCESS', 'DELETE')") on ProcessRestRepository#delete, mirroring the existing pattern already used on findOne. Reuses the existing ProcessRestPermissionEvaluatorPlugin (owner-or-admin check, independent of READ/WRITE/DELETE) — no new plugin needed. One line, no other changes; out of scope: adding a regression IT for the zero-bitstream case (flagged below as a follow-up).

Test evidence

mvn -pl dspace-server-webapp -am -DskipTests install   -> BUILD SUCCESS
mvn checkstyle:check -pl dspace-server-webapp          -> 0 Checkstyle violations

Risk & rollback

Purely additive authorization check — only tightens access; the existing owner/admin callers are unaffected. Rollback = revert the single annotation line.

Notes / assumptions

  • Originated from security audit (2026_07_20_dq)
  • Follow-up (not blocking): add a ProcessRestRepositoryIT case asserting an anonymous DELETE on a bitstream-less (SCHEDULED) process now returns 401/403 instead of 204.

DELETE /api/system/processes/{id} had no method-level authorization
check, unlike its siblings (findOne, findAll, findByCurrentUser). The
only check lived inside ProcessServiceImpl#delete's per-bitstream
loop, so a process with zero bitstreams (e.g. status SCHEDULED)
skipped the loop entirely and bypassed authorization, letting an
anonymous DELETE remove any process record.

Adds hasPermission(#integer, 'PROCESS', 'DELETE'), matching findOne.
Reuses the existing ProcessRestPermissionEvaluatorPlugin (owner-or-
admin check, independent of READ/WRITE/DELETE) - no new plugin needed.

Originated from security audit (2026_07_20_dq)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Tightens security on the System Processes REST API by adding a missing method-level authorization check to prevent unauthorized deletion of process records via DELETE /api/system/processes/{id}.

Changes:

  • Adds @PreAuthorize("hasPermission(#…, 'PROCESS', 'DELETE')") to ProcessRestRepository#delete to align with existing authorization patterns on related endpoints.

Comment on lines 167 to 169
@PreAuthorize("hasPermission(#integer, 'PROCESS', 'DELETE')")
protected void delete(Context context, Integer integer)
throws AuthorizeException, RepositoryMethodNotImplementedException {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: renamed the parameter from integer to id (and updated the SpEL expression to #id), matching the convention used elsewhere in this class. Files: ProcessRestRepository.java. Validation: mvn -pl dspace-server-webapp -am install (BUILD SUCCESS) + checkstyle:check (0 violations).

}

@Override
@PreAuthorize("hasPermission(#integer, 'PROCESS', 'DELETE')")

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: added 3 cases to ProcessRestRepositoryIT covering DELETE authorization on the exact bitstream-less/SCHEDULED process shape that bypassed the check: deleteProcessAdmin (204, then 404 on re-fetch), deleteProcessAnonymousUnauthorizedException (401), deleteProcessForDifferentUserForbiddenException (403). Files: ProcessRestRepositoryIT.java. Validation: compiles clean under failsafe locally; full run needs the Docker Postgres/Solr stack this repo's CI already provisions (skipIntegrationTests=false in build.yml), so the authoritative run is the CI check on this PR.

- Rename delete()'s parameter from `integer` to `id` for consistency
  with the rest of the repository and to make the SpEL expression
  read clearly (#id vs #integer).
- Add ProcessRestRepositoryIT coverage for DELETE authorization on the
  bitstream-less/SCHEDULED process shape that previously bypassed the
  check entirely: admin succeeds (204, then 404 on re-fetch), anonymous
  is rejected (401), and a different authenticated user is rejected
  (403).

Addresses both Copilot review comments on PR #1386.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants