github-actions[bot] opened a new pull request, #73304:
URL: https://github.com/apache/airflow/pull/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 c614c57062a95aade62cd5df774ae3c33bd57003)
Co-authored-by: Jarek Potiuk <[email protected]>
Generated-by: Claude Opus 5
Claude-Session: https://claude.ai/code/session_012zrnHJHPchB83FtwrYRf5q
--
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]