Airflow Leaks: When Proxies Spill Secrets in the Logs
Jan 18, 2026·5 min read
Executive Summary (TL;DR)
Apache Airflow's built-in secrets masker missed the `proxy` and `proxies` keywords. If you configured a connection to route through an authenticated proxy (e.g., `http://user:pass@proxy:8080`), Airflow treated that URL as harmless metadata. Consequently, task logs—often visible to a wide range of users—would print the full URL, including the password, in plain text. Fix involves upgrading to 3.1.6+.
Apache Airflow versions prior to 3.1.6 failed to mask sensitive credentials embedded within proxy URLs in connection configurations, leading to clear-text password exposure in execution logs.
The Hook: The Logfile Confessional
In the world of DevOps and Data Engineering, logs are the holy grail. They are the first place you look when a pipeline creates a crater instead of a data lake. Apache Airflow, the industry standard for orchestration, is notoriously chatty. It logs everything from task starts to XCom pushes, often giving developers a warm fuzzy feeling that they can debug anything.
But there is a dark side to verbosity. When a system blindly logs configuration objects to help you debug, it relies heavily on heuristics to decide what not to print. Airflow uses a SecretsMasker—a digital censor bar that scans for words like password, secret, or api_key and replaces their values with ***.
CVE-2025-68675 is the story of what happens when that censor bar gets a little too relaxed. It turns out, developers often route traffic through proxies, and those proxies often need authentication. Airflow didn't consider the word "proxy" to be dangerous, effectively treating http://admin:SuperSecret@myproxy.local the same as http://google.com. The result? Your proxy credentials ending up in the task logs, readable by anyone with 'Viewer' access.
The Flaw: A Whitelist in a Blacklist World
The root cause here is a classic failure of enumeration. Airflow's security model for logging relies on a default list of sensitive keys. When a Connection object is dumped to a log (which happens frequently during debugging or connection testing), the mask_secret utility iterates through the fields.
If the field name matches a pattern in the sensitive list (e.g., password, auth, token), the value is scrubbed. This is a "blacklist" approach to sanitation—you have to know exactly what is bad to stop it. If you encounter a field name you haven't anticipated, it gets a free pass.
Prior to version 3.1.6, proxies and proxy were not on the list. This is particularly dangerous because the standard format for HTTP proxy configuration in Python requests (and many other libraries) involves embedding the credentials directly in the Authority part of the URI: scheme://user:password@host:port. By failing to flag the key proxy as sensitive, Airflow allowed the entire string—credentials and all—to bypass the filter and land in the plaintext logs.
The Code: The Missing Keywords
The fix was embarrassingly simple, which highlights just how fragile keyword-based masking can be. The remediation involved updating the default configuration of the secrets masker to include the missing terms.
Here is a conceptual look at what happened in the code. The DEFAULT_SENSITIVE_FIELDS set defines what gets redacted:
# BEFORE (Vulnerable)
DEFAULT_SENSITIVE_FIELDS = {
'password',
'secret',
'passwd',
'authorization',
'api_key',
'apikey',
'access_token',
}
# AFTER (Fixed in 3.1.6)
DEFAULT_SENSITIVE_FIELDS = {
'password',
'secret',
'passwd',
'authorization',
'api_key',
'apikey',
'access_token',
# The new additions that save the day:
'proxy',
'proxies',
}By simply adding these two strings, any dictionary key or object attribute named proxy or proxies now triggers the masker. The value http://user:pass@1.2.3.4 gets transformed into *** in the logs, preventing the leak.
The Exploit: Phishing in the Logs
Exploiting this doesn't require buffer overflows or heap spraying. It requires a valid account with minimal permissions (like Viewer role) and a bit of patience. The attack vector is strictly internal, relying on an authorized user or developer creating a connection that uses a proxy.
Step 1: The Setup An admin configures a new HTTP Connection in Airflow to talk to an external API. Because the enterprise network is strict, they must route through an authenticated squid proxy.
{
"conn_id": "secure_api",
"conn_type": "http",
"host": "api.vendor.com",
"extra": {
"proxies": {
"http": "http://svc_airflow:Hunter2!@10.0.0.5:3128",
"https": "http://svc_airflow:Hunter2!@10.0.0.5:3128"
}
}
}Step 2: The Trigger
A DAG runs using this connection. If the DAG has logging enabled for connection details (common in debug mode) or if an error occurs that dumps the connection context, the proxies dictionary is printed to stdout.
Step 3: The Harvest
The attacker logs into the Airflow UI, browses to the Grid View, clicks on the task instance, and hits "Logs". There, staring them in the face, is:
[INFO] Using connection parameters: ... 'proxies': {'http': 'http://svc_airflow:Hunter2!@10.0.0.5:3128'} ...
The attacker now has valid credentials for the internal proxy, which is often a gateway to the wider internal network.
The Impact: Why Should We Panic?
While this is a CVSS 7.5 (High), the real-world impact depends heavily on your network architecture. If your proxies utilize a generic, low-privilege account, this is annoying but manageable. However, if—like many organizations—you reuse service accounts, this could be catastrophic.
The credentials leaked here (svc_airflow in our example) might effectively be a master key for network egress. An attacker who has compromised a low-level user account on the Airflow web interface can upgrade their access to network-level pivoting. They can use these credentials to route malicious traffic through your corporate proxy, potentially bypassing firewall rules that trust the proxy IP, or access other internal services that assume traffic coming from the proxy is legitimate.
The Fix: Upgrade and Rotate
The primary mitigation is straightforward: Upgrade to Apache Airflow 3.1.6. This version patches the SecretsMasker to respect proxy fields.
If you cannot upgrade immediately, you have two options:
- Manual Masking: You can manually update your
airflow.cfgto addproxyandproxiesto thesensitive_var_conn_namesconfiguration. This forces the masker to pick them up without a code change. - Credential Rotation: Assume any proxy credentials currently configured in Airflow have been logged. Rotate the passwords for those service accounts. Even if you patch the software, the old logs (stored in S3, GCS, or local disk) still contain the plaintext passwords. Cleaning up historical logs is just as important as patching the code.
Official Patches
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Apache Airflow Apache | < 3.1.6 | 3.1.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-532 |
| CVSS v3.1 | 7.5 (High) |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None (to trigger), Low (to view logs) |
| EPSS Score | 0.00063 (Low) |
| Exploit Status | No Known Exploitation |
MITRE ATT&CK Mapping
Insertion of Sensitive Information into Log File
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.