[Bug]: Data Consumer gets 403 on GET /assets/{id} even when asset is linked to an active Data Product

Open Beginner friendly
#583 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
python

Research direction

Start in src/backend/src/controller/assets_manager.py at resolve_accessible_asset_ids, then trace its GET /api/assets/{id} caller and the DataProductsManager.list_products fail-closed behavior. Check the is_visible_consumer rule against active and deprecated products. Done when a consumer can load an asset linked to a published Data Product while unrelated assets remain denied.

Written by the indexing model from the issue text.

Description

Summary

A Data Consumer navigating to an asset detail page (/assets/<id>) receives a 403 even when:

  • The asset is explicitly linked to a Data Product (via a Deliverable / OutputPort)
  • That Data Product has active status

Steps to reproduce

  1. Create a Data Product with status active
  2. Add an asset as a Deliverable (OutputPort → linked asset via portHasTable / portHasView etc.)
  3. Switch to the Data Consumer role
  4. Navigate directly to /assets/<asset-id> (e.g. by clicking the asset link on the DP detail page)

Expected: Asset detail page loads — consumer has access because the asset is attached to a published DP.
Actual: 403 — "Asset is not linked to a Data Product accessible to this user."

Root cause

AssetsManager.resolve_accessible_asset_ids (called from GET /api/assets/{id} consumer path) delegates to DataProductsManager.list_products(is_admin=False) with no caller context (no caller_email, no caller_team_ids, no caller_project_ids).

DataProductsRepository.get_multi has a fail-closed guard: when is_admin=False and all three scope inputs are None, it returns [] immediately rather than applying any status filter. This was intentional for the DP listing endpoint, but resolve_accessible_asset_ids relies on the old assumption that list_products(is_admin=False) returns at least the published (active/deprecated) DPs.

The result: resolve_accessible_asset_ids always returns an empty set for any non-admin caller → every asset is denied → 403.

Affected file

src/backend/src/controller/assets_manager.pyresolve_accessible_asset_ids method.

Proposed fix

The purpose of resolve_accessible_asset_ids is "which assets can a consumer see via the marketplace?" — i.e. assets of published DPs, regardless of caller ownership. The fix is to fetch all products with is_admin=True and filter locally to consumer-visible statuses:

from src.common.version_visibility import is_visible_consumer

products = data_products_manager.list_products(
    skip=0, limit=10_000, is_admin=True,
)
products = [p for p in products if is_visible_consumer(p)]

This matches the catalogue/marketplace contract: published (active/deprecated) DP assets are readable by any caller with data-products:READ_ONLY.

Dominant language
Python
Stars
212
Forks
71
Avg merge
4d 10h
Merged PRs (30d)
43

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from databrickslabs/ontos

All issues in databrickslabs/ontos

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.