Skip to content

Reject reserved XCom serialization keys submitted as JSON string literals#69378

Merged
potiuk merged 1 commit into
apache:mainfrom
potiuk:guard-xcom-string-literal-reserved-keys
Jul 6, 2026
Merged

Reject reserved XCom serialization keys submitted as JSON string literals#69378
potiuk merged 1 commit into
apache:mainfrom
potiuk:guard-xcom-string-literal-reserved-keys

Conversation

@potiuk

@potiuk potiuk commented Jul 4, 2026

Copy link
Copy Markdown
Member

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts,
lists and tuples but not str, so a value submitted as a JSON string literal
— e.g. json.dumps({"__classname__": ...}) — was stored verbatim and
re-parsed into a dict on a ?deserialize=true read, slipping past the filter.

This extends _walk to json.loads a string value and inspect the decoded
dict/list the same way the read path does. Strings that are not JSON, or
that decode to non-container values, are unchanged and still accepted.

Tests

  • test_create_xcom_entry_blocks_forbidden_keys_in_json_string
  • test_patch_xcom_entry_blocks_forbidden_keys_in_json_string
  • test_create_xcom_entry_allows_benign_string_values (no false positives)
Was generative AI tooling used to co-author this PR?
  • Yes — Claude Opus 4.8 (1M context)

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

…rals

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts, lists
and tuples but not str, so a value submitted as a JSON string literal
(e.g. json.dumps({"__classname__": ...})) was stored verbatim and re-parsed
into a dict on a ?deserialize=true read, slipping past the filter.

Extend _walk to json.loads a string value and inspect the decoded dict/list
the same way the read path does. Strings that are not JSON, or that decode
to non-container values, are unchanged and still accepted.

Generated-by: Claude Opus 4.8 (1M context) following the guidelines at
https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions
@boring-cyborg boring-cyborg Bot added the area:API Airflow's REST/HTTP API label Jul 4, 2026
@potiuk potiuk added the backport-to-v3-3-test Backport to v3-3-test label Jul 4, 2026
@potiuk potiuk added this to the Airflow 3.3.1 milestone Jul 4, 2026
@potiuk potiuk merged commit aae7c8f into apache:main Jul 6, 2026
78 checks passed
@potiuk potiuk deleted the guard-xcom-string-literal-reserved-keys branch July 6, 2026 11:19
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Backport successfully created: v3-3-test

Note: As of Merging PRs targeted for Airflow 3.X
the committer who merges the PR is responsible for backporting the PRs that are bug fixes (generally speaking) to the maintenance branches.

In matter of doubt please ask in #release-management Slack channel.

Status Branch Result
v3-3-test PR Link

potiuk added a commit that referenced this pull request Jul 6, 2026
… string literals (#69378)

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts, lists
and tuples but not str, so a value submitted as a JSON string literal
(e.g. json.dumps({"__classname__": ...})) was stored verbatim and re-parsed
into a dict on a ?deserialize=true read, slipping past the filter.

Extend _walk to json.loads a string value and inspect the decoded dict/list
the same way the read path does. Strings that are not JSON, or that decode
to non-container values, are unchanged and still accepted.
(cherry picked from commit aae7c8f)

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
Generated-by: Claude Opus 4.8 (1M context) following the guidelines at
https: //github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions
potiuk added a commit that referenced this pull request Jul 6, 2026
… string literals (#69378) (#69462)

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts, lists
and tuples but not str, so a value submitted as a JSON string literal
(e.g. json.dumps({"__classname__": ...})) was stored verbatim and re-parsed
into a dict on a ?deserialize=true read, slipping past the filter.

Extend _walk to json.loads a string value and inspect the decoded dict/list
the same way the read path does. Strings that are not JSON, or that decode
to non-container values, are unchanged and still accepted.
(cherry picked from commit aae7c8f)


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

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
vatsrahul1001 pushed a commit that referenced this pull request Jul 7, 2026
… string literals (#69378) (#69462)

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts, lists
and tuples but not str, so a value submitted as a JSON string literal
(e.g. json.dumps({"__classname__": ...})) was stored verbatim and re-parsed
into a dict on a ?deserialize=true read, slipping past the filter.

Extend _walk to json.loads a string value and inspect the decoded dict/list
the same way the read path does. Strings that are not JSON, or that decode
to non-container values, are unchanged and still accepted.
(cherry picked from commit aae7c8f)


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

Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
vatsrahul1001 pushed a commit that referenced this pull request Jul 9, 2026
… string literals (#69378) (#69462)

The XCom create/update payload validator _check_forbidden_xcom_keys
recursively rejects reserved serialization keys (__classname__, __type,
__var, ...) in dict/list values. Its _walk helper descended dicts, lists
and tuples but not str, so a value submitted as a JSON string literal
(e.g. json.dumps({"__classname__": ...})) was stored verbatim and re-parsed
into a dict on a ?deserialize=true read, slipping past the filter.

Extend _walk to json.loads a string value and inspect the decoded dict/list
the same way the read path does. Strings that are not JSON, or that decode
to non-container values, are unchanged and still accepted.
(cherry picked from commit aae7c8f)


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

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

area:API Airflow's REST/HTTP API backport-to-v3-3-test Backport to v3-3-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants