diff --git a/CHANGELOG.md b/CHANGELOG.md index 157d8f34..7bfa136c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ Changes since the last non-beta release. _Please add entries here for your pull requests that have not yet been released._ +### Changed + +- Redact sensitive data (Authorization headers, tokens) from `--trace` output. [PR 261](https://github.com/shakacode/control-plane-flow/pull/261) by [Sergey Tarasov](https://github.com/dzirtusss). + ## [4.1.1] - 2025-03-14 diff --git a/lib/core/config.rb b/lib/core/config.rb index 54d963e6..9c076f42 100644 --- a/lib/core/config.rb +++ b/lib/core/config.rb @@ -25,7 +25,7 @@ def initialize(args, options, required_options) return unless trace_mode ControlplaneApiDirect.trace = trace_mode - Shell.warn("Trace mode is enabled, this will print sensitive information to the console.") + Shell.warn("Trace mode is enabled. Sensitive data is redacted, but please review output before sharing.") end def org diff --git a/lib/core/controlplane_api_direct.rb b/lib/core/controlplane_api_direct.rb index 6f27c19a..a672ffe6 100644 --- a/lib/core/controlplane_api_direct.rb +++ b/lib/core/controlplane_api_direct.rb @@ -1,5 +1,27 @@ # frozen_string_literal: true +class RedactedDebugOutput + SAFE_HEADERS = %w[Content-Type Content-Length Accept Host Date Cache-Control Connection].freeze + HEADER_REGEX = /^([A-Za-z\-]+): (.+)$/.freeze + + def <<(msg) + $stdout << redact(msg) + end + + private + + def redact(msg) + msg.lines.map { |line| redact_line(line) }.join + end + + def redact_line(line) + match = line.match(HEADER_REGEX) + return line.gsub(/[\w\-._]{50,}/, "[REDACTED]") unless match + + SAFE_HEADERS.any? { |h| h.casecmp(match[1]).zero? } ? line : "#{match[1]}: [REDACTED]\n" + end +end + class ControlplaneApiDirect API_METHODS = { get: Net::HTTP::Get, @@ -37,7 +59,7 @@ def call(url, method:, host: :api, body: nil) # rubocop:disable Metrics/MethodLe http = Net::HTTP.new(uri.hostname, uri.port) http.use_ssl = uri.scheme == "https" - http.set_debug_output($stdout) if trace + http.set_debug_output(RedactedDebugOutput.new) if trace response = http.start { |ht| ht.request(request) }