# typed: true # Copyright (c) 2015 Sqreen. All Rights Reserved. # Please refer to our terms for more information: https://www.sqreen.com/terms.html # TODO: Sqreen.config_get require 'json' require 'sqreen/log' module Sqreen # For redacting sensitive data and avoid having it sent to our servers class SensitiveDataRedactor DEFAULT_SENSITIVE_KEYS = Set.new(%w[password secret passwd authorization api_key apikey access_token]).freeze DEFAULT_REGEX = /\A(?:\d[ -]*?){13,16}\z/ MASK = ''.freeze def self.from_config keys = Sqreen.config_get(:strip_sensitive_keys) keys = keys.split(',') if keys && keys.is_a?(String) regex = Sqreen.config_get(:strip_sensitive_regex) if regex && regex.is_a?(String) begin regex = Regexp.compile(regex) rescue RegexpError Sqreen.log.warn("Invalid regular expression given in strip_sensitive_regex: #{regex}") regex = nil end else regex = nil end new(keys: keys, regex: regex) end def initialize(params = {}) @regex = params[:regex] || DEFAULT_REGEX @keys = (params[:keys] || DEFAULT_SENSITIVE_KEYS).map(&:downcase) end def redact(obj) result = obj redacted = [] case obj when String if obj =~ @regex result = MASK redacted << obj end when Array result = [] obj.each do |e| e, r = redact(e) result << e redacted += r end when Hash result = {} obj.each do |k, v| ck = k.is_a?(String) ? k.downcase : k if @keys.include?(ck) redacted += SensitiveDataRedactor.all_strings(v) v = MASK else v, r = redact(v) redacted += r end result[k] = v end end [result, redacted] end class << self def all_strings(v) accum = [] all_strings_impl(v, accum) accum end private def all_strings_impl(obj, accum) case obj when String accum << obj when Array obj.each { |el| all_strings_impl(el, accum) } when Hash obj.each do |k, v| all_strings_impl(k, accum) all_strings_impl(v, accum) end end end end end end