Class: RSpec::Signal::Redactor

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/signal/redactor.rb

Overview

Best-effort scrubbing of obvious credentials before a report leaves the machine.

This is a safety net, not a guarantee. It targets shapes that are unambiguous (token prefixes, auth headers, credential-ish assignments) and deliberately does not try to guess at arbitrary secret values, because false positives destroy the diagnostic value of a report.

Always review artifacts before sending them somewhere you do not control.

Constant Summary collapse

PLACEHOLDER =
"[REDACTED]"
SENSITIVE_KEY =

Keys whose values are considered sensitive.

/
  (?:api[_-]?key|secret[_-]?key|access[_-]?key|client[_-]?secret|private[_-]?key|
     secret|password|passwd|pwd|token|auth[_-]?token|access[_-]?token|refresh[_-]?token|
     session[_-]?id|csrf|cookie|authorization|credentials?)
/xi
DEFAULT_PATTERNS =
[
  # Authorization: Bearer xyz / Basic xyz
  /\b(Authorization\s*[:=]\s*["']?\s*(?:Bearer|Basic|Token)\s+)[^\s"',;)\]}]+/i,
  # key: "value" / key => 'value' / key=value / "key":"value"
  /(["']?#{SENSITIVE_KEY.source}["']?\s*(?:=>|[:=])\s*)(["'])(?:(?!\2).){3,}\2/xi,
  /(\b#{SENSITIVE_KEY.source}\s*=\s*)(?!["'])[^\s"',;&)\]}]{3,}/xi,
  # URL query parameters
  /([?&]#{SENSITIVE_KEY.source}=)[^&\s"'<>]+/xi,
  # URL userinfo: https://user:pass@host
  %r{(\b[a-z][a-z0-9+.-]*://[^/\s:@]+:)[^/\s@]+(@)}i,
  # Well-known token shapes
  /\bAKIA[0-9A-Z]{16}\b/,
  /\bASIA[0-9A-Z]{16}\b/,
  /\bgh[pousr]_[A-Za-z0-9]{20,}\b/,
  /\bgithub_pat_[A-Za-z0-9_]{20,}\b/,
  /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/,
  /\b(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{10,}\b/,
  /\bglpat-[A-Za-z0-9_-]{16,}\b/,
  /\bAIza[0-9A-Za-z_-]{30,}\b/,
  # JWTs
  /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]*/,
  # PEM blocks
  /-----BEGIN[A-Z ]*PRIVATE KEY-----.*?-----END[A-Z ]*PRIVATE KEY-----/m
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(enabled: true, patterns: DEFAULT_PATTERNS, extra_patterns: [], filter: nil) ⇒ Redactor

Returns a new instance of Redactor.



49
50
51
52
53
# File 'lib/rspec/signal/redactor.rb', line 49

def initialize(enabled: true, patterns: DEFAULT_PATTERNS, extra_patterns: [], filter: nil)
  @enabled = enabled
  @patterns = patterns + Array(extra_patterns)
  @filter = filter
end

Instance Method Details

#call(text) ⇒ String? Also known as: scrub

Parameters:

  • text (String, nil)

Returns:

  • (String, nil)


59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rspec/signal/redactor.rb', line 59

def call(text)
  return text if text.nil? || !@enabled

  result = text.dup
  @patterns.each do |pattern|
    result = result.gsub(pattern) do |match|
      replacement_for(pattern, match, Regexp.last_match)
    end
  end
  result = @filter.call(result) if @filter
  result
end

#enabled?Boolean

Returns:

  • (Boolean)


55
# File 'lib/rspec/signal/redactor.rb', line 55

def enabled? = @enabled