This is an automated email from the ASF dual-hosted git repository.
vatsrahul1001 pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-3-test by this push:
new d7baa28bcbd [v3-3-test] Document scope boundaries the security model
leaves implicit (#72172) (#72829)
d7baa28bcbd is described below
commit d7baa28bcbd3711f3d0c7074e49a5a28bb7711fa
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Sep 10 16:27:18 2026 +0530
[v3-3-test] Document scope boundaries the security model leaves implicit
(#72172) (#72829)
* Document scope boundaries the security model leaves implicit
The 'What is NOT considered a security vulnerability' section states it is
written for security researchers and AI agents to read before reporting. In
practice several recurring report shapes are not covered by it, and each one
costs a triage cycle to re-derive from first principles.
Add five entries for boundaries the project already applies but has not
written down:
- Client libraries act on values their calling application supplies; the
trust
decision about those values belongs to that application, as it does for
Dag
authors passing unsanitized input to operators.
- Features documented as experimental or alpha do not yet carry security
guarantees. Defects in them are worth fixing but are not handled through
the
security process, and should be reassessed when the feature graduates.
- Bounding request size is the terminating proxy's responsibility. This is
distinct from the authenticated-DoS entry and applies to unauthenticated
requests too, including endpoints that must be reachable without
credentials.
- A defect reachable only on an end-of-life release line has no release in
which to ship a fix, including where a provider still installs on that
line.
- Params schema validation is a correctness feature, not a security control.
Declaring no params opts out of validation rather than asserting
emptiness.
Sharpen the connection-configuration entry, which currently reads as 'this
role is privileged, so nothing counts'. The grant covers worker-context
execution and the values the role may write; it does not cover recovering
credential material the role cannot read, nor reaching a component it has no
execution rights over.
Clarify the Execution API token entry. It currently states a short nominal
lifetime and non-revocability as separate facts, which reads as though the
ten-minute figure bounds exposure. Read together they do not: refresh
re-issues
from the token's own claims, so the lifetime bounds only a holder who stops
using the token, and a leaked token remains usable indefinitely and cannot
be
withdrawn. Also record that reissue does not consult the database, so a
token
naming a finished or archived task instance still refreshes.
Record one limitation the model asserts but the code cannot satisfy: the
edge3
worker signs its own requests, so remote edge-worker hosts must hold the JWT
signing key. That contradicts the guidance that workers never hold it, and
voids the assurance that the secret is confined to the API server and
scheduler.
* Match the impersonation heading underline to its title
The underline was one character short of the title, which Sphinx reports as
a warning and the docs build promotes to an error, failing both the docs and
spellcheck jobs.
(cherry picked from commit 7e6eeb0383c709c7982627744d9ee0a80283b600)
Co-authored-by: Jarek Potiuk <[email protected]>
Co-authored-by: Rahul Vats <[email protected]>
---
airflow-core/docs/security/security_model.rst | 136 +++++++++++++++++++++++++-
airflow-core/docs/security/workload.rst | 18 ++++
2 files changed, 151 insertions(+), 3 deletions(-)
diff --git a/airflow-core/docs/security/security_model.rst
b/airflow-core/docs/security/security_model.rst
index e9882ba83d8..8e561051070 100644
--- a/airflow-core/docs/security/security_model.rst
+++ b/airflow-core/docs/security/security_model.rst
@@ -567,6 +567,19 @@ model — Airflow does not enforce these natively.
be available to components that need to generate tokens
(Scheduler/Executor, API Server) and
components that need to validate tokens (API Server). Workers should not
have access to the signing
key — they only need the tokens provided to them.
+
+ **Exception — remote edge workers.** The ``edge3`` provider's worker
signs its own API requests, so
+ every host running an edge worker must be provisioned with ``[api_auth]
jwt_secret``. There is no
+ asymmetric alternative on that path, and no arrangement in which the
worker is issued a token by
+ the API server instead: the worker has to authenticate to the Edge API
before it can be given
+ any workload, so it must already hold a credential at that point.
Provisioning the signing key on
+ the host is what satisfies that bootstrap. In symmetric mode this is the
same secret used to sign user
+ JWTs and Execution API task tokens, so a deployment running edge workers
cannot satisfy the
+ guidance above, and the assurance in *Token signing key might be a shared
secret* below — which is
+ conditioned on the secret being available only to the API server and
scheduler — does not hold for
+ it. Deployment Managers should treat edge-worker hosts as part of the
control-plane trust boundary,
+ or accept that compromise of any edge-worker host is equivalent to
compromise of the deployment's
+ token-signing capability.
* Connection credentials for external systems (via Secrets Managers) should
only be available to the API Server
(which serves them to workers via the Execution API), not to the
Scheduler, Dag File Processor,
or Triggerer processes directly. This however limits some of the features
of Airflow - such as Deadline
@@ -983,9 +996,23 @@ team's connection" are describing a known limitation of
the current isolation mo
Execution API tokens not being revocable
........................................
-Execution API tokens issued to workers are short-lived (default 10 minutes)
with automatic refresh
-and are intentionally not subject to revocation. This is a design choice
documented in
-:doc:`/security/jwt_token_authentication`, not a missing security control.
+Execution API tokens issued to workers have a short nominal lifetime (default
10 minutes) with
+automatic refresh, and are intentionally not subject to revocation. This is a
design choice documented
+in :doc:`/security/jwt_token_authentication`, not a missing security control.
+
+Deployment Managers should read the two properties together rather than
separately. Refresh re-issues
+a token from its own claims, so a holder who keeps presenting a token keeps
extending it: the nominal
+lifetime bounds only a holder who *stops* using it. Combined with the absence
of revocation, this means a token
+that leaks — through a log, a process listing, or a compromised worker —
remains usable for as long as
+its holder continues to present it, and cannot be withdrawn. The ten-minute
figure is not a bound on
+exposure after a leak.
+
+Refresh is also not tied to the task's lifecycle: the reissue path validates
the token's signature and
+expiry but does not consult the database, so a token naming a task instance
that has finished, or whose
+row has been archived, still refreshes. Reports of this specific behaviour are
treated as hardening
+opportunities rather than vulnerabilities, and contributions binding reissue
to task state are welcome
+through the normal process. Deployments requiring a hard bound on credential
lifetime should rely on
+network isolation of workers rather than on token expiry.
Connection configuration capabilities
......................................
@@ -998,6 +1025,18 @@ capabilities. The ``test connection`` feature is disabled
by default since Airfl
it is an explicit Deployment Manager decision that acknowledges these risks.
See
:ref:`connection-configuration-users` for details.
+The boundary of this grant is **worker-context execution and the connection
values the role may
+write**. A connection configuration user causing code to run on a worker, or
influencing a client
+library's behaviour through connection parameters, is exercising a documented
capability and is not a
+vulnerability — even where the mechanism looks like injection.
+
+What this grant does **not** include is obtaining credential material the role
is not entitled to
+read, or reaching a component the role has no execution rights over. The role
has write-only access to
+stored credentials, so a defect that lets a connection configuration user
*recover* a secret, or that
+causes code to execute in the Scheduler or API server rather than on a worker,
crosses the boundary and
+**is** a vulnerability. The distinguishing question is not the role, which is
privileged either way,
+but whether the defect yields something the role could not already obtain.
+
Denial of Service by authenticated users
........................................
@@ -1049,6 +1088,97 @@ code" or "database credentials accessible in
configuration") are expected behavi
include a proof-of-concept that demonstrates how the finding violates the
security model described
in this document, including identifying the specific user role involved and
the attack scenario.
+Client libraries and caller-supplied values
+...........................................
+
+The Apache Airflow Python Client, and other client libraries the project
publishes, are **libraries**.
+They act on values their calling application supplies and have no basis on
which to decide that one
+caller-supplied string is trusted and another is not.
+
+Reports that an embedding application can cause a client library to misbehave
by passing it untrusted
+or malformed input — an attacker-influenced path parameter, a configuration
value of the wrong type, a
+plaintext scheme chosen for a remote host, or configuration mutated after the
client was constructed —
+describe a decision the calling application made. The trust boundary sits in
that application, not in
+the library. This mirrors the position taken for Dag authors passing
unsanitized input to operators
+and hooks.
+
+A defect in a client library **is** in scope when it misbehaves on input the
calling application
+supplied correctly — for example if a value the library itself documents as
safe is mishandled, or if
+the library silently ignores a security-relevant setting the caller did set.
+
+Experimental and alpha features
+................................
+
+Features the project documents as experimental, alpha, or preview do not yet
carry security
+guarantees, and defects confined to them are not treated as production
security vulnerabilities.
+This includes, at the time of writing, multi-team mode and executors marked
alpha in their provider
+documentation.
+
+Such defects are still worth fixing and are welcome as public contributions;
they are simply not
+handled through the security process, and no advisory is issued. When a
feature graduates out of
+experimental status, previously deferred issues affecting it should be
reassessed on their merits at
+that point.
+
+Request size limits and other reverse-proxy responsibilities
+.............................................................
+
+Airflow's API server is an ASGI application. Like any such application, it
reads a request body into
+memory before dispatching to a handler, and it does not impose a limit on
request size. Bounding
+request size, connection rates, and total concurrent connections is the
responsibility of the
+terminating reverse proxy or ingress — ``client_max_body_size`` in nginx,
``max_request_bytes`` in
+Envoy, or the equivalent in the deployment's chosen load balancer.
+
+Reports that an unauthenticated client can cause the API server to allocate
memory by sending a large
+request body, including to endpoints that must be reachable without
credentials such as the login
+route, describe this property. They are not treated as vulnerabilities in
Airflow. Note that this
+holds regardless of whether the request is authenticated: it is a distinct
point from the
+*Denial of Service by authenticated users* carve-out above, and applies to
unauthenticated requests
+as well.
+
+Deployment Managers should ensure a request-size limit is configured at the
proxy layer. Airflow is
+not intended to be exposed directly to untrusted networks.
+
+Issues only reachable on end-of-life Airflow versions
+......................................................
+
+Security advisories are issued for release lines that still receive releases.
A defect reachable only
+on a line that has reached end of life is not handled through the security
process, because there is
+no release in which to ship a fix.
+
+This holds even when a provider package that still installs on that line
contains the affected code:
+a provider continuing to support an end-of-life core does not extend security
support to that core.
+Users on an end-of-life line should upgrade.
+
+Params and schema validation
+.............................
+
+Airflow's params schema validation is a correctness and usability feature. It
is not a security
+control, and it is not relied upon to enforce any trust boundary.
+
+In particular, an operator that declares no params has opted out of validation
for that field; it has
+not asserted that the field will be empty. Reports that unchecked data can be
supplied where no
+schema was declared describe the absence of a control that was never claimed.
+
+Impersonation and Dag file parsing
+..................................
+
+``run_as_user`` confines task **execution** to a different Unix user. It does
not confine Dag file
+**import**.
+
+The effective ``run_as_user`` value is itself Dag-author-controlled — it can
be set on the Dag or on
+the task, overriding the deployment default. Airflow therefore cannot know
which user to impersonate
+until it has parsed the Dag file, and parsing a Dag file executes its
module-level code. That code
+runs as the worker's own Unix user, before any impersonation takes place.
+
+This ordering follows from where the setting lives, not from an oversight, and
it cannot be reversed
+without moving the setting somewhere the worker can read before parsing.
Reports that module-level
+Dag code executes as the worker user prior to impersonation describe expected
behaviour.
+
+Deployment Managers using ``run_as_user`` to confine Dag authors should read
it as constraining what
+a task does once it runs, not as a sandbox around the Dag file. A deployment
that also needs
+module-level Dag code confined must isolate the worker itself rather than rely
on impersonation
+within it. See :ref:`workload-isolation` and the impersonation section of
:doc:`/security/workload`.
+
Supported deployment platforms
..............................
diff --git a/airflow-core/docs/security/workload.rst
b/airflow-core/docs/security/workload.rst
index 8fee15db2bd..4b76169924c 100644
--- a/airflow-core/docs/security/workload.rst
+++ b/airflow-core/docs/security/workload.rst
@@ -51,6 +51,24 @@ not set.
[core]
default_impersonation = airflow
+What impersonation does not cover
+'''''''''''''''''''''''''''''''''
+
+Impersonation applies to task **execution**. It does not apply to Dag file
**parsing**.
+
+``run_as_user`` can be set on the Dag or on the task, so it overrides
``default_impersonation``.
+Airflow cannot know which user to switch to until it has parsed the Dag file,
and parsing a Dag file
+executes its module-level code. That code therefore runs as the worker's own
unix user, before any
+``sudo -u`` takes place; the file is parsed a second time after the switch, as
the impersonated user.
+
+So ``run_as_user`` and ``default_impersonation`` constrain what a task does
once it runs. Neither
+isolates the Dag file itself, and neither can be made to without moving the
setting somewhere the
+worker can read before parsing. If module-level Dag code also has to be
confined, isolate the worker
+— for example by running untrusted Dag authors' workloads on separate workers
— rather than relying
+on impersonation within a shared one.
+
+See :doc:`/security/security_model` for how this fits the overall trust
boundaries.
+
.. _workload-isolation:
Workload Isolation and Current Limitations