You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
proxy/internal/DefaultSampleDataService.targetAllowed admits a table preview when allowedTables.contains(bare) || allowedTables.contains(qualified) || allowedSchemas.contains(schema).
With allowed_tables = [orders], GET /api/v1/datasources/{id}/sample-rows?schema=archive&table=orders
therefore reads archive.orders, while the query gate
(workflow/internal/DatasourcePermissionChecker.rejectedTables → core.api.AllowedTables.coveringEntry)
rejects SELECT * FROM archive.orders. A bare entry only covers an unqualified reference in the gate;
the preview always addresses a concrete schema.table, so the bare-name shortcut widens it.
#936 (PR #1088) narrows introspectSchema for non-admins, which already hides the ambiguous case from resolveTarget — but targetAllowed is the explicit second check and must stand on its own.
Fix
Reuse core.api.AllowedTables (normalize / normalizeEntry / coveringEntry) in DefaultSampleDataService; delete its private normalizeList / normalize copies.
A bare allowed_tables entry admits a schema-qualified preview target only when no other schema in the introspected view has a table of that name — the fail-closed rule core/internal/SchemaViewPermissionFilter uses (core: scope schema introspection to the caller's allow-list #936).
Same dedup in DefaultQueryDryRunService (private normalizeList + inline matcher → AllowedTables).
Unit tests in DefaultSampleDataServiceTest; document in docs/05-backend.md → "Sample data path (AF-443)".
Depends on #936 (PR #1088), which introduces core.api.AllowedTables.
Problem
proxy/internal/DefaultSampleDataService.targetAllowedadmits a table preview whenallowedTables.contains(bare) || allowedTables.contains(qualified) || allowedSchemas.contains(schema).With
allowed_tables = [orders],GET /api/v1/datasources/{id}/sample-rows?schema=archive&table=orderstherefore reads
archive.orders, while the query gate(
workflow/internal/DatasourcePermissionChecker.rejectedTables→core.api.AllowedTables.coveringEntry)rejects
SELECT * FROM archive.orders. A bare entry only covers an unqualified reference in the gate;the preview always addresses a concrete
schema.table, so the bare-name shortcut widens it.#936 (PR #1088) narrows
introspectSchemafor non-admins, which already hides the ambiguous case fromresolveTarget— buttargetAllowedis the explicit second check and must stand on its own.Fix
core.api.AllowedTables(normalize/normalizeEntry/coveringEntry) inDefaultSampleDataService; delete its privatenormalizeList/normalizecopies.allowed_tablesentry admits a schema-qualified preview target only when no other schema in the introspected view has a table of that name — the fail-closed rulecore/internal/SchemaViewPermissionFilteruses (core: scope schema introspection to the caller's allow-list #936).DefaultQueryDryRunService(privatenormalizeList+ inline matcher →AllowedTables).DefaultSampleDataServiceTest; document indocs/05-backend.md→ "Sample data path (AF-443)".Depends on #936 (PR #1088), which introduces
core.api.AllowedTables.