databrickslabs / databrickslabs/ontos

[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.

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

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.

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.

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.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.