Skip to content

Enforce ti:self scope on /execution/task-reschedules/{ti}/start_date#67628

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:enforce-ti-self-scope-on-task-reschedules-start-date
Jun 21, 2026
Merged

Enforce ti:self scope on /execution/task-reschedules/{ti}/start_date#67628
potiuk merged 1 commit into
apache:mainfrom
potiuk:enforce-ti-self-scope-on-task-reschedules-start-date

Conversation

@potiuk

@potiuk potiuk commented May 27, 2026

Copy link
Copy Markdown
Member

Three sibling per-task-instance routers under airflow.api_fastapi.execution_api.routes opt into the ti:self JWT scope, which "verifies that the token's sub claim matches the {task_instance_id} path parameter, preventing a worker from accessing another task's endpoints" (per security/jwt_token_authentication.html): task_instances.py, hitl.py, and task_state.py. The task_reschedules.py router for GET /execution/task-reschedules/{task_instance_id}/start_date was missing that scope, so any authenticated worker could read the first reschedule timestamp of any task instance in the deployment by passing that task instance's UUID in the URL path.

This change adds the standard dependencies=[Security(require_auth, scopes=["ti:self"])] to the router declaration — the same pattern the three sibling routers already use. One new regression test under TestGetRescheduleStartDate exercises the mismatched-subject path and asserts 403.

Test plan

  • New regression test test_mismatched_subject_is_rejected asserts a mismatched JWT subject is rejected with 403 on the concrete route.
  • Existing TestGetRescheduleStartDate tests still pass (the conftest client fixture auto-matches the JWT subject to the path parameter, so happy-path tests are unaffected).
  • prek run --from-ref main --to-ref HEAD --stage pre-commit clean on touched files.
  • prek run --from-ref main --to-ref HEAD --stage manual clean on touched files.
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Opus 4.7 (1M context)

Generated-by: Claude Opus 4.7 (1M context) following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

@ashb ashb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As i said before: We should also add a dual to existing test_ti_self_routes_have_task_instance_id_param that tests that all routes with {task_instance_id} param in them either have ti:self or an explicit exclusion.

That is a much more useful test than re-testing the effect of the scope on one end point

@potiuk potiuk force-pushed the enforce-ti-self-scope-on-task-reschedules-start-date branch from ebe21d7 to 855f993 Compare June 5, 2026 02:05
@potiuk

potiuk commented Jun 5, 2026

Copy link
Copy Markdown
Member Author

Done — replaced the per-endpoint test with the structural dual you described. test_routes_with_task_instance_id_param_enforce_ti_self now asserts every operation exposing a {task_instance_id} path param requires the ti:self scope (or is on an explicit, currently-empty TI_ID_ROUTES_WITHOUT_TI_SELF allowlist), and dropped test_mismatched_subject_is_rejected.

One implementation note: I couldn't do it by walking app.routes like the existing forward test — the execution API assembles routes per version, so in the test harness static route introspection only surfaces a single top-level route. So it checks the served OpenAPI spec (security per operation) across every version in the bundle instead. Verified it's non-vacuous (12 such paths) and that it actually catches the gap: reverting the ti:self dependency makes it fail, listing GET /task-reschedules/{task_instance_id}/start_date across all versions.

Side note from that: the existing test_ti_self_routes_have_task_instance_id_param (forward direction) appears to be effectively vacuous for the same route-introspection reason — happy to convert it to the OpenAPI approach in a follow-up if you agree.


Drafted-by: Claude Code (Opus 4.8); reviewed by @potiuk before posting

@potiuk potiuk force-pushed the enforce-ti-self-scope-on-task-reschedules-start-date branch 2 times, most recently from d24359b to 70b90cf Compare June 5, 2026 16:49
Three sibling per-task-instance routers under `airflow.api_fastapi.execution_api.routes` opt into the `ti:self` JWT scope, which verifies that the token's `sub` claim matches the `{task_instance_id}` path parameter, preventing a worker from accessing another task's endpoints: `task_instances.py`, `hitl.py`, and `task_state.py`. The `task_reschedules.py` router for `GET /execution/task-reschedules/{task_instance_id}/start_date` was missing that scope, so any authenticated worker could read the first reschedule timestamp of any task instance in the deployment by passing that task instance's UUID in the URL path.

This change adds the standard `dependencies=[Security(require_auth, scopes=["ti:self"])]` to the router declaration — the same pattern the three sibling routers already use. One new regression test under `TestGetRescheduleStartDate` exercises the mismatched-subject path and asserts 403.

Reference: airflow-s/airflow-s#406

Generated-by: Claude Opus 4.7 (1M context) following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions
@potiuk potiuk force-pushed the enforce-ti-self-scope-on-task-reschedules-start-date branch from 70b90cf to eef3797 Compare June 5, 2026 16:53
@potiuk potiuk requested a review from ashb June 11, 2026 17:33
@potiuk

potiuk commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

@ashb — circling back: the structural dual you asked for went in on the 5th (test_routes_with_task_instance_id_param_enforce_ti_self) — it walks every {task_instance_id} operation across all API versions and asserts each carries ti:self or sits in an explicit TI_ID_ROUTES_WITHOUT_TI_SELF exclusion set. PR's mergeable + green. Could you take another look / clear the change-request? Thanks!

@potiuk potiuk added this to the Airflow 3.3.0 milestone Jun 21, 2026
@potiuk potiuk merged commit ab68720 into apache:main Jun 21, 2026
90 checks passed
@potiuk potiuk deleted the enforce-ti-self-scope-on-task-reschedules-start-date branch June 21, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:API Airflow's REST/HTTP API area:task-sdk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants