Repository navigation
Authorize POST /assets/events on the asset named in the body - #73007
Conversation
The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri.
Checking the asset both in the dependency and in the route authorized the same request twice, and dropping the dependency would have made the generated permission docs list the endpoint as public. Reading the asset id from the validated body in the dependency keeps a single per-asset check that the docs still see.
|
Hi maintainer, this PR was merged without a milestone set.
|
Backport failed to create: v3-3-test. View the failure log Run detailsNote: As of Merging PRs targeted for Airflow 3.X In matter of doubt please ask in #release-management Slack channel.
You can attempt to backport this manually by running: cherry_picker 9636fcb v3-3-testThis should apply the commit to the v3-3-test branch and leave the commit in conflict state marking After you have resolved the conflicts, you can continue the backport process by running: cherry_picker --continueIf you don't have cherry-picker installed, see the installation guide. |
…#73139) The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri. Co-authored-by: Henry Chen <henrychen@apache.org>
…#73139) The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri. Co-authored-by: Henry Chen <henrychen@apache.org>
…#73139) The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri. Co-authored-by: Henry Chen <henrychen@apache.org>
…73458) * [v3-3-test] Clarify that AccessView.JOBS is the Edge worker management permission (#72627) (#73073) The Edge UI plugin docs say that "can read on Plugins" and "can read on Jobs" let you view the UI and manage the workers, but they do not say how the two permissions differ, and they do not mention what the default Viewer role already holds. Both gaps matter, because the endpoints and the navigation are gated differently: - The worker management endpoints under /edge_worker/ui/ check only AccessView.JOBS, and the check is not method-aware -- the same dependency guards the GET reads and the POST/PATCH/DELETE mutations. - "can read on Plugins" only controls whether the plugin shows up in the UI navigation. It is not required in order to call the endpoints. So "can read on Jobs" alone is enough to shut down, delete, re-queue and retune Edge workers, whether or not the plugin is visible to that user. That is intentional -- AccessView.JOBS is the management permission for the plugin rather than a read-only grant -- but it reads as surprising from the code alone, where a permission named "can read" guards mutating routes. It is more surprising in a default Flask AppBuilder setup, where the Viewer role includes (ACTION_CAN_READ, RESOURCE_JOB) but not the Plugins read: such a user cannot see the Edge plugin and can still reach its management endpoints. Adds a warning to the UI plugin docs stating the intent, the split between the two permissions, the consequence for the default Viewer role, and the concrete action for deployments where Viewers must not manage workers. Points at the existing "fine granular access control" entry in architecture.rst rather than restating it. Documentation only; no behaviour change. (cherry picked from commit 1391b09) * [v3-3-test] Keep the Gradle wrapper jar out of the source release (#69444) (#73108) ASF policy does not permit compiled binaries in a source release and the Gradle wrapper is not among the exempted build tools (LEGAL-570), so main stopped shipping java-sdk/gradle/wrapper/gradle-wrapper.jar in #69444. Only half of that change reached this branch. The breeze side already restores gradlew and gradlew.bat after `git archive` drops them, but the java-sdk/.gitattributes side never followed, so nothing is actually dropped and the 43 KB jar is still in the 3.3.2rc1 source tarball. Carrying the rest of the file over also starts shipping java-sdk/.editorconfig, which the root .gitattributes strips today even though ktlint reads it at build time and the build task requires that lint to pass. gradle-wrapper.properties stays in the tarball on purpose: it carries the pinned Gradle version and distribution checksum a verifier needs to regenerate the wrapper. Generated-by: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DCUVuZ8CCeER1QLhVEKAaZ * Authorize POST /assets/events on the asset named in the body (#73007) (#73139) The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri. Co-authored-by: Henry Chen <henrychen@apache.org> * Bump the 3-3-fab-ui-package-updates group across 1 directory with 3 updates (#73208) Bumps the 3-3-fab-ui-package-updates group with 3 updates in the /providers/fab/src/airflow/providers/fab/www directory: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) and [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env). Updates `@babel/core` from 8.0.1 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/packages/babel-core) Updates `@babel/eslint-parser` from 8.0.1 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/eslint/babel-eslint-parser) Updates `@babel/preset-env` from 8.0.2 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/packages/babel-preset-env) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates - dependency-name: "@babel/eslint-parser" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates - dependency-name: "@babel/preset-env" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Reject non-numeric --limit values in airflow dags list-jobs (#72891) (#73214) The --limit option had no argparse type, so a value such as "abc" or "-1" was passed straight into the SQLAlchemy query and surfaced as a raw ValueError traceback instead of a usage error. Validating it at parse time gives the standard argparse message and exit code 2, while keeping 0 and positive integers working exactly as before. (cherry picked from commit 022ff83) Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> * [v3-3-test] Fix DAG.cli() crashing on dags test --show-dagrun (#72810) (#73216) * Fix DAG.cli() crashing on dags test --show-dagrun A Dag file run as a script goes through DAG.cli(), whose parser drops the dag_id positional and passes the Dag object to the handler instead. dag_test never needed dag_id from the parsed arguments until it rendered the run: the task instance query read args.dag_id, so --show-dagrun, --save-dagrun and --imgcat-dagrun raised AttributeError after the Dag had already run, while the plain command and the regular airflow dags test path worked. Filtering on the resolved Dag's id is the same value on the regular path and the only one available from DAG.cli(). * Update airflow-core/tests/unit/cli/commands/test_dag_command.py * Update airflow-core/tests/unit/cli/commands/test_dag_command.py --------- (cherry picked from commit 63fc32f) Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> Co-authored-by: Henry Chen <henryhenry0512@gmail.com> * Split the api_fastapi common parameters module into a package (#73239) The parameters module had grown to ~1800 lines mixing generic query helpers with hundreds of domain-specific query-parameter aliases, making it hard to navigate and maintain. Grouping the machinery (base, search, filter, sort, range) and the per-domain aliases (dag, dag_run, task_instance, xcom, asset, misc) into focused submodules keeps each file readable. The package __init__ re-exports the names consumed elsewhere in the codebase so existing import paths keep working. Backport of #72795 to v3-3-test. Because v3-3-test's parameters.py has a smaller set of query-parameter definitions than main (some PRs were not backported), this was re-created by running the same mechanical split on v3-3-test's file rather than cherry-picked: every definition is byte-identical to the original, and __init__ re-exports only the names consumed outside the package. * [v3-3-test] Document that plugin names must be unique (#73197) (#73203) (cherry picked from commit 49674b7) Co-authored-by: Aaron Chen <nailo2c@gmail.com> * [v3-3-test] Decode deadline alert interval and callback without generic deserialization (#72651) (#73304) * Decode deadline alert interval and callback without generic deserialization decode_deadline_alert passed the Dag-author controlled interval and callback to airflow.sdk.serde.deserialize, which imports the class named in the payload and instantiates it with the encoded arguments. These decoders run in the scheduler and the API server whenever a serialized Dag is loaded, so any class under the airflow.* allow list could be constructed there. The security model says a Dag author reaches those processes only through registered plugins and providers, and the codebase enforces that at decode time for timetables, priority weight strategies and operator extra links. Deadline fields had no equivalent gate. Both fields are now rebuilt from their encoded form directly: * interval accepts a number, a timedelta payload, or a variable-interval payload carrying a key, each reconstructed from primitives. * callback accepts AsyncCallback or SyncCallback, selected from a fixed map rather than imported by name, with path as a string, queue/executor as optional strings, and unexpected fields refused. Neither reaches serde.deserialize, so the class a Dag author names in either field is never imported. Filtering in front of deserialize was tried first and was not sufficient. serde normalises the legacy {__type, __var} shape into __classname__ *inside* deserialize, so a payload inspected beforehand carries no class name to reject. Payloads are normalised before inspection here, and that case is tested. Known residual, deliberately not closed here: callback kwargs are still passed through generic deserialization, so a legitimate callback can carry an arbitrary allow-listed class under its kwargs. Deferring that decode to the process that runs the callback would close it, but the kwargs are consumed through two paths using two different encodings, and getting either wrong hands user code an encoded dict in place of its argument. The residual is not specific to deadlines -- it is the general property of deserializing Dag-author data, shared with every other serde call site. A test asserts the current behaviour so the gap stays visible and any change to it has to be deliberate. Tests assert the class is never constructed rather than that an error is raised. Against unpatched sources the callback case reports DID NOT RAISE and the interval case names the instance that had already been built. * Accept pre-3.2 callback paths and validate fields per callback class Review feedback on the deadline decoding gate. Callbacks moved out of airflow.sdk.definitions.deadline in 3.2, so alerts serialized by an earlier version name the old module. The allow list only held the current path, which would have made those rows undecodable on upgrade -- the same backward-compatibility case the interval allow list already covers. The permitted callback fields were a hardcoded set covering both subclasses at once, so a payload could carry queue on a SyncCallback or executor on an AsyncCallback. The set is per class, and each class already declares its own via serialized_fields(), so ask it rather than restating the answer here and letting the two drift. That also turns a TypeError raised from inside the rebuild into the intended refusal, and the check now runs before anything is reconstructed from the payload. (cherry picked from commit c614c57) Generated-by: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012zrnHJHPchB83FtwrYRf5q Co-authored-by: Jarek Potiuk <jarek@potiuk.com> * Bump swagger-ui-dist (#73332) Bumps the 3-3-registry-package-updates group with 1 update in the /registry directory: [swagger-ui-dist](https://github.com/swagger-api/swagger-ui). Updates `swagger-ui-dist` from 5.32.14 to 5.32.15 - [Release notes](https://github.com/swagger-api/swagger-ui/releases) - [Commits](swagger-api/swagger-ui@v5.32.14...v5.32.15) --- updated-dependencies: - dependency-name: swagger-ui-dist dependency-version: 5.32.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: 3-3-registry-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webpack (#73333) Bumps the 3-3-fab-ui-package-updates group with 1 update in the /providers/fab/src/airflow/providers/fab/www directory: [webpack](https://github.com/webpack/webpack). Updates `webpack` from 5.110.3 to 5.111.0 - [Release notes](https://github.com/webpack/webpack/releases) - [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md) - [Commits](webpack/webpack@v5.110.3...v5.111.0) --- updated-dependencies: - dependency-name: webpack dependency-version: 5.111.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-3-fab-ui-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Skip provider dependency generation for help command in breeze cli (#71689) (#73330) (cherry picked from commit 60633c8) Co-authored-by: feberbo <felipeboralli@gmail.com> * Bump the github-actions-updates group with 5 updates (#73344) Bumps the github-actions-updates group with 5 updates: | Package | From | To | | --- | --- | --- | | [actions/setup-java](https://github.com/actions/setup-java) | `6.0.0` | `6.0.1` | | [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) | `10.0.1` | `10.1.0` | | [github/codeql-action/init](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | | [github/codeql-action/autobuild](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | | [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | Updates `actions/setup-java` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](actions/setup-java@dd06d9c...de7274f) Updates `astral-sh/setup-uv` from 10.0.1 to 10.1.0 - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](astral-sh/setup-uv@20cfd1b...bec219d) Updates `github/codeql-action/init` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) Updates `github/codeql-action/autobuild` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-updates - dependency-name: astral-sh/setup-uv dependency-version: 10.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/init dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/autobuild dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/analyze dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Make the constraints check follow the cooldown rules the constraints use (#73316) (#73385) After every provider release wave the `Deps *:constraints` jobs doubled for three or four days and then recovered on their own. The constraints are resolved under uv's `exclude-newer` cooldown with the per-package overrides in the root pyproject.toml, where Airflow's own distributions are exempt, so a fresh provider wave lands in the constraints the same day. The check had its own 4-day cooldown applied to every package, so for those days the pin was newer than "latest" and a plain equality check counted it as outdated. With `--explain-why` every such package then cost a full `uv sync` that tried to pin it to the *older* version and reported that the pin did not take effect. On 2026-09-15 that was 37 providers and about 12 extra minutes per job, with nothing to act on. The check now reads `[tool.uv.exclude-newer-package]` and applies the same rules: no cooldown for exempt distributions, a moved cutoff where one is configured. A pin that is still ahead of "latest" counts as up to date, so no explanation runs for it either. (cherry picked from commit 7da73c8) Generated-by: Claude Opus 5 Co-authored-by: Jarek Potiuk <jarek@potiuk.com> * Stop shipping broken agent-skill symlinks in the source release (#73107) (#73448) Excluding .agents from the source tarball (#68851) left .claude behind. Everything under .claude/skills is a relay symlink into .agents/skills, so export-ignore strips the targets while the links themselves still ship: unpacking the source release yields broken symlinks, and .claude/ arrives holding nothing but those dead links. Found while verifying 3.3.2rc1, whose tarball carries five of them. The released 3.3.1 carries the same ones, so this is long-standing rather than something a recent change introduced. .github needs no equivalent entry: its own skills relays are already covered by the existing .github export-ignore. (cherry picked from commit 4b0eb8e) * [v3-3-test] Run the scheduled CI upgrade check on v3-3-test (#73318) 3.3.x is the release branch under active maintenance, so its pinned uv, prek and image versions drift the same way main's do — but nothing has been refreshing them, because the only caller targets main. v3-2-test carried the same caller until it stopped taking releases. (cherry picked from commit 39c9a5d) Co-authored-by: Jarek Potiuk <jarek@potiuk.com> Generated-by: Claude Code (Opus 5) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Jarek Potiuk <jarek@potiuk.com> Co-authored-by: Vincent <97131062+vincbeck@users.noreply.github.com> Co-authored-by: Henry Chen <henrychen@apache.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> Co-authored-by: Henry Chen <henryhenry0512@gmail.com> Co-authored-by: Pierre Jeambrun <pierrejbrun@gmail.com> Co-authored-by: Aaron Chen <nailo2c@gmail.com> Co-authored-by: feberbo <felipeboralli@gmail.com>
#73449) (#73459) * [v3-3-test] Clarify that AccessView.JOBS is the Edge worker management permission (#72627) (#73073) The Edge UI plugin docs say that "can read on Plugins" and "can read on Jobs" let you view the UI and manage the workers, but they do not say how the two permissions differ, and they do not mention what the default Viewer role already holds. Both gaps matter, because the endpoints and the navigation are gated differently: - The worker management endpoints under /edge_worker/ui/ check only AccessView.JOBS, and the check is not method-aware -- the same dependency guards the GET reads and the POST/PATCH/DELETE mutations. - "can read on Plugins" only controls whether the plugin shows up in the UI navigation. It is not required in order to call the endpoints. So "can read on Jobs" alone is enough to shut down, delete, re-queue and retune Edge workers, whether or not the plugin is visible to that user. That is intentional -- AccessView.JOBS is the management permission for the plugin rather than a read-only grant -- but it reads as surprising from the code alone, where a permission named "can read" guards mutating routes. It is more surprising in a default Flask AppBuilder setup, where the Viewer role includes (ACTION_CAN_READ, RESOURCE_JOB) but not the Plugins read: such a user cannot see the Edge plugin and can still reach its management endpoints. Adds a warning to the UI plugin docs stating the intent, the split between the two permissions, the consequence for the default Viewer role, and the concrete action for deployments where Viewers must not manage workers. Points at the existing "fine granular access control" entry in architecture.rst rather than restating it. Documentation only; no behaviour change. (cherry picked from commit 1391b09) * [v3-3-test] Keep the Gradle wrapper jar out of the source release (#69444) (#73108) ASF policy does not permit compiled binaries in a source release and the Gradle wrapper is not among the exempted build tools (LEGAL-570), so main stopped shipping java-sdk/gradle/wrapper/gradle-wrapper.jar in #69444. Only half of that change reached this branch. The breeze side already restores gradlew and gradlew.bat after `git archive` drops them, but the java-sdk/.gitattributes side never followed, so nothing is actually dropped and the 43 KB jar is still in the 3.3.2rc1 source tarball. Carrying the rest of the file over also starts shipping java-sdk/.editorconfig, which the root .gitattributes strips today even though ktlint reads it at build time and the build task requires that lint to pass. gradle-wrapper.properties stays in the tarball on purpose: it carries the pinned Gradle version and distribution checksum a verifier needs to regenerate the wrapper. Generated-by: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DCUVuZ8CCeER1QLhVEKAaZ * Authorize POST /assets/events on the asset named in the body (#73007) (#73139) The route dependency reads the asset id from the path, but this endpoint carries it in the request body, so the auth manager was only asked whether the caller may post to any asset at all. An auth manager that scopes assets by id, name, or uri could not deny an event for an asset the caller may not touch, and the response still returned that asset's name and uri. Co-authored-by: Henry Chen <henrychen@apache.org> * Bump the 3-3-fab-ui-package-updates group across 1 directory with 3 updates (#73208) Bumps the 3-3-fab-ui-package-updates group with 3 updates in the /providers/fab/src/airflow/providers/fab/www directory: [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core), [@babel/eslint-parser](https://github.com/babel/babel/tree/HEAD/eslint/babel-eslint-parser) and [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env). Updates `@babel/core` from 8.0.1 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/packages/babel-core) Updates `@babel/eslint-parser` from 8.0.1 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/eslint/babel-eslint-parser) Updates `@babel/preset-env` from 8.0.2 to 8.0.5 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v8.0.5/packages/babel-preset-env) --- updated-dependencies: - dependency-name: "@babel/core" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates - dependency-name: "@babel/eslint-parser" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates - dependency-name: "@babel/preset-env" dependency-version: 8.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: 3-3-fab-ui-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Reject non-numeric --limit values in airflow dags list-jobs (#72891) (#73214) The --limit option had no argparse type, so a value such as "abc" or "-1" was passed straight into the SQLAlchemy query and surfaced as a raw ValueError traceback instead of a usage error. Validating it at parse time gives the standard argparse message and exit code 2, while keeping 0 and positive integers working exactly as before. (cherry picked from commit 022ff83) Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> * [v3-3-test] Fix DAG.cli() crashing on dags test --show-dagrun (#72810) (#73216) * Fix DAG.cli() crashing on dags test --show-dagrun A Dag file run as a script goes through DAG.cli(), whose parser drops the dag_id positional and passes the Dag object to the handler instead. dag_test never needed dag_id from the parsed arguments until it rendered the run: the task instance query read args.dag_id, so --show-dagrun, --save-dagrun and --imgcat-dagrun raised AttributeError after the Dag had already run, while the plain command and the regular airflow dags test path worked. Filtering on the resolved Dag's id is the same value on the regular path and the only one available from DAG.cli(). * Update airflow-core/tests/unit/cli/commands/test_dag_command.py * Update airflow-core/tests/unit/cli/commands/test_dag_command.py --------- (cherry picked from commit 63fc32f) Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> Co-authored-by: Henry Chen <henryhenry0512@gmail.com> * Split the api_fastapi common parameters module into a package (#73239) The parameters module had grown to ~1800 lines mixing generic query helpers with hundreds of domain-specific query-parameter aliases, making it hard to navigate and maintain. Grouping the machinery (base, search, filter, sort, range) and the per-domain aliases (dag, dag_run, task_instance, xcom, asset, misc) into focused submodules keeps each file readable. The package __init__ re-exports the names consumed elsewhere in the codebase so existing import paths keep working. Backport of #72795 to v3-3-test. Because v3-3-test's parameters.py has a smaller set of query-parameter definitions than main (some PRs were not backported), this was re-created by running the same mechanical split on v3-3-test's file rather than cherry-picked: every definition is byte-identical to the original, and __init__ re-exports only the names consumed outside the package. * [v3-3-test] Document that plugin names must be unique (#73197) (#73203) (cherry picked from commit 49674b7) Co-authored-by: Aaron Chen <nailo2c@gmail.com> * [v3-3-test] Decode deadline alert interval and callback without generic deserialization (#72651) (#73304) * Decode deadline alert interval and callback without generic deserialization decode_deadline_alert passed the Dag-author controlled interval and callback to airflow.sdk.serde.deserialize, which imports the class named in the payload and instantiates it with the encoded arguments. These decoders run in the scheduler and the API server whenever a serialized Dag is loaded, so any class under the airflow.* allow list could be constructed there. The security model says a Dag author reaches those processes only through registered plugins and providers, and the codebase enforces that at decode time for timetables, priority weight strategies and operator extra links. Deadline fields had no equivalent gate. Both fields are now rebuilt from their encoded form directly: * interval accepts a number, a timedelta payload, or a variable-interval payload carrying a key, each reconstructed from primitives. * callback accepts AsyncCallback or SyncCallback, selected from a fixed map rather than imported by name, with path as a string, queue/executor as optional strings, and unexpected fields refused. Neither reaches serde.deserialize, so the class a Dag author names in either field is never imported. Filtering in front of deserialize was tried first and was not sufficient. serde normalises the legacy {__type, __var} shape into __classname__ *inside* deserialize, so a payload inspected beforehand carries no class name to reject. Payloads are normalised before inspection here, and that case is tested. Known residual, deliberately not closed here: callback kwargs are still passed through generic deserialization, so a legitimate callback can carry an arbitrary allow-listed class under its kwargs. Deferring that decode to the process that runs the callback would close it, but the kwargs are consumed through two paths using two different encodings, and getting either wrong hands user code an encoded dict in place of its argument. The residual is not specific to deadlines -- it is the general property of deserializing Dag-author data, shared with every other serde call site. A test asserts the current behaviour so the gap stays visible and any change to it has to be deliberate. Tests assert the class is never constructed rather than that an error is raised. Against unpatched sources the callback case reports DID NOT RAISE and the interval case names the instance that had already been built. * Accept pre-3.2 callback paths and validate fields per callback class Review feedback on the deadline decoding gate. Callbacks moved out of airflow.sdk.definitions.deadline in 3.2, so alerts serialized by an earlier version name the old module. The allow list only held the current path, which would have made those rows undecodable on upgrade -- the same backward-compatibility case the interval allow list already covers. The permitted callback fields were a hardcoded set covering both subclasses at once, so a payload could carry queue on a SyncCallback or executor on an AsyncCallback. The set is per class, and each class already declares its own via serialized_fields(), so ask it rather than restating the answer here and letting the two drift. That also turns a TypeError raised from inside the rebuild into the intended refusal, and the check now runs before anything is reconstructed from the payload. (cherry picked from commit c614c57) Generated-by: Claude Opus 5 Claude-Session: https://claude.ai/code/session_012zrnHJHPchB83FtwrYRf5q Co-authored-by: Jarek Potiuk <jarek@potiuk.com> * Bump swagger-ui-dist (#73332) Bumps the 3-3-registry-package-updates group with 1 update in the /registry directory: [swagger-ui-dist](https://github.com/swagger-api/swagger-ui). Updates `swagger-ui-dist` from 5.32.14 to 5.32.15 - [Release notes](https://github.com/swagger-api/swagger-ui/releases) - [Commits](swagger-api/swagger-ui@v5.32.14...v5.32.15) --- updated-dependencies: - dependency-name: swagger-ui-dist dependency-version: 5.32.15 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: 3-3-registry-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Bump webpack (#73333) Bumps the 3-3-fab-ui-package-updates group with 1 update in the /providers/fab/src/airflow/providers/fab/www directory: [webpack](https://github.com/webpack/webpack). Updates `webpack` from 5.110.3 to 5.111.0 - [Release notes](https://github.com/webpack/webpack/releases) - [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md) - [Commits](webpack/webpack@v5.110.3...v5.111.0) --- updated-dependencies: - dependency-name: webpack dependency-version: 5.111.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: 3-3-fab-ui-package-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Skip provider dependency generation for help command in breeze cli (#71689) (#73330) (cherry picked from commit 60633c8) Co-authored-by: feberbo <felipeboralli@gmail.com> * Bump the github-actions-updates group with 5 updates (#73344) Bumps the github-actions-updates group with 5 updates: | Package | From | To | | --- | --- | --- | | [actions/setup-java](https://github.com/actions/setup-java) | `6.0.0` | `6.0.1` | | [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) | `10.0.1` | `10.1.0` | | [github/codeql-action/init](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | | [github/codeql-action/autobuild](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | | [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.37.9` | `4.38.0` | Updates `actions/setup-java` from 6.0.0 to 6.0.1 - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](actions/setup-java@dd06d9c...de7274f) Updates `astral-sh/setup-uv` from 10.0.1 to 10.1.0 - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](astral-sh/setup-uv@20cfd1b...bec219d) Updates `github/codeql-action/init` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) Updates `github/codeql-action/autobuild` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](github/codeql-action@cdf488f...b96794f) --- updated-dependencies: - dependency-name: actions/setup-java dependency-version: 6.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: github-actions-updates - dependency-name: astral-sh/setup-uv dependency-version: 10.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/init dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/autobuild dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates - dependency-name: github/codeql-action/analyze dependency-version: 4.38.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: github-actions-updates ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [v3-3-test] Make the constraints check follow the cooldown rules the constraints use (#73316) (#73385) After every provider release wave the `Deps *:constraints` jobs doubled for three or four days and then recovered on their own. The constraints are resolved under uv's `exclude-newer` cooldown with the per-package overrides in the root pyproject.toml, where Airflow's own distributions are exempt, so a fresh provider wave lands in the constraints the same day. The check had its own 4-day cooldown applied to every package, so for those days the pin was newer than "latest" and a plain equality check counted it as outdated. With `--explain-why` every such package then cost a full `uv sync` that tried to pin it to the *older* version and reported that the pin did not take effect. On 2026-09-15 that was 37 providers and about 12 extra minutes per job, with nothing to act on. The check now reads `[tool.uv.exclude-newer-package]` and applies the same rules: no cooldown for exempt distributions, a moved cutoff where one is configured. A pin that is still ahead of "latest" counts as up to date, so no explanation runs for it either. (cherry picked from commit 7da73c8) Generated-by: Claude Opus 5 Co-authored-by: Jarek Potiuk <jarek@potiuk.com> * Stop shipping broken agent-skill symlinks in the source release (#73107) (#73448) Excluding .agents from the source tarball (#68851) left .claude behind. Everything under .claude/skills is a relay symlink into .agents/skills, so export-ignore strips the targets while the links themselves still ship: unpacking the source release yields broken symlinks, and .claude/ arrives holding nothing but those dead links. Found while verifying 3.3.2rc1, whose tarball carries five of them. The released 3.3.1 carries the same ones, so this is long-standing rather than something a recent change introduced. .github needs no equivalent entry: its own skills relays are already covered by the existing .github export-ignore. (cherry picked from commit 4b0eb8e) * [v3-3-test] Skip --explain-why for Python 3.10 in the deps summary job (#73449) Python 3.10 is losing support in more and more of our dependencies, so the constraints check has far more outdated packages to explain there, and each explanation costs a dependency resolution. That pushed the 3.10 job from ~18 to ~27 minutes on main. With 3.10 support being dropped in weeks, the explanations are not worth the CI time for that version. (cherry picked from commit b7a50ec) Co-authored-by: Jarek Potiuk <jarek@potiuk.com> Generated-by: Claude Opus 5 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Jarek Potiuk <jarek@potiuk.com> Co-authored-by: Vincent <97131062+vincbeck@users.noreply.github.com> Co-authored-by: Henry Chen <henrychen@apache.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Y-C <easoneason0905@gmail.com> Co-authored-by: Eason09053360 <185830721+Eason09053360@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: rjgoyln <151457491+rjgoyln@users.noreply.github.com> Co-authored-by: Henry Chen <henryhenry0512@gmail.com> Co-authored-by: Pierre Jeambrun <pierrejbrun@gmail.com> Co-authored-by: Aaron Chen <nailo2c@gmail.com> Co-authored-by: feberbo <felipeboralli@gmail.com>
Why
POST /assets/eventsis guarded byrequires_access_asset(method="POST"), but that dependency reads the asset id from the URL path. This endpoint carries the id in the request body, so the dependency runs before the body is parsed and passes an emptyAssetDetails(id=None)to the auth manager. The only question the auth manager can answer is whether the caller may post to any asset at all.An auth manager that scopes assets by id, name, or uri, the granularity added in #72682, therefore cannot deny an event for an asset the caller may not touch, and the response still returns that asset's name and uri. The built-in Simple and FAB auth managers ignore
details, so they are unaffected.POST /assets/{asset_id}/materializeis also unaffected because its id is in the path.What
airflow-core/src/airflow/api_fastapi/core_api/routes/public/assets.py: aftercreate_asset_eventresolves theAssetModelfrom the body, it callsis_authorized_assetwith the fullAssetDetails(id, name, uri)and raises 403 when denied. This mirrors the explicit second authorizationmaterialize_assetperforms on the Dag it resolves. The dependency-level check stays in place.Was generative AI tooling used to co-author this PR?