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

Reply via email to