This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new c8e0ec564a7 Document Connection-extras allowlist rule for provider 
hooks/operators (#66032)
c8e0ec564a7 is described below

commit c8e0ec564a7a4633533a50bc0f77c7f35f534f58
Author: Jarek Potiuk <[email protected]>
AuthorDate: Thu Apr 30 20:07:10 2026 +0200

    Document Connection-extras allowlist rule for provider hooks/operators 
(#66032)
    
    * Document that providers must not forward Connection extras blindly
    
    Add a security section to providers/AGENTS.md explaining the trust
    boundary between Connection editors and DAG authors, and the
    allowlist rule for forwarding Connection.extra values to hooks,
    operators, and client libraries.
    
    * Update providers/AGENTS.md
    
    Co-authored-by: Shahar Epstein <[email protected]>
    
    ---------
    
    Co-authored-by: Shahar Epstein <[email protected]>
---
 providers/AGENTS.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/providers/AGENTS.md b/providers/AGENTS.md
index 254c8df7436..bf75c002d4e 100644
--- a/providers/AGENTS.md
+++ b/providers/AGENTS.md
@@ -31,3 +31,77 @@ change that warrants explanation), update the provider's 
`docs/changelog.rst` di
 PR, just below the `Changelog` header — exactly as the in-file `NOTE TO 
CONTRIBUTORS` block
 describes. Routine entries (features, bug fixes, misc) are collected 
automatically by the release
 manager from commit messages, so most PRs do not need to touch the changelog 
at all.
+
+## Security: Connection extras must not be forwarded blindly to hooks/operators
+
+**Never pass the whole `Connection.extra` dict (or `**conn.extra_dejson`) as
+keyword arguments to a hook, operator, client constructor, or any underlying
+library call.** Forward only the specific extra keys you have explicitly
+reviewed and know are safe to expose.
+
+### Why this matters — different security boundaries
+
+Airflow has two distinct user roles with different trust levels:
+
+- **Connection editors** — UI/API users with permission to create or edit
+  Connections. They control the host, login, password, and the `extra` JSON
+  blob.
+- **DAG authors** — users who write the Python code that constructs hooks
+  and operators. They control which arguments are passed at call sites.
+
+These are *not* the same population, and the security model treats them
+differently. A Connection editor is trusted to supply credentials for a target
+system; they are **not** trusted to alter how the worker process behaves, load
+arbitrary Python code, change file paths the worker reads, or pass options
+into client libraries that the DAG author did not opt into.
+
+### What goes wrong when extras are forwarded blindly
+
+Many client libraries accept constructor or method kwargs that are dangerous
+when attacker-controlled. Concrete examples seen in the wild:
+
+- A kwarg that names a Python callable, plugin path, or import string —
+  attacker sets it to a module they control → **remote code execution** on
+  the worker.
+- A kwarg that points at a local file (cert path, key file, log path,
+  config file) — attacker redirects it to read or overwrite worker-side
+  files.
+- A kwarg that sets a proxy, endpoint URL, or hostname — attacker
+  redirects traffic to an MITM endpoint and harvests credentials or
+  tokens for *other* systems.
+- A kwarg that toggles TLS verification, signing, or auth — attacker
+  silently downgrades security.
+- A kwarg that controls subprocess execution, shell invocation, or
+  template rendering — attacker reaches command/template injection.
+
+In all of these, the Connection editor effectively gains capabilities
+(RCE, file read/write, traffic redirection, auth bypass) that the security
+model does not grant them.
+
+### The rule
+
+- **Allowlist, never passthrough.** In the hook, read each extra key by
+  name (`conn.extra_dejson.get("region_name")`,
+  `conn.extra_dejson.get("verify")`, …) and pass only those named values
+  forward. Reject or ignore unknown keys.
+- **Do not** write `SomeClient(**conn.extra_dejson)`,
+  `hook = MyHook(**conn.extra_dejson)`, or
+  `kwargs.update(conn.extra_dejson)` followed by a downstream call.
+- When adding support for a new extra key, treat it like any other public
+  argument: review what the underlying library does with it, and document
+  it in the provider's connection docs.
+- If a DAG author genuinely needs to pass a non-allowlisted option, that
+  option should be a **Dag-author-supplied argument** on the operator or
+  hook (with its own review), not something a Connection editor can set.
+
+### When reviewing provider PRs
+
+Flag any of these patterns:
+
+- `**conn.extra_dejson` or `**self.extra_dejson` spread into a constructor
+  or call.
+- Looping over `conn.extra_dejson.items()` and forwarding every key.
+- New code paths where extras are merged into `kwargs` and then passed on
+  unfiltered.
+- "Convenience" features that let users put arbitrary client kwargs into
+  `extra` — they widen the Connection-editor blast radius.

Reply via email to