mikebridge opened a new pull request, #44093: URL: https://github.com/apache/superset/pull/44093
### SUMMARY The dashboard object-read gate (`security_manager.raise_for_access(dashboard=…)`) has three admit paths for non-admin, non-guest users: editorship, viewers (published-gated), and a datasource-based fallback used when the viewers list is empty — which also admits dashboards with **no charts** at all. The fallback ignored `published`, while the list filter's equivalent fallback branch has always been published-only (`superset/dashboards/filters.py`). Two concrete consequences: - an **unpublished** dashboard with an empty viewers list was readable by direct URL — for chart-less dashboards, by *every* authenticated user — even though it appeared in no list. Chart-less does not mean content-less: markdown-only dashboards are documents; - **removing the last viewer subject silently widened access**: with viewers set, reads require `published AND is_viewer`; emptying viewers dropped the dashboard into the fallback, which had no published check — restricting the audience loosened the gate. **Fix**: the fallback branch (including the chart-less admit) now requires `dashboard.published`, aligning the gate with the list filter. Owners, editors — including `EXTRA_EDITORS_RESOLVER`-granted editors — and admins are admitted *before* the fallback regardless of published state, so authoring flows over brand-new/empty dashboards are untouched; published dashboards keep their existing link-share semantics. Lineage note: the chart-less admit predates the current gate shape (the pre-#43781 fallback admitted on an empty `datasources` collection) and was preserved as pinned status-quo, not a fresh policy decision; this PR implements the ratified tightening. A SECURITY.md write-up of the object-read semantics (fallback breadth, published, guest asymmetry) follows separately. ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF N/A — authorization behavior. Before: unpublished + no viewers ⇒ fallback admit. After: fallback requires published; 403 otherwise. ### TESTING INSTRUCTIONS `pytest tests/unit_tests/dashboards/semantic_view_access_test.py` — 29 tests. The pre-existing fallback pins (published fixtures) pass unchanged; the empty-dashboard pin is re-scoped to published; two new deny pins land: `test_gate_denies_unpublished_empty_dashboard` (sc-120032) and `test_gate_denies_unpublished_dashboard_via_datasource_fallback` (the sc-120031 inversion). Reverting the production change flips exactly those two (verified via stash control). `tests/unit_tests/security/test_permission_hooks.py` and `tests/unit_tests/subjects/test_raise_for_access.py` pass unchanged (46 total across the three gate-test homes). Manual: as a non-editor with datasource access, open an unpublished dashboard with an empty viewers list by URL → 403; publish it → renders; add yourself as viewer while unpublished → still 403 (viewer branch requires published — unchanged behavior). ### ADDITIONAL INFORMATION - [ ] Has associated issue: - [ ] Required feature flags: - [ ] Changes UI - [ ] Includes DB Migration (follow approval process in [SIP-59](https://github.com/apache/superset/issues/13351)) - [ ] Migration is atomic, supports rollback & is backwards-compatible - [ ] Confirm DB migration upgrade and downgrade tested - [ ] Runtime estimates and downtime expectations provided - [ ] Introduces new feature or API - [ ] Removes existing feature or API 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JRLEJS4mUqKBoPjSjviKUW -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
