diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 index 95f4c62f..3e9b0a3c 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 @@ -1,4 +1,4 @@ -# db-dump-cf v1.8 — Dump 1C configuration to CF file +# db-dump-cf v1.9 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -76,10 +76,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } # --- Resolve V8Path --- @@ -196,7 +197,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -241,7 +242,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py index 93cb2b75..1010cc7a 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-cf v1.8 — Dump 1C configuration to CF file +# db-dump-cf v1.9 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -105,14 +105,13 @@ def output_nonempty(path): return os.path.isfile(path) and os.path.getsize(path) > 0 -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -166,7 +165,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) exit_code = result.returncode out_missing = exit_code == 0 and not output_nonempty(args.OutputFile) @@ -216,7 +215,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 index 5a44e8d4..9a75d529 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 @@ -1,4 +1,4 @@ -# db-dump-dt v1.7 — Dump 1C information base to DT file +# db-dump-dt v1.8 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -60,10 +60,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } # --- Resolve V8Path --- @@ -176,7 +177,7 @@ try { $arguments += "$OutputFile" $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -214,7 +215,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py index d2bcce17..18b7531c 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-dt v1.7 — Dump 1C information base to DT file +# db-dump-dt v1.8 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -105,14 +105,13 @@ def output_nonempty(path): return os.path.isfile(path) and os.path.getsize(path) > 0 -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -159,7 +158,7 @@ def main(): ib_data = tempfile.mkdtemp(prefix="ibcmd_data_") atexit.register(shutil.rmtree, ib_data, ignore_errors=True) arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) exit_code = result.returncode out_missing = exit_code == 0 and not output_nonempty(args.OutputFile) @@ -203,7 +202,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 index cd469f01..50bbb4a1 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 @@ -1,4 +1,4 @@ -# db-dump-xml v1.10 — Dump 1C configuration to XML files +# db-dump-xml v1.11 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -99,10 +99,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } # --- Resolve V8Path --- @@ -237,7 +238,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -310,7 +311,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py index 076898c5..53e7789f 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-xml v1.10 — Dump 1C configuration to XML files +# db-dump-xml v1.11 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -105,14 +105,13 @@ def dir_nonempty(path): return os.path.isdir(path) and any(os.scandir(path)) -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -197,7 +196,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) exit_code = result.returncode out_missing = exit_code == 0 and not dir_nonempty(args.ConfigDir) @@ -270,7 +269,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 index 750cfab5..a5f9c8e9 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 @@ -1,4 +1,4 @@ -# db-load-cf v1.9 — Load 1C configuration from CF file +# db-load-cf v1.10 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -76,10 +76,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } function Get-ExitAnnotation { @@ -206,7 +207,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -247,7 +248,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.py b/.claude/skills/db-load-cf/scripts/db-load-cf.py index d4c04591..ae6a711c 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.py +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-cf v1.9 — Load 1C configuration from CF file +# db-load-cf v1.10 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -123,14 +123,13 @@ def describe_exit(code): return "" -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -184,7 +183,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) if result.returncode == 0: print(f"Configuration loaded successfully from: {args.InputFile}") @@ -228,7 +227,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 index 54895be1..2c1d820e 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 @@ -1,4 +1,4 @@ -# db-load-dt v1.8 — Load 1C information base from DT file +# db-load-dt v1.9 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -73,10 +73,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } function Get-ExitAnnotation { @@ -200,7 +201,7 @@ try { $arguments += "$InputFile" $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -236,7 +237,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.py b/.claude/skills/db-load-dt/scripts/db-load-dt.py index 53be60d0..cfe4631f 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.py +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-dt v1.8 — Load 1C information base from DT file +# db-load-dt v1.9 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -123,14 +123,13 @@ def describe_exit(code): return "" -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -181,7 +180,7 @@ def main(): ib_data = tempfile.mkdtemp(prefix="ibcmd_data_") atexit.register(shutil.rmtree, ib_data, ignore_errors=True) arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) if result.returncode == 0: print(f"Information base restored successfully from: {args.InputFile}") @@ -223,7 +222,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-load-git/scripts/db-load-git.ps1 b/.claude/skills/db-load-git/scripts/db-load-git.ps1 index 8e0da758..c80709fe 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.ps1 +++ b/.claude/skills/db-load-git/scripts/db-load-git.ps1 @@ -1,4 +1,4 @@ -# db-load-git v1.14 — Load Git changes into 1C database +# db-load-git v1.15 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -108,10 +108,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } function Get-ExitAnnotation { @@ -395,7 +396,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -411,7 +412,7 @@ try { if ($UserName) { $applyArgs += "--user=$UserName" } if ($Password) { $applyArgs += "--password=$Password" } $applyArgs += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $applyArgs)" + Write-Host "Running: ibcmd $(Protect-Secrets ($applyArgs -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $applyArgs $applyOut = $__ib.Output $exitCode = $__ib.ExitCode @@ -469,7 +470,7 @@ try { # --- Execute --- Write-Host "" Write-Host "Executing partial configuration load..." - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-load-git/scripts/db-load-git.py b/.claude/skills/db-load-git/scripts/db-load-git.py index ae96607a..6665a098 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.py +++ b/.claude/skills/db-load-git/scripts/db-load-git.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-git v1.14 — Load Git changes into 1C database +# db-load-git v1.15 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -145,14 +145,13 @@ def describe_exit(code): return "" -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -341,7 +340,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) if result.returncode != 0: print(f"Error loading changes (code: {result.returncode}){describe_exit(result.returncode)}", file=sys.stderr) @@ -361,7 +360,7 @@ def main(): if args.Password: apply_args.append(f"--password={args.Password}") apply_args.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(apply_args))}") + print(f"Running: ibcmd {_redact(' '.join(apply_args), args.Password, args.UserName)}") ar = run_ibcmd([v8path] + apply_args, bool(args.UserName)) exit_code = ar.returncode if exit_code == 0: @@ -416,7 +415,7 @@ def main(): # --- Execute --- print("") print("Executing partial configuration load...") - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 index e262df47..5e3953f8 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 @@ -1,4 +1,4 @@ -# db-load-xml v1.15 — Load 1C configuration from XML files +# db-load-xml v1.16 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -108,10 +108,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } function Get-ExitAnnotation { @@ -267,7 +268,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -284,7 +285,7 @@ try { if ($UserName) { $applyArgs += "--user=$UserName" } if ($Password) { $applyArgs += "--password=$Password" } $applyArgs += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $applyArgs)" + Write-Host "Running: ibcmd $(Protect-Secrets ($applyArgs -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $applyArgs $applyOut = $__ib.Output $exitCode = $__ib.ExitCode @@ -374,7 +375,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.py b/.claude/skills/db-load-xml/scripts/db-load-xml.py index b5f86f6d..01077fea 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.py +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-xml v1.15 — Load 1C configuration from XML files +# db-load-xml v1.16 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -123,14 +123,13 @@ def describe_exit(code): return "" -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -233,7 +232,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) if result.returncode != 0: print(f"Error loading configuration from files (code: {result.returncode}){describe_exit(result.returncode)}", file=sys.stderr) @@ -253,7 +252,7 @@ def main(): if args.Password: apply_args.append(f"--password={args.Password}") apply_args.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(apply_args))}") + print(f"Running: ibcmd {_redact(' '.join(apply_args), args.Password, args.UserName)}") ar = run_ibcmd([v8path] + apply_args, bool(args.UserName)) exit_code = ar.returncode if exit_code == 0: @@ -342,7 +341,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/db-run/scripts/db-run.ps1 b/.claude/skills/db-run/scripts/db-run.ps1 index 3806cbe9..4996ec32 100644 --- a/.claude/skills/db-run/scripts/db-run.ps1 +++ b/.claude/skills/db-run/scripts/db-run.ps1 @@ -1,4 +1,4 @@ -# db-run v1.3 — Launch 1C:Enterprise +# db-run v1.4 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -79,6 +79,13 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text +} + # --- Resolve V8Path --- function Find-ProjectV8Path { $dir = (Get-Location).Path @@ -166,10 +173,8 @@ if ($URL) { $argString += " /DisableStartupDialogs" # --- Execute (background) --- -# Mask credentials (/N, /P) before printing the command line — never leak secrets. -# Anchor to a token boundary (whitespace before the flag) so a "/N" or "/P" that merely -# appears inside a path (e.g. ...\Program Files\..., ...\NSHIROV\...) is not mangled. -$displayArg = $argString -replace '(?<=\s)(/[NP])("[^"]*"|\S+)', '$1***' +# Redact the password/user before printing the command line — never leak secrets. +$displayArg = Protect-Secrets $argString @($Password, $UserName) Write-Host "Running: 1cv8.exe $displayArg" $proc = Start-Process -FilePath $V8Path -ArgumentList $argString -PassThru diff --git a/.claude/skills/db-run/scripts/db-run.py b/.claude/skills/db-run/scripts/db-run.py index 7826a1cd..41c1ca2b 100644 --- a/.claude/skills/db-run/scripts/db-run.py +++ b/.claude/skills/db-run/scripts/db-run.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-run v1.3 — Launch 1C:Enterprise +# db-run v1.4 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -75,6 +75,15 @@ def resolve_v8path(v8path): return v8path +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text + + def main(): sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") @@ -133,9 +142,8 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute (background) --- - # Mask credentials (/N, /P) before printing the command line — never leak secrets. - display = [re.sub(r"^(/[NP]).+", r"\1***", a) for a in arguments] - print(f"Running: 1cv8.exe {' '.join(display)}") + # Redact the password/user before printing the command line — never leak secrets. + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") proc = subprocess.Popen([v8path] + arguments) # --- Bounded early-exit check --- diff --git a/.claude/skills/db-update/scripts/db-update.ps1 b/.claude/skills/db-update/scripts/db-update.ps1 index 823e6a4f..9ed9be05 100644 --- a/.claude/skills/db-update/scripts/db-update.ps1 +++ b/.claude/skills/db-update/scripts/db-update.ps1 @@ -1,4 +1,4 @@ -# db-update v1.9 — Update 1C database configuration +# db-update v1.10 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -89,10 +89,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } function Get-ExitAnnotation { @@ -214,7 +215,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -266,7 +267,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/db-update/scripts/db-update.py b/.claude/skills/db-update/scripts/db-update.py index 8f63c5ea..89a6a290 100644 --- a/.claude/skills/db-update/scripts/db-update.py +++ b/.claude/skills/db-update/scripts/db-update.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-update v1.9 — Update 1C database configuration +# db-update v1.10 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -123,14 +123,13 @@ def describe_exit(code): return "" -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -185,7 +184,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, bool(args.UserName)) if result.returncode == 0: print("Database configuration updated successfully") @@ -237,7 +236,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/epf-build/scripts/epf-build.ps1 b/.claude/skills/epf-build/scripts/epf-build.ps1 index e1603080..d30979c6 100644 --- a/.claude/skills/epf-build/scripts/epf-build.ps1 +++ b/.claude/skills/epf-build/scripts/epf-build.ps1 @@ -1,4 +1,4 @@ -# epf-build v1.8 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.9 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -70,10 +70,11 @@ param( $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } # --- Resolve V8Path --- @@ -201,7 +202,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -239,7 +240,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/epf-build/scripts/epf-build.py b/.claude/skills/epf-build/scripts/epf-build.py index 314afdad..e80f52f8 100644 --- a/.claude/skills/epf-build/scripts/epf-build.py +++ b/.claude/skills/epf-build/scripts/epf-build.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-build v1.8 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.9 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -105,14 +105,13 @@ def output_nonempty(path): return os.path.isfile(path) and os.path.getsize(path) > 0 -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -182,7 +181,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, warn_no_user=False) exit_code = result.returncode out_missing = exit_code == 0 and not output_nonempty(args.OutputFile) @@ -221,7 +220,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True, diff --git a/.claude/skills/epf-dump/scripts/epf-dump.ps1 b/.claude/skills/epf-dump/scripts/epf-dump.ps1 index 8ff025a5..b61a9041 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.ps1 +++ b/.claude/skills/epf-dump/scripts/epf-dump.ps1 @@ -1,4 +1,4 @@ -# epf-dump v1.7 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.8 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -162,10 +162,11 @@ function Test-DirNonEmpty { return (Test-Path $Path -PathType Container) -and ([bool](Get-ChildItem -LiteralPath $Path -Force -ErrorAction SilentlyContinue | Select-Object -First 1)) } -function Format-SafeArgs { - # Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display. - param([string[]]$A) - ($A | ForEach-Object { $_ -replace '^(/[NP]).+', '$1***' -replace '^(--(user|password)=).+', '$1***' }) -join ' ' +function Protect-Secrets { + # Redact literal secret values from a display string (String.Replace is literal, not regex). + param([string]$Text, [string[]]$Secrets) + foreach ($s in $Secrets) { if ($s) { $Text = $Text.Replace($s, '***') } } + return $Text } $engine = if ((Split-Path $V8Path -Leaf) -match '^ibcmd') { "ibcmd" } else { "1cv8" } @@ -202,7 +203,7 @@ try { if ($UserName) { $arguments += "--user=$UserName" } if ($Password) { $arguments += "--password=$Password" } $arguments += "--data=$tempDir" - Write-Host "Running: ibcmd $(Format-SafeArgs $arguments)" + Write-Host "Running: ibcmd $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $__ib = Invoke-IbcmdProcess $V8Path $arguments $output = $__ib.Output $exitCode = $__ib.ExitCode @@ -241,7 +242,7 @@ try { $arguments += "/DisableStartupDialogs" # --- Execute --- - Write-Host "Running: 1cv8.exe $(Format-SafeArgs $arguments)" + Write-Host "Running: 1cv8.exe $(Protect-Secrets ($arguments -join ' ') @($Password, $UserName))" $process = Start-Process -FilePath $V8Path -ArgumentList $arguments -NoNewWindow -Wait -PassThru $exitCode = $process.ExitCode diff --git a/.claude/skills/epf-dump/scripts/epf-dump.py b/.claude/skills/epf-dump/scripts/epf-dump.py index 10b2e41f..f2551b1b 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.py +++ b/.claude/skills/epf-dump/scripts/epf-dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-dump v1.7 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.8 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -105,14 +105,13 @@ def dir_nonempty(path): return os.path.isdir(path) and any(os.scandir(path)) -def _mask(args): - """Mask credential tokens (/N, /P for 1cv8; --user=, --password= for ibcmd) for display.""" - out = [] - for a in args: - a = re.sub(r"^(/[NP]).+", r"\1***", a) - a = re.sub(r"^(--(?:user|password)=).+", r"\1***", a) - out.append(a) - return out +def _redact(text, *secrets): + """Redact literal secret values (password, user) from a display string — + precise, never touches lookalike paths.""" + for s in secrets: + if s: + text = text.replace(s, "***") + return text def main(): @@ -179,7 +178,7 @@ def main(): if args.Password: arguments.append(f"--password={args.Password}") arguments.append(f"--data={ib_data}") - print(f"Running: ibcmd {' '.join(_mask(arguments))}") + print(f"Running: ibcmd {_redact(' '.join(arguments), args.Password, args.UserName)}") result = run_ibcmd([v8path] + arguments, warn_no_user=False) exit_code = result.returncode out_missing = exit_code == 0 and not dir_nonempty(args.OutputDir) @@ -219,7 +218,7 @@ def main(): arguments.append("/DisableStartupDialogs") # --- Execute --- - print(f"Running: 1cv8.exe {' '.join(_mask(arguments))}") + print(f"Running: 1cv8.exe {_redact(' '.join(arguments), args.Password, args.UserName)}") result = subprocess.run( [v8path] + arguments, capture_output=True,