Skip to content

Commit 7e93206

Browse files
committed
fix: properly handle multi-line secrets in secret masking
1 parent 5b10ee9 commit 7e93206

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

airbyte_cdk/cli/airbyte_cdk/_secrets.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -459,25 +459,50 @@ def _print_ci_secrets_masks(
459459
_print_ci_secrets_masks_for_config(config=config_dict)
460460

461461

462+
def _print_ci_secret_mask_for_value(value: Any) -> None:
463+
"""Print GitHub CI mask for a single secret value.
464+
465+
Dict and list values masked as their JSON stringified versions.
466+
"""
467+
if isinstance(value, dict):
468+
# For nested dicts, we also need to mask the json-stringified version
469+
for v in value.values():
470+
_print_ci_secret_mask_for_value(v)
471+
472+
return
473+
474+
if isinstance(value, list):
475+
# For lists, we also need to mask the json-stringified version
476+
for list_item in value:
477+
_print_ci_secret_mask_for_value(list_item)
478+
479+
return
480+
481+
# For other types besides dict and list, we convert to string and mask each line
482+
# separately to handle multi-line secrets (e.g. private keys)
483+
484+
secret_str_lines = str(value).splitlines()
485+
for line in secret_str_lines:
486+
print(f"::add-mask::{line!s}")
487+
488+
462489
def _print_ci_secrets_masks_for_config(
463490
config: dict[str, str] | list[Any] | Any,
464491
) -> None:
465492
"""Print GitHub CI mask for secrets config, navigating child nodes recursively."""
466493
if isinstance(config, list):
494+
# Check each item in the list to look for nested dicts that may contain secrets:
467495
for item in config:
468496
_print_ci_secrets_masks_for_config(item)
469497

470-
if isinstance(config, dict):
498+
elif isinstance(config, dict):
471499
for key, value in config.items():
472500
if _is_secret_property(key):
473501
logger.debug(f"Masking secret for config key: {key}")
474-
print(f"::add-mask::{value!s}")
475-
if isinstance(value, dict):
476-
# For nested dicts, we also need to mask the json-stringified version
477-
print(f"::add-mask::{json.dumps(value)!s}")
478-
479-
if isinstance(value, (dict, list)):
480-
_print_ci_secrets_masks_for_config(config=value)
502+
_print_ci_secret_mask_for_value(value)
503+
elif isinstance(value, (dict, list)):
504+
# Recursively check nested dicts and lists
505+
_print_ci_secrets_masks_for_config(value)
481506

482507

483508
def _is_secret_property(property_name: str) -> bool:

0 commit comments

Comments
 (0)