Skip to content

[v3-4-test] Mask CLI secrets in the audit log by parsed argument, not argv position (#72650) - #75144

Merged
potiuk merged 1 commit into
v3-4-testfrom
backport-4bbe5f5-v3-4-test
Oct 19, 2026
Merged

potiuk merged 1 commit into
v3-4-testfrom
backport-4bbe5f5-v3-4-test

Conversation

@github-actions

Copy link
Copy Markdown
Contributor
  • Mask CLI secrets in the audit log by parsed argument, not argv position

_build_metrics recorded sys.argv into the audit log and masked the variables
value by position, assuming the key and value were the final two arguments. Any
supported trailing option displaces them: 'airflow variables set KEY VALUE
--description TEXT' ends in '--description TEXT', so the value was written to
Log.extra in clear. --description is the instance found, not the class -- the
same is true of --serialize-json and of any option added later.

Take the key and value from the parsed Namespace instead, and redact that value
wherever it appears in the recorded command. Position no longer matters.

--conn-extra was not masked at all. It is the field connection secrets live in,
and it accepts nested JSON. It is now redacted alongside --conn-json, and both
are walked recursively -- --conn-json previously masked only top-level keys, so
a secret one level down was recorded in clear. A value that cannot be parsed as
JSON is redacted whole, because these options carry connection material and a
value that cannot be inspected is not safe to record.

Both argparse spellings are handled. --conn-json, --conn-extra and --conn-uri
were matched as standalone tokens only, so the equally valid --conn-json=VALUE
form skipped redaction entirely and recorded the secret. --conn-uri had that gap
before this change as well.

Note for operators: this prevents new disclosures only. Existing Log.extra rows
and backups retain values already written and should be redacted or expired,
and any credentials exposed that way rotated.

The seven new cases fail against unpatched sources.

  • Mask long-form password options on every CLI subcommand in the audit log

--password and --conn-password name a password on every subcommand,
including those contributed by providers (keycloak-auth-manager ...
--password), but were only masked for users and connections. Mask the
long spellings everywhere; keep -p limited to users and connections, as
elsewhere it means --port or --exclude-providers.

Generated-by: Claude Opus 5

  • Mask CLI secrets by parsed value in every argument spelling

Mask secrets supplied through any supported argument spelling in the
recorded command line: abbreviated and attached options, repeated
options, JSON (incl. conf) and URI values, and celery flower auth.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

  • Mask secrets after grouped short flags and in task-params / env-vars

Mask a parsed secret wherever it appears in a recorded token, which covers grouped
short flags, and add tasks test -t/--task-params and --env-vars to the JSON options.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

  • Limit in-token masking to whole values and short-option clusters

Mask a parsed value only where it is a whole token or ends a single-dash short-option
cluster, for plain, JSON and URI options alike, so a short value is not masked wherever
its text happens to appear in the recorded command line.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

  • Mask clustered, repeated-empty and double-scheme URI secrets in CLI audit log

Generated-by: Claude Opus 5

  • Only treat a URI as double-scheme when the host carries a protocol

Generated-by: Claude Opus 5

  • Match Connection's double-scheme parsing when masking URIs

Generated-by: Claude Opus 5

  • Walk short-option clusters by option arity and fail closed on any unparsed credentials

Generated-by: Claude Opus 5

  • Mask the whole URI when credentials cannot be located reliably

Generated-by: Claude Opus 5

  • Detect percent-encoded credentials when masking URIs

Generated-by: Claude Opus 5

  • Match credentials across newlines when masking URIs

Generated-by: Claude Opus 5

  • Keep CLI commands running when audit-log masking fails

The command line is masked for the audit log before the command runs, so an unexpected error in the masking aborted every CLI command. A failure now records the command fully masked instead: the command still runs, and nothing a secret could be in reaches the log. The short-option table is also checked against the real parsers, so a command definition change cannot silently change what gets masked.
(cherry picked from commit 4bbe5f5)

Co-authored-by: Jarek Potiuk jarek@potiuk.com
Generated-by: Claude Opus 5

… argv position (#72650)

* Mask CLI secrets in the audit log by parsed argument, not argv position

_build_metrics recorded sys.argv into the audit log and masked the variables
value by position, assuming the key and value were the final two arguments. Any
supported trailing option displaces them: 'airflow variables set KEY VALUE
--description TEXT' ends in '--description TEXT', so the value was written to
Log.extra in clear. --description is the instance found, not the class -- the
same is true of --serialize-json and of any option added later.

Take the key and value from the parsed Namespace instead, and redact that value
wherever it appears in the recorded command. Position no longer matters.

--conn-extra was not masked at all. It is the field connection secrets live in,
and it accepts nested JSON. It is now redacted alongside --conn-json, and both
are walked recursively -- --conn-json previously masked only top-level keys, so
a secret one level down was recorded in clear. A value that cannot be parsed as
JSON is redacted whole, because these options carry connection material and a
value that cannot be inspected is not safe to record.

Both argparse spellings are handled. --conn-json, --conn-extra and --conn-uri
were matched as standalone tokens only, so the equally valid --conn-json=VALUE
form skipped redaction entirely and recorded the secret. --conn-uri had that gap
before this change as well.

Note for operators: this prevents new disclosures only. Existing Log.extra rows
and backups retain values already written and should be redacted or expired,
and any credentials exposed that way rotated.

The seven new cases fail against unpatched sources.

* Mask long-form password options on every CLI subcommand in the audit log

--password and --conn-password name a password on every subcommand,
including those contributed by providers (keycloak-auth-manager ...
--password), but were only masked for users and connections. Mask the
long spellings everywhere; keep -p limited to users and connections, as
elsewhere it means --port or --exclude-providers.

Generated-by: Claude Opus 5

* Mask CLI secrets by parsed value in every argument spelling

Mask secrets supplied through any supported argument spelling in the
recorded command line: abbreviated and attached options, repeated
options, JSON (incl. conf) and URI values, and celery flower auth.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Mask secrets after grouped short flags and in task-params / env-vars

Mask a parsed secret wherever it appears in a recorded token, which covers grouped
short flags, and add tasks test -t/--task-params and --env-vars to the JSON options.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Limit in-token masking to whole values and short-option clusters

Mask a parsed value only where it is a whole token or ends a single-dash short-option
cluster, for plain, JSON and URI options alike, so a short value is not masked wherever
its text happens to appear in the recorded command line.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Mask clustered, repeated-empty and double-scheme URI secrets in CLI audit log

Generated-by: Claude Opus 5

* Only treat a URI as double-scheme when the host carries a protocol

Generated-by: Claude Opus 5

* Match Connection's double-scheme parsing when masking URIs

Generated-by: Claude Opus 5

* Walk short-option clusters by option arity and fail closed on any unparsed credentials

Generated-by: Claude Opus 5

* Mask the whole URI when credentials cannot be located reliably

Generated-by: Claude Opus 5

* Detect percent-encoded credentials when masking URIs

Generated-by: Claude Opus 5

* Match credentials across newlines when masking URIs

Generated-by: Claude Opus 5

* Keep CLI commands running when audit-log masking fails

The command line is masked for the audit log before the command runs, so an unexpected error in the masking aborted every CLI command. A failure now records the command fully masked instead: the command still runs, and nothing a secret could be in reaches the log. The short-option table is also checked against the real parsers, so a command definition change cannot silently change what gets masked.
(cherry picked from commit 4bbe5f5)

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Generated-by: Claude Opus 5
@potiuk
potiuk marked this pull request as ready for review October 19, 2026 22:22
@potiuk
potiuk merged commit e9f4f4d into v3-4-test Oct 19, 2026
77 of 78 checks passed
@potiuk
potiuk deleted the backport-4bbe5f5-v3-4-test branch October 19, 2026 22:22
@github-actions github-actions Bot added this to the Airflow 3.4.1 milestone Oct 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor Author

Hi maintainer, this PR was merged without a milestone set.
We've automatically set the milestone to Airflow 3.4.1 based on: merged to version branch
If this milestone is not correct, please update it to the appropriate milestone.

This comment was generated by Milestone Tag Assistant.

vatsrahul1001 pushed a commit that referenced this pull request Oct 20, 2026
… argv position (#72650) (#75144)

* Mask CLI secrets in the audit log by parsed argument, not argv position

_build_metrics recorded sys.argv into the audit log and masked the variables
value by position, assuming the key and value were the final two arguments. Any
supported trailing option displaces them: 'airflow variables set KEY VALUE
--description TEXT' ends in '--description TEXT', so the value was written to
Log.extra in clear. --description is the instance found, not the class -- the
same is true of --serialize-json and of any option added later.

Take the key and value from the parsed Namespace instead, and redact that value
wherever it appears in the recorded command. Position no longer matters.

--conn-extra was not masked at all. It is the field connection secrets live in,
and it accepts nested JSON. It is now redacted alongside --conn-json, and both
are walked recursively -- --conn-json previously masked only top-level keys, so
a secret one level down was recorded in clear. A value that cannot be parsed as
JSON is redacted whole, because these options carry connection material and a
value that cannot be inspected is not safe to record.

Both argparse spellings are handled. --conn-json, --conn-extra and --conn-uri
were matched as standalone tokens only, so the equally valid --conn-json=VALUE
form skipped redaction entirely and recorded the secret. --conn-uri had that gap
before this change as well.

Note for operators: this prevents new disclosures only. Existing Log.extra rows
and backups retain values already written and should be redacted or expired,
and any credentials exposed that way rotated.

The seven new cases fail against unpatched sources.

* Mask long-form password options on every CLI subcommand in the audit log

--password and --conn-password name a password on every subcommand,
including those contributed by providers (keycloak-auth-manager ...
--password), but were only masked for users and connections. Mask the
long spellings everywhere; keep -p limited to users and connections, as
elsewhere it means --port or --exclude-providers.

Generated-by: Claude Opus 5

* Mask CLI secrets by parsed value in every argument spelling

Mask secrets supplied through any supported argument spelling in the
recorded command line: abbreviated and attached options, repeated
options, JSON (incl. conf) and URI values, and celery flower auth.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Mask secrets after grouped short flags and in task-params / env-vars

Mask a parsed secret wherever it appears in a recorded token, which covers grouped
short flags, and add tasks test -t/--task-params and --env-vars to the JSON options.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Limit in-token masking to whole values and short-option clusters

Mask a parsed value only where it is a whole token or ends a single-dash short-option
cluster, for plain, JSON and URI options alike, so a short value is not masked wherever
its text happens to appear in the recorded command line.

Generated-by: Claude Opus 5 following the guidelines at https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions

* Mask clustered, repeated-empty and double-scheme URI secrets in CLI audit log

Generated-by: Claude Opus 5

* Only treat a URI as double-scheme when the host carries a protocol

Generated-by: Claude Opus 5

* Match Connection's double-scheme parsing when masking URIs

Generated-by: Claude Opus 5

* Walk short-option clusters by option arity and fail closed on any unparsed credentials

Generated-by: Claude Opus 5

* Mask the whole URI when credentials cannot be located reliably

Generated-by: Claude Opus 5

* Detect percent-encoded credentials when masking URIs

Generated-by: Claude Opus 5

* Match credentials across newlines when masking URIs

Generated-by: Claude Opus 5

* Keep CLI commands running when audit-log masking fails

The command line is masked for the audit log before the command runs, so an unexpected error in the masking aborted every CLI command. A failure now records the command fully masked instead: the command still runs, and nothing a secret could be in reaches the log. The short-option table is also checked against the real parsers, so a command definition change cannot silently change what gets masked.
(cherry picked from commit 4bbe5f5)


Generated-by: Claude Opus 5

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant