Skip to content

Fixes #29145: Prevent NPE when query tags are null#29249

Open
kumarroshan12 wants to merge 3 commits into
open-metadata:mainfrom
kumarroshan12:fix-piimasker-null-tags
Open

Fixes #29145: Prevent NPE when query tags are null#29249
kumarroshan12 wants to merge 3 commits into
open-metadata:mainfrom
kumarroshan12:fix-piimasker-null-tags

Conversation

@kumarroshan12

@kumarroshan12 kumarroshan12 commented Jun 20, 2026

Copy link
Copy Markdown

Describe your changes:

Fixes #29145

This PR fixes a NullPointerException in PIIMasker when query tags are not loaded and query.getTags() returns null.

The issue occurred when non-admin users accessed queries without requesting the tags field (for example, GET /api/v1/queries?fields=queryUsedIn). The masking logic attempted to call .stream() on a null tag list, resulting in a server error.

Changes made:

  • Added a null check in hasPiiSensitiveTag(Query) before streaming tags.
  • Added a regression test covering queries with null tags for unauthorized users.

Type of change:

  • Bug fix

High-level design:

N/A — small change.

Tests:

Use cases covered

  • Unauthorized user accessing queries when query.getTags() is null
  • Existing query masking behavior for authorized and unauthorized users remains unchanged

Unit tests

  • I added unit tests for the new/changed logic.

  • Files added/updated:

    • PIIMaskerTest.java
    • PIIMasker.java

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (no UI changes).

Manual testing performed

  1. Added a regression test with query.setTags(null)
  2. Verified the test failed with:
    Cannot invoke "java.util.List.stream()" because query.getTags() is null
  3. Added null handling in hasPiiSensitiveTag(Query)
  4. Re-ran PIIMaskerTest
  5. Verified all tests passed (8/8)

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes #29145: Prevent NPE when query tags are null
  • My PR is linked to a GitHub issue via Fixes #29145 above.
  • I have commented on my code, particularly in hard-to-understand areas. (Not applicable - small backend bug fix.)
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed. (Not applicable - small backend bug fix.)
  • For UI changes: I attached a screen recording and/or screenshots above. (Not applicable - small backend bug fix.)
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added a test that covers the exact scenario we are fixing.

Greptile Summary

This PR adds a null guard to hasPiiSensitiveTag(Query) in PIIMasker.java, preventing an NPE when query.getTags() returns null — a situation that arises when non-admin users access queries without requesting the tags field. A regression test is included that exercises the exact failure path.

  • PIIMasker.java: Replaced the direct .getTags().stream() call with listOrEmpty(query.getTags()).stream(), consistent with the listOrEmpty utility already used elsewhere in the class.
  • PIIMaskerTest.java: Added a test that sets tags to null, simulates an unauthorized user, and asserts no NPE is thrown and the query text passes through correctly.

Confidence Score: 5/5

Safe to merge — the change is a single, well-scoped null guard that matches an existing utility pattern in the class.

The fix replaces one unsafe .getTags().stream() call with listOrEmpty(query.getTags()).stream(), which is exactly how every other nullable tag list in the class is handled. The regression test directly reproduces the reported failure path. No behavior changes for the happy path.

No files require special attention.

Important Files Changed

Filename Overview
openmetadata-service/src/main/java/org/openmetadata/service/security/mask/PIIMasker.java One-line fix replacing direct .getTags().stream() with listOrEmpty(query.getTags()).stream() to guard against null tags on Query; change is minimal, correct, and consistent with existing codebase patterns.
openmetadata-service/src/test/java/org/openmetadata/service/security/mask/PIIMaskerTest.java Adds a focused regression test covering the null-tags NPE path for unauthorized users; test setup, assertions, and mocking are appropriate.

Comments Outside Diff (1)

  1. openmetadata-service/src/main/java/org/openmetadata/service/security/mask/PIIMasker.java, line 312-344 (link)

    P1 Same null-tags NPE risk in Table, SearchIndex, and Topic overloads

    hasPiiSensitiveTag(Table) (line 313), hasPiiSensitiveTag(SearchIndex) (line 324), and hasPiiSensitiveTag(Topic) (line 333) all call .getTags().stream() without a null guard. If any API path retrieves those entities without the tags field (just as GET /queries?fields=queryUsedIn reproduced the original bug), the identical NPE will surface. Notably, hasPiiSensitiveTag(Container) already has the null check at line 317, confirming the pattern has been hit before — it just wasn't applied consistently.

Reviews (3): Last reviewed commit: "Apply spotless formatting" | Re-trigger Greptile

@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@kumarroshan12

Copy link
Copy Markdown
Author

Hi maintainers,

I addressed the review feedback by using listOrEmpty(query.getTags()) and verified the updated tests pass locally.

It looks like the PR is currently blocked because:

Could someone please help with the project metadata and workflow approval?

Thank you!

@harshach harshach added the safe to test Add this label to run secure Github workflows on PRs label Jun 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

The Java checkstyle failed.

Please run mvn spotless:apply in the root of your repository and commit the changes to this PR.
You can also use pre-commit to automate the Java code formatting.

You can install the pre-commit hooks with make install_test precommit_install.

@github-actions

github-actions Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (15 flaky)

✅ 4305 passed · ❌ 0 failed · 🟡 15 flaky · ⏭️ 88 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 302 0 0 4
🟡 Shard 2 812 0 3 9
🟡 Shard 3 815 0 1 8
🟡 Shard 4 852 0 7 12
🟡 Shard 5 732 0 1 47
🟡 Shard 6 792 0 3 8
🟡 15 flaky test(s) (passed on retry)
  • Features/ContextCenter.spec.ts › searching documents filters the list to matching results (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › Admin: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › EditAll User: Complete export-import-validate flow (shard 2, 1 retry)
  • Features/KnowledgeCenterList.spec.ts › Knowledge Center List - Verify Recently Viewed widget (shard 3, 1 retry)
  • Flow/ObservabilityAlerts.spec.ts › Test case alert (shard 4, 1 retry)
  • Flow/PersonaFlow.spec.ts › Set default persona for team should work properly (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Markdown (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Entity Reference List (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Email (shard 4, 1 retry)
  • Pages/CustomProperties.spec.ts › Should search custom properties for apiCollection in right panel (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Description Add, Update and Remove for child entities (shard 4, 1 retry)
  • Pages/EntityDataConsumer.spec.ts › Tier Add, Update and Remove (shard 5, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › Column lineage for searchIndex -> dashboard (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/Users.spec.ts › Create and Delete user (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@gitar-bot

gitar-bot Bot commented Jun 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Adds a null guard to the PIIMasker query-tag stream to prevent NullPointerException and includes a regression test for unauthorized user access. The implementation correctly resolves the reported issue.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Non-admins are receiving a 500 from API call

2 participants