Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions airflow-core/newsfragments/62964.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent JWT tokens from appearing in task logs by excluding the token field from workload object representations.
4 changes: 2 additions & 2 deletions airflow-core/src/airflow/executors/workloads/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from abc import ABC
from typing import TYPE_CHECKING

from pydantic import BaseModel, ConfigDict
from pydantic import BaseModel, ConfigDict, Field

if TYPE_CHECKING:
from airflow.api_fastapi.auth.tokens import JWTGenerator
Expand Down Expand Up @@ -69,7 +69,7 @@ class BaseWorkloadSchema(BaseModel):

model_config = ConfigDict(populate_by_name=True)

token: str
token: str = Field(repr=False)
"""The identity token for this workload"""

@staticmethod
Expand Down
36 changes: 36 additions & 0 deletions airflow-core/tests/unit/executors/test_workloads.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,47 @@
# under the License.
from __future__ import annotations

from pathlib import PurePosixPath
from uuid import uuid4

from airflow.executors import workloads
from airflow.executors.workloads import TaskInstance, TaskInstanceDTO
from airflow.executors.workloads.base import BundleInfo
from airflow.executors.workloads.task import ExecuteTask


def test_task_instance_alias_keeps_backwards_compat():
assert TaskInstance is TaskInstanceDTO
assert workloads.TaskInstance is TaskInstanceDTO
assert workloads.TaskInstanceDTO is TaskInstanceDTO


def test_token_excluded_from_workload_repr():
"""Ensure JWT tokens do not leak into log output via repr()."""
fake_token = "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.secret_payload.signature"
ti = TaskInstanceDTO(
id=uuid4(),
dag_version_id=uuid4(),
task_id="test_task",
dag_id="test_dag",
run_id="test_run",
try_number=1,
map_index=-1,
pool_slots=1,
queue="default",
priority_weight=1,
)
workload = ExecuteTask(
ti=ti,
dag_rel_path=PurePosixPath("test_dag.py"),
token=fake_token,
bundle_info=BundleInfo(name="dags-folder", version=None),
log_path="test.log",
)

workload_repr = repr(workload)

# Token MUST NOT appear in repr (prevents leaking into logs)
assert fake_token not in workload_repr, f"JWT token leaked into repr! Found token in: {workload_repr}"
# But token should still be accessible as an attribute
assert workload.token == fake_token