diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py
index f2ac1f7a9403a..fee330e1fd1d6 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/connections.py
@@ -17,12 +17,15 @@
from __future__ import annotations
+import json
from collections import abc
from typing import Annotated
-from pydantic import Field
+from pydantic import Field, field_validator
+from pydantic_core.core_schema import ValidationInfo
from airflow.api_fastapi.core_api.base import BaseModel, StrictBaseModel
+from airflow.sdk.execution_time.secrets_masker import redact
# Response Models
@@ -39,6 +42,26 @@ class ConnectionResponse(BaseModel):
password: str | None
extra: str | None
+ @field_validator("password", mode="after")
+ @classmethod
+ def redact_password(cls, v: str | None, field_info: ValidationInfo) -> str | None:
+ if v is None:
+ return None
+ return redact(v, field_info.field_name)
+
+ @field_validator("extra", mode="before")
+ @classmethod
+ def redact_extra(cls, v: str | None) -> str | None:
+ if v is None:
+ return None
+ try:
+ extra_dict = json.loads(v)
+ redacted_dict = redact(extra_dict)
+ return json.dumps(redacted_dict)
+ except json.JSONDecodeError:
+ # we can't redact fields in an unstructured `extra`
+ return v
+
class ConnectionCollectionResponse(BaseModel):
"""Connection Collection serializer for responses."""
diff --git a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
index 8452e738445e4..866d555c06857 100644
--- a/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx
@@ -56,7 +56,7 @@ const ConnectionForm = ({
const { conf: extra, setConf } = useParamStore();
const {
control,
- formState: { isDirty, isValid },
+ formState: { isValid },
handleSubmit,
reset,
watch,
@@ -92,14 +92,6 @@ const ConnectionForm = ({
mutateConnection(data);
};
- const hasChanges = () => {
- if (isDirty) {
- return true;
- }
-
- return JSON.stringify(JSON.parse(extra)) !== JSON.stringify(JSON.parse(initialConnection.extra));
- };
-
const validateAndPrettifyJson = (value: string) => {
try {
const parsedJson = JSON.parse(value) as JSON;
@@ -240,7 +232,7 @@ const ConnectionForm = ({