diff --git a/src/StaticPHP/Artifact/Downloader/Type/GitHubTokenSetupTrait.php b/src/StaticPHP/Artifact/Downloader/Type/GitHubTokenSetupTrait.php index 90c42507..34e350d4 100644 --- a/src/StaticPHP/Artifact/Downloader/Type/GitHubTokenSetupTrait.php +++ b/src/StaticPHP/Artifact/Downloader/Type/GitHubTokenSetupTrait.php @@ -16,10 +16,12 @@ trait GitHubTokenSetupTrait // GITHUB_TOKEN support if (($token = getenv('GITHUB_TOKEN')) !== false && ($user = getenv('GITHUB_USER')) !== false) { logger()->debug("Using 'GITHUB_TOKEN' with user {$user} for authentication"); + spc_add_log_filter([$user, $token]); return ['Authorization: Basic ' . base64_encode("{$user}:{$token}")]; } if (($token = getenv('GITHUB_TOKEN')) !== false) { logger()->debug("Using 'GITHUB_TOKEN' for authentication"); + spc_add_log_filter($token); return ["Authorization: Bearer {$token}"]; } return []; diff --git a/src/StaticPHP/Exception/ExceptionHandler.php b/src/StaticPHP/Exception/ExceptionHandler.php index 9dddc910..053d82a3 100644 --- a/src/StaticPHP/Exception/ExceptionHandler.php +++ b/src/StaticPHP/Exception/ExceptionHandler.php @@ -115,7 +115,7 @@ class ExceptionHandler $msg = explode("\n", (string) $message); foreach ($msg as $v) { $line = str_pad($v, strlen($v) + $indent_space, ' ', STR_PAD_LEFT); - fwrite($spc_log, strip_ansi_colors($line) . PHP_EOL); + spc_write_log($spc_log, strip_ansi_colors($line) . PHP_EOL); if ($output_log) { InteractiveTerm::plain(ConsoleColor::$color($line) . '', 'error'); } diff --git a/src/StaticPHP/Runtime/Shell/Shell.php b/src/StaticPHP/Runtime/Shell/Shell.php index 2d0d90b8..f9f4f175 100644 --- a/src/StaticPHP/Runtime/Shell/Shell.php +++ b/src/StaticPHP/Runtime/Shell/Shell.php @@ -114,22 +114,22 @@ abstract class Shell if (!$this->enable_log_file) { return; } - // write executed command to log file using fwrite + // write executed command to log file using spc_write_log $log_file = fopen(SPC_SHELL_LOG, 'a'); - fwrite($log_file, "\n>>>>>>>>>>>>>>>>>>>>>>>>>> [" . date('Y-m-d H:i:s') . "]\n"); - fwrite($log_file, "> Executing command: {$cmd}\n"); + spc_write_log($log_file, "\n>>>>>>>>>>>>>>>>>>>>>>>>>> [" . date('Y-m-d H:i:s') . "]\n"); + spc_write_log($log_file, "> Executing command: {$cmd}\n"); // get the backtrace to find the file and line number $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2); if (isset($backtrace[1]['file'], $backtrace[1]['line'])) { $file = $backtrace[1]['file']; $line = $backtrace[1]['line']; - fwrite($log_file, "> Called from: {$file} at line {$line}\n"); + spc_write_log($log_file, "> Called from: {$file} at line {$line}\n"); } - fwrite($log_file, "> Environment variables: {$this->getEnvString()}\n"); + spc_write_log($log_file, "> Environment variables: {$this->getEnvString()}\n"); if ($this->cd !== null) { - fwrite($log_file, "> Working dir: {$this->cd}\n"); + spc_write_log($log_file, "> Working dir: {$this->cd}\n"); } - fwrite($log_file, "\n"); + spc_write_log($log_file, "\n"); } /** @@ -154,7 +154,7 @@ abstract class Shell ): array { $file_res = null; if ($this->enable_log_file) { - // write executed command to the log file using fwrite + // write executed command to the log file using spc_write_log $file_res = fopen(SPC_SHELL_LOG, 'a'); } if ($console_output) { @@ -194,10 +194,10 @@ abstract class Shell foreach ([$pipes[1], $pipes[2]] as $pipe) { while (($chunk = fread($pipe, 8192)) !== false && $chunk !== '') { if ($console_output) { - fwrite($console_res, $chunk); + spc_write_log($console_res, $chunk); } if ($file_res !== null) { - fwrite($file_res, $chunk); + spc_write_log($file_res, $chunk); } if ($capture_output) { $output_value .= $chunk; @@ -207,7 +207,7 @@ abstract class Shell // check exit code if ($throw_on_error && $status['exitcode'] !== 0) { if ($file_res !== null) { - fwrite($file_res, "Command exited with non-zero code: {$status['exitcode']}\n"); + spc_write_log($file_res, "Command exited with non-zero code: {$status['exitcode']}\n"); } throw new ExecutionException( cmd: $original_command ?? $cmd, @@ -238,10 +238,10 @@ abstract class Shell foreach ($read as $pipe) { while (($chunk = fread($pipe, 8192)) !== false && $chunk !== '') { if ($console_output) { - fwrite($console_res, $chunk); + spc_write_log($console_res, $chunk); } if ($file_res !== null) { - fwrite($file_res, $chunk); + spc_write_log($file_res, $chunk); } if ($capture_output) { $output_value .= $chunk; diff --git a/src/bootstrap.php b/src/bootstrap.php index 95384b71..7856c0b2 100644 --- a/src/bootstrap.php +++ b/src/bootstrap.php @@ -52,7 +52,7 @@ if (filter_var(getenv('SPC_ENABLE_LOG_FILE'), FILTER_VALIDATE_BOOLEAN)) { $log_file_fd = fopen(SPC_OUTPUT_LOG, 'a'); $ob_logger->addLogCallback(function ($level, $output) use ($log_file_fd) { if ($log_file_fd) { - fwrite($log_file_fd, strip_ansi_colors($output) . "\n"); + spc_write_log($log_file_fd, strip_ansi_colors($output) . "\n"); } return true; }); diff --git a/src/globals/functions.php b/src/globals/functions.php index 712cf621..ee279328 100644 --- a/src/globals/functions.php +++ b/src/globals/functions.php @@ -132,6 +132,32 @@ function patch_point(): string return ''; } +// Add log filter value(s) to prevent secret leak +function spc_add_log_filter(array|string $filter): void +{ + global $spc_log_filters; + if (!is_array($spc_log_filters)) { + $spc_log_filters = []; + } + if (is_string($filter)) { + if (!in_array($filter, $spc_log_filters, true)) { + $spc_log_filters[] = $filter; + } + } elseif (is_array($filter)) { + $spc_log_filters = array_values(array_unique(array_merge($spc_log_filters, $filter))); + } +} + +function spc_write_log(mixed $stream, string $data): false|int +{ + // get filter + global $spc_log_filters; + if (is_array($spc_log_filters)) { + $data = str_replace($spc_log_filters, '***', $data); + } + return fwrite($stream, $data); +} + function patch_point_interrupt(int $retcode, string $msg = ''): InterruptException { return new InterruptException(message: $msg, code: $retcode);