Airflow masks connection passwords, sensitive variables and sensitive extra fields in task logs and the UI by matching the value. It does not mask secrets passed through XCom or environment variables. Masking is a safety net for accidents, not a way to make printing secrets acceptable.
How masking works
The Airflow documentation says masking matches the specific value appearing anywhere in your output. It applies to connection passwords, sensitive variables, and keys in a connection's extra data whose names contain sensitive keywords such as password, secret, token, api key and private key. You can extend the keyword list through an environment variable for sensitive names.
Because it matches values, a very short password can cause unrelated characters in logs to be replaced. Choose real, long secrets.
Where it stops
| Path | Masked? |
|---|---|
| Connection password read through Airflow | Yes |
| Sensitive variable read through Airflow | Yes |
| Value passed through XCom | No, per the docs, when printed downstream |
| Secret in an environment variable | No, per the docs |
| Secret printed before a custom mask is set | No, the docs say the mask must be set first |
The docs also describe a setting that disables masking, so check that nobody has switched it off.
Better habits
- Fetch secrets at run time from connections or variables rather than baking them into environment variables. The docs recommend this for Kubernetes pod tasks, or native Kubernetes secrets.
- Never put secrets in XCom. Pass a reference or a name, and look the secret up in the downstream task.
- Register custom masks early. The docs name a mask function you can call in a Dag file or an operator's execute method, before any output.
- Do not log connection objects or full configs.
- Check the setting that controls masking in each environment.
- Review log retention. Task logs can live in object storage for a long time. See log retention by data class.
A quick audit
Search recent task logs for the first few characters of one known test secret. Run it for a connection password, an environment variable secret and an XCom value. Whatever shows up in clear text is the gap you need to close.
Quick check
Is my secret safe if it is in an environment variable?
Not from log leaks. The docs say secrets passed as environment variables are not masked by Airflow.
Can I turn masking off?
There is a setting for it. Keep it on unless you have a strong reason.
Safeguard dependency scanning and policy gates cover the libraries your Dags import. A free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.