Skip to content

fix(security): filter unreadable items/bitstreams from public usage statistics - #1540

Merged
milanmajchrak merged 3 commits into
dtq-devfrom
sec/usage-report-read-filter
Oct 28, 2026
Merged

milanmajchrak merged 3 commits into
dtq-devfrom
sec/usage-report-read-filter

Conversation

@Kasinhou

@Kasinhou Kasinhou commented Oct 27, 2026 •

Copy link
Copy Markdown

Problem

Public usage reports could disclose the identity of objects the caller cannot read:

  • Site TopItems returned names and UUIDs of inaccessible items.
  • An accessible item's TotalDownloads report returned filenames and IDs of individually restricted bitstreams.

Part of dataquest-dev/dspace-customers#1104 (R15), see #1083.

Fix

Check the caller's READ permission before including each item or bitstream in these reports. Skip missing objects instead of returning an unresolved URL. Resolve historical numeric bitstream IDs as well as UUIDs; return the resolved bitstream's canonical UUID.

The existing report structure, configuration and aggregation are preserved. Authorization applies to the requesting user, including non-admin users with explicit READ policies.

Tests

  • Site TopItems: anonymous sees only readable items; admin sees both.
  • Item TotalDownloads: anonymous sees only readable files; admin sees both.
  • A non-admin with explicit READ sees the restricted file; another user does not.
  • Historical numeric IDs resolve to canonical UUIDs and follow the same READ checks. Statistics for a deleted bitstream are skipped.

The two previously failing download tests now reload the existing fixtures into the current persistence context. They no longer create files through a detached collection.

Local validation: all 49 tests in StatisticsRestRepositoryIT passed (0 failures/errors), including existing report behavior and the UUID/legacy authorization cases. Production/test compilation and Checkstyle passed. Full GitHub CI must pass on the updated commit before merge.

Matus Kasak added 2 commits October 27, 2026 13:21
Site-level TopItems and item TotalDownloads reports returned the name and
UUID of items/files without checking the caller's READ permission, leaking
withdrawn/embargoed/restricted content to anonymous users.

Inject AuthorizeService and BitstreamService into UsageReportUtils and only
add a point when the current user has READ on the resolved item/bitstream.
Drop the unresolved raw-handle fallback in the site report.
Use BitstreamService#findByIdOrLegacyId with a null/blank guard instead of
UUID.fromString so migrated statistics rows with legacy numeric ids do not
crash the TotalDownloads report. Add a test proving a non-admin eperson with
an explicit READ policy still sees the restricted bitstream while another
eperson without it does not.

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.

🟡 Changes recommended

Serialize resolved legacy bitstreams using canonical UUIDs and add regression coverage for numeric legacy IDs.

1 open issue
What changed in this PR

This pull request prevents public usage-statistics reports from exposing unreadable items and bitstreams while preserving access for authorized users.

Changes:

  • Applies per-user READ authorization to site TopItems results.
  • Resolves bitstreams using UUIDs or legacy IDs before filtering TotalDownloads results.
  • Adds integration tests for anonymous, administrator, and explicitly authorized users.
File Summary
dspace-server-webapp/​src/​main/​java/​org/​dspace/​app/​rest/​utils/​UsageReportUtils.java Filters unreadable items and bitstreams from usage reports. A moderate issue remains: legacy numeric IDs should be serialized as the resolved bitstream UUID. A nit remains to add regression coverage for legacy numeric IDs.
dspace-server-webapp/​src/​test/​java/​org/​dspace/​app/​rest/​StatisticsRestRepositoryIT.java Adds coverage for restricted item and bitstream visibility across user roles; legacy numeric-ID resolution is not yet covered.

Review effort: Lite

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.

🟢 Approval recommended

The security filtering and legacy-ID handling are covered by integration tests, with no unresolved blocking issues.

No open issues 🎉

1 resolved since last review

Review effort: Lite

@milanmajchrak
milanmajchrak merged commit a88553d into dtq-dev Oct 28, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants