potiuk opened a new pull request, #67493: URL: https://github.com/apache/airflow/pull/67493
The bulk pool / connection / variable endpoints build an `existing_*_to_team` lookup from request entities, but the filter that decides which entities go into that lookup explicitly excludes every `BulkAction.CREATE`. For `CREATE + action_on_existence=overwrite`, the PUT-method authz check added in `_get_resource_methods_from_bulk_request()` then runs with `team_name=None` even when the resource being overwritten already belongs to a team — bypassing the per-team membership check the single-item PUT endpoint enforces. Reported as F-002 in the [`apache/tooling-agents` L3 ASVS sweep `0920c77`](https://github.com/apache/tooling-agents/issues/23). ## Why this is not a CVE Multi-team (`[core] multi_team`) is documented as **experimental** in [`security_model.rst#future-multi-team-isolation`](https://github.com/apache/airflow/blob/main/airflow-core/docs/security/security_model.rst#future-multi-team-isolation) and explicitly does not provide task-level isolation guarantees: *"Deployment Managers who enable the multi-team feature should not rely on it alone for security-critical isolation between teams at the task execution layer."* The bypass surfaces only in deployments that have already accepted the documented experimental-isolation trade-off, so it is a defense-in-depth fix on an experimental surface rather than a vulnerability disclosure. The bulk path should still match single-item PUT authz behaviour either way. ## Change Add `_bulk_action_needs_existing_team_lookup()` that returns `True` for UPDATE / DELETE and for `CREATE + OVERWRITE`. The three bulk authz functions (`requires_access_pool_bulk`, `requires_access_connection_bulk`, `requires_access_variable_bulk`) now use that helper instead of the bare `action.action != BulkAction.CREATE` filter, so CREATE+OVERWRITE entities are included in the team-name lookup and the PUT check sees the actual owning team. ## Test plan - [x] Updated `test_requires_access_pool_bulk` / `test_requires_access_connection_bulk` / `test_requires_access_variable_bulk` to use a realistic mock (CREATE+OVERWRITE entity exists with a team) and assert (a) the names looked up against the DB are the union of DELETE + CREATE+OVERWRITE entities, (b) the POST and PUT authz requests for the CREATE+OVERWRITE entity carry the existing team name. - [x] `prek run ruff` clean on touched files. - [x] `prek run mypy-airflow-core` clean on `security.py`. - [x] All three bulk-authz tests pass. --- ##### Was generative AI tooling used to co-author this PR? - [X] Yes — Claude Code (Opus 4.7) Generated-by: Claude Code (Opus 4.7) following [the guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions) -- 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]
