-
Notifications
You must be signed in to change notification settings - Fork 1.3k
SnowflakeRegistry._apply_object UPDATE path missing project_id filter - cross-project overwrites #6208
Description
Summary
SnowflakeRegistry.apply_object in sdk/python/feast/infra/registry/snowflake.py omits project_id from the WHERE clause on the UPDATE path, allowing an apply* call for one project to overwrite a same-named object belonging to a different project.
Problem
The _apply_object helper has two SQL branches:
- SELECT (existence check) — correctly scoped:
SELECT ... WHERE project_id = '{project}' AND {id_field} = '{name}' - UPDATE (overwrite) — missing project_id:
UPDATE ... WHERE {id_field} = '{name}'
Because the UPDATE does not include project_id in its WHERE clause, it matches all rows with that name across every project (when registry is shared). This affects every resource type that goes through _apply_object: entities, data sources, feature views, feature services, saved datasets, validation references, permissions, and infrastructure objects.
Reproducer
- Create a Snowflake-backed registry shared by two projects (project_a and project_b).
- In project_a, run feast apply with an entity named driver.
- In project_b, run feast apply with an entity also named driver (but with different configuration).
- Query project_a's driver entity — it now reflects project_b's definition because the UPDATE overwrote the row without filtering by project_id.
Expected behavior
The UPDATE query should include project_id in the WHERE clause so that only the row for the correct project is updated:
UPDATE ... WHERE project_id = '{project}' AND {id_field} = '{name}'
Impact
Affects all resource types (entities, data sources, feature views, feature services, saved datasets, validation references, permissions, infra objects).
Any multi-project deployment sharing a Snowflake registry is at risk of silent data corruption.
Note: The DELETE path (_delete_object) correctly includes project_id, so this bug is limited to the update/overwrite path.