├── .bundle └── config ├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── build.yml │ ├── codeql-analysis.yml │ ├── lint.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .rubocop.yml ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── docs └── assets │ └── gem.png ├── lib ├── patterns │ └── default.rb ├── redacting_logger.rb └── version.rb ├── redacting-logger.gemspec ├── script ├── bootstrap ├── env ├── lint └── test ├── spec ├── fixtures │ └── fake.private_key ├── lib │ └── redacting_logger_spec.rb └── spec_helper.rb └── vendor └── cache ├── activesupport-7.1.5.1.gem ├── ast-2.4.3.gem ├── base64-0.2.0.gem ├── benchmark-0.4.0.gem ├── bigdecimal-3.1.9.gem ├── concurrent-ruby-1.3.5.gem ├── connection_pool-2.5.0.gem ├── date-3.4.1.gem ├── diff-lcs-1.6.2.gem ├── docile-1.4.0.gem ├── drb-2.2.1.gem ├── i18n-1.14.7.gem ├── io-console-0.8.0.gem ├── irb-1.15.2.gem ├── json-2.12.2.gem ├── language_server-protocol-3.17.0.5.gem ├── lint_roller-1.1.0.gem ├── logger-1.7.0.gem ├── minitest-5.25.5.gem ├── mutex_m-0.3.0.gem ├── parallel-1.27.0.gem ├── parser-3.3.8.0.gem ├── pp-0.6.2.gem ├── prettyprint-0.2.0.gem ├── prism-1.4.0.gem ├── psych-5.2.3.gem ├── racc-1.8.1.gem ├── rack-3.1.14.gem ├── rainbow-3.1.1.gem ├── rdoc-6.13.1.gem ├── regexp_parser-2.10.0.gem ├── reline-0.6.1.gem ├── rspec-3.13.1.gem ├── rspec-core-3.13.4.gem ├── rspec-expectations-3.13.5.gem ├── rspec-mocks-3.13.5.gem ├── rspec-support-3.13.4.gem ├── rubocop-1.75.7.gem ├── rubocop-ast-1.44.1.gem ├── rubocop-github-0.23.0.gem ├── rubocop-performance-1.25.0.gem ├── rubocop-rails-2.30.3.gem ├── rubocop-rspec-3.6.0.gem ├── ruby-progressbar-1.13.0.gem ├── securerandom-0.3.2.gem ├── simplecov-0.22.0.gem ├── simplecov-erb-1.0.1.gem ├── simplecov-html-0.12.3.gem ├── simplecov_json_formatter-0.1.4.gem ├── stringio-3.1.6.gem ├── tzinfo-2.0.6.gem ├── unicode-display_width-3.1.4.gem └── unicode-emoji-4.0.4.gem /.bundle/config: -------------------------------------------------------------------------------- 1 | --- 2 | BUNDLE_BIN: "bin" 3 | BUNDLE_PATH: "vendor/gems" 4 | BUNDLE_CACHE_PATH: "vendor/cache" 5 | BUNDLE_CACHE_ALL: "true" 6 | BUNDLE_SPECIFIC_PLATFORM: "true" 7 | BUNDLE_NO_INSTALL: "true" 8 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @GrantBirki 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: bundler 5 | vendor: true 6 | directory: "/" 7 | groups: 8 | ruby-dependencies: 9 | patterns: 10 | - "*" 11 | schedule: 12 | interval: weekly 13 | day: "tuesday" 14 | time: "21:00" 15 | - package-ecosystem: github-actions 16 | directory: "/" 17 | groups: 18 | github-actions: 19 | patterns: 20 | - "*" 21 | schedule: 22 | interval: weekly 23 | day: "tuesday" 24 | time: "21:00" 25 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | workflow_call: 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | build: 17 | name: build 18 | 19 | strategy: 20 | matrix: 21 | os: [ubuntu-latest, macos-latest] 22 | runs-on: ${{ matrix.os }} 23 | 24 | steps: 25 | - name: checkout 26 | uses: actions/checkout@v4 27 | 28 | - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # pin@v1.244.0 29 | with: 30 | bundler-cache: true 31 | 32 | - name: bootstrap 33 | run: script/bootstrap 34 | 35 | - name: build 36 | run: | 37 | GEM_NAME=$(ls | grep gemspec | cut -d. -f1) 38 | echo "Attempting to build gem $GEM_NAME..." 39 | gem build $GEM_NAME 40 | if [ $? -eq 0 ]; then 41 | echo "Gem built successfully!" 42 | else 43 | echo "Gem build failed!" 44 | exit 1 45 | fi 46 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | # pull_request: 7 | # # The branches below must be a subset of the branches above 8 | # branches: [ main ] 9 | schedule: 10 | - cron: '15 23 * * 5' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | language: [ 'ruby' ] 25 | 26 | steps: 27 | - name: checkout 28 | uses: actions/checkout@v4 29 | 30 | # Initializes the CodeQL tools for scanning. 31 | - name: Initialize CodeQL 32 | uses: github/codeql-action/init@v3 33 | with: 34 | languages: ${{ matrix.language }} 35 | 36 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 37 | # If this step fails, then you should remove it and run the build manually (see below) 38 | - name: Autobuild 39 | uses: github/codeql-action/autobuild@v3 40 | #- run: | 41 | # make bootstrap 42 | # make release 43 | 44 | - name: Perform CodeQL Analysis 45 | uses: github/codeql-action/analyze@v3 46 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: lint 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | lint: 14 | name: lint 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: checkout 19 | uses: actions/checkout@v4 20 | 21 | - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # pin@v1.244.0 22 | with: 23 | bundler-cache: true 24 | 25 | - name: bootstrap 26 | run: script/bootstrap 27 | 28 | - name: lint 29 | run: script/lint 30 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - lib/version.rb 10 | 11 | permissions: 12 | contents: write 13 | packages: write 14 | 15 | jobs: 16 | release: 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: checkout 21 | uses: actions/checkout@v4 22 | with: 23 | persist-credentials: false 24 | 25 | - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # pin@v1.244.0 26 | with: 27 | bundler-cache: false 28 | 29 | - name: bootstrap 30 | run: script/bootstrap 31 | 32 | - name: lint 33 | run: script/lint 34 | 35 | - name: test 36 | run: script/test 37 | 38 | - name: set GEM_NAME from gemspec 39 | run: echo "GEM_NAME=$(ls | grep gemspec | cut -d. -f1)" >> $GITHUB_ENV 40 | 41 | # builds the gem and saves the version to GITHUB_ENV 42 | - name: build 43 | run: echo "GEM_VERSION=$(gem build ${{ env.GEM_NAME }}.gemspec 2>&1 | grep Version | cut -d':' -f 2 | tr -d " \t\n\r")" >> $GITHUB_ENV 44 | 45 | - name: publish to GitHub packages 46 | run: | 47 | export OWNER=$( echo ${{ github.repository }} | cut -d "/" -f 1 ) 48 | GEM_HOST_API_KEY=${{ secrets.GITHUB_TOKEN }} gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} ${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem 49 | 50 | - name: release 51 | uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # pin@v1.16.0 52 | with: 53 | artifacts: "${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem" 54 | tag: "v${{ env.GEM_VERSION }}" 55 | generateReleaseNotes: true 56 | 57 | - name: publish to RubyGems 58 | run: | 59 | mkdir -p ~/.gem 60 | echo -e "---\n:rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}" > ~/.gem/credentials 61 | chmod 0600 ~/.gem/credentials 62 | gem push ${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem 63 | rm ~/.gem/credentials 64 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | permissions: 10 | contents: read 11 | 12 | jobs: 13 | test: 14 | name: test 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | ruby: [ '3.1.2', '3.1.4', '3.2.2', '3.2.3', '3.3.0', '3.3.1', '3.4.0', '3.4.2' ] 19 | 20 | steps: 21 | - name: checkout 22 | uses: actions/checkout@v4 23 | 24 | - uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # pin@v1.244.0 25 | with: 26 | bundler-cache: true 27 | ruby-version: ${{ matrix.ruby }} 28 | 29 | - name: bootstrap 30 | run: script/bootstrap 31 | 32 | - name: test 33 | run: script/test 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | coverage 3 | logs 4 | tmp 5 | vendor/gems 6 | .idea 7 | .byebug_history 8 | .local/ 9 | .DS_Store 10 | .lesshst 11 | *.pem 12 | *.key 13 | *.crt 14 | *.csr 15 | *.secret 16 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_gem: 2 | rubocop-github: 3 | - config/default.yml 4 | 5 | AllCops: 6 | NewCops: enable 7 | SuggestExtensions: false 8 | DisplayCopNames: true 9 | TargetRubyVersion: 3.2 10 | Exclude: 11 | - 'bin/*' 12 | - 'spec/acceptance/fixtures/**/*' 13 | - 'spec/unit/fixtures/**/*' 14 | - 'vendor/**/*' 15 | - '.github/**/*' 16 | 17 | Style/HashSyntax: 18 | Enabled: false 19 | 20 | Metrics/CyclomaticComplexity: 21 | Max: 15 22 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.2 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | gem "logger", "~> 1.7" 6 | 7 | group :development do 8 | gem "irb", "~> 1.15" 9 | gem "rspec", "~> 3.13" 10 | gem "rubocop", "~> 1.75" 11 | gem "rubocop-github", "~> 0.23" 12 | gem "rubocop-performance", "~> 1.25" 13 | gem "rubocop-rspec", "~> 3.6" 14 | gem "simplecov", "~> 0.22" 15 | gem "simplecov-erb", "~> 1.0" 16 | end 17 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (7.1.5.1) 5 | base64 6 | benchmark (>= 0.3) 7 | bigdecimal 8 | concurrent-ruby (~> 1.0, >= 1.0.2) 9 | connection_pool (>= 2.2.5) 10 | drb 11 | i18n (>= 1.6, < 2) 12 | logger (>= 1.4.2) 13 | minitest (>= 5.1) 14 | mutex_m 15 | securerandom (>= 0.3) 16 | tzinfo (~> 2.0) 17 | ast (2.4.3) 18 | base64 (0.2.0) 19 | benchmark (0.4.0) 20 | bigdecimal (3.1.9) 21 | concurrent-ruby (1.3.5) 22 | connection_pool (2.5.0) 23 | date (3.4.1) 24 | diff-lcs (1.6.2) 25 | docile (1.4.0) 26 | drb (2.2.1) 27 | i18n (1.14.7) 28 | concurrent-ruby (~> 1.0) 29 | io-console (0.8.0) 30 | irb (1.15.2) 31 | pp (>= 0.6.0) 32 | rdoc (>= 4.0.0) 33 | reline (>= 0.4.2) 34 | json (2.12.2) 35 | language_server-protocol (3.17.0.5) 36 | lint_roller (1.1.0) 37 | logger (1.7.0) 38 | minitest (5.25.5) 39 | mutex_m (0.3.0) 40 | parallel (1.27.0) 41 | parser (3.3.8.0) 42 | ast (~> 2.4.1) 43 | racc 44 | pp (0.6.2) 45 | prettyprint 46 | prettyprint (0.2.0) 47 | prism (1.4.0) 48 | psych (5.2.3) 49 | date 50 | stringio 51 | racc (1.8.1) 52 | rack (3.1.14) 53 | rainbow (3.1.1) 54 | rdoc (6.13.1) 55 | psych (>= 4.0.0) 56 | regexp_parser (2.10.0) 57 | reline (0.6.1) 58 | io-console (~> 0.5) 59 | rspec (3.13.1) 60 | rspec-core (~> 3.13.0) 61 | rspec-expectations (~> 3.13.0) 62 | rspec-mocks (~> 3.13.0) 63 | rspec-core (3.13.4) 64 | rspec-support (~> 3.13.0) 65 | rspec-expectations (3.13.5) 66 | diff-lcs (>= 1.2.0, < 2.0) 67 | rspec-support (~> 3.13.0) 68 | rspec-mocks (3.13.5) 69 | diff-lcs (>= 1.2.0, < 2.0) 70 | rspec-support (~> 3.13.0) 71 | rspec-support (3.13.4) 72 | rubocop (1.75.7) 73 | json (~> 2.3) 74 | language_server-protocol (~> 3.17.0.2) 75 | lint_roller (~> 1.1.0) 76 | parallel (~> 1.10) 77 | parser (>= 3.3.0.2) 78 | rainbow (>= 2.2.2, < 4.0) 79 | regexp_parser (>= 2.9.3, < 3.0) 80 | rubocop-ast (>= 1.44.0, < 2.0) 81 | ruby-progressbar (~> 1.7) 82 | unicode-display_width (>= 2.4.0, < 4.0) 83 | rubocop-ast (1.44.1) 84 | parser (>= 3.3.7.2) 85 | prism (~> 1.4) 86 | rubocop-github (0.23.0) 87 | rubocop (>= 1.72) 88 | rubocop-performance (>= 1.24) 89 | rubocop-rails (>= 2.23) 90 | rubocop-performance (1.25.0) 91 | lint_roller (~> 1.1) 92 | rubocop (>= 1.75.0, < 2.0) 93 | rubocop-ast (>= 1.38.0, < 2.0) 94 | rubocop-rails (2.30.3) 95 | activesupport (>= 4.2.0) 96 | lint_roller (~> 1.1) 97 | rack (>= 1.1) 98 | rubocop (>= 1.72.1, < 2.0) 99 | rubocop-ast (>= 1.38.0, < 2.0) 100 | rubocop-rspec (3.6.0) 101 | lint_roller (~> 1.1) 102 | rubocop (~> 1.72, >= 1.72.1) 103 | ruby-progressbar (1.13.0) 104 | securerandom (0.3.2) 105 | simplecov (0.22.0) 106 | docile (~> 1.1) 107 | simplecov-html (~> 0.11) 108 | simplecov_json_formatter (~> 0.1) 109 | simplecov-erb (1.0.1) 110 | simplecov (< 1.0) 111 | simplecov-html (0.12.3) 112 | simplecov_json_formatter (0.1.4) 113 | stringio (3.1.6) 114 | tzinfo (2.0.6) 115 | concurrent-ruby (~> 1.0) 116 | unicode-display_width (3.1.4) 117 | unicode-emoji (~> 4.0, >= 4.0.4) 118 | unicode-emoji (4.0.4) 119 | 120 | PLATFORMS 121 | arm64-darwin-21 122 | darwin 123 | ruby 124 | x86_64-darwin-20 125 | x86_64-linux 126 | 127 | DEPENDENCIES 128 | irb (~> 1.15) 129 | logger (~> 1.7) 130 | rspec (~> 3.13) 131 | rubocop (~> 1.75) 132 | rubocop-github (~> 0.23) 133 | rubocop-performance (~> 1.25) 134 | rubocop-rspec (~> 3.6) 135 | simplecov (~> 0.22) 136 | simplecov-erb (~> 1.0) 137 | 138 | BUNDLED WITH 139 | 2.4.19 140 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Grant Birkinbine 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # redacting-logger 2 | 3 | [![test](https://github.com/github/redacting-logger/actions/workflows/test.yml/badge.svg)](https://github.com/github/redacting-logger/actions/workflows/test.yml) [![lint](https://github.com/github/redacting-logger/actions/workflows/lint.yml/badge.svg)](https://github.com/github/redacting-logger/actions/workflows/lint.yml) [![build](https://github.com/github/redacting-logger/actions/workflows/build.yml/badge.svg)](https://github.com/github/redacting-logger/actions/workflows/build.yml) [![CodeQL](https://github.com/github/redacting-logger/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/github/redacting-logger/actions/workflows/codeql-analysis.yml) [![release](https://github.com/github/redacting-logger/actions/workflows/release.yml/badge.svg)](https://github.com/github/redacting-logger/actions/workflows/release.yml) 4 | 5 | A redacting Ruby logger to prevent the leaking of secrets via logs 6 | 7 | > This Gem wraps the official Ruby [`logger`](https://github.com/ruby/logger) utility 8 | 9 | ![Gem](docs/assets/gem.png) 10 | 11 | ## Installation 💎 12 | 13 | You can download this Gem from [GitHub Packages](https://github.com/github/redacting-logger/pkgs/rubygems/redacting-logger) or [RubyGems](https://rubygems.org/gems/redacting-logger) 14 | 15 | Via a Gemfile: 16 | 17 | ```ruby 18 | source "https://rubygems.org" 19 | 20 | gem "redacting-logger", "~> X.X.X" # Replace X.X.X with the latest version 21 | ``` 22 | 23 | ## Usage 💻 24 | 25 | ### Basic 26 | 27 | ```ruby 28 | require "redacting_logger" 29 | 30 | # Create a new logger 31 | logger = RedactingLogger.new(redact_patterns: [/topsecret/]) 32 | 33 | # Log a message that contains some redacted pattern 34 | logger.info("This is a topsecret message.") 35 | ``` 36 | 37 | This will output: 38 | 39 | ```text 40 | I, [timestamp] INFO -- : This is a [REDACTED] message. 41 | ``` 42 | 43 | ### Advanced 44 | 45 | ```ruby 46 | require "redacting_logger" 47 | 48 | # Create a new logger 49 | logger = RedactingLogger.new( 50 | $stdout, # The device to log to (defaults to $stdout if not provided) 51 | redact_patterns: [/REDACTED_PATTERN1/, /REDACTED_PATTERN2/], # An array of Regexp patterns to redact from the logs 52 | level: Logger::INFO, # The log level to use 53 | redacted_msg: "[REDACTED]", # The message to replace the redacted patterns with 54 | use_default_patterns: true # Whether to use the default built-in patterns or not 55 | ) 56 | 57 | # Log a message that contains some redacted patterns 58 | logger.info("This is a message with a REDACTED_PATTERN1 and REDACTED_PATTERN2 in it.") 59 | ``` 60 | 61 | This will output: 62 | 63 | ```text 64 | I, [timestamp] INFO -- : This is a message with a [REDACTED] and [REDACTED] in it. 65 | ``` 66 | 67 | ## Default Redaction Patterns 68 | 69 | This Gem comes pre-built with a few redaction patterns to help you get started. These patterns can be located in [`lib/patterns/default.rb`](lib/patterns/default.rb) 70 | 71 | A few examples of these patterns are: 72 | 73 | - GitHub Personal Access Tokens 74 | - GitHub Temporary Actions Tokens 75 | - RSA Private Keys 76 | - JWT Tokens 77 | 78 | You can disable these default patterns with: 79 | 80 | ```ruby 81 | logger = RedactingLogger.new( 82 | use_default_patterns: false # Whether to use the default built-in patterns or not 83 | ) 84 | ``` 85 | -------------------------------------------------------------------------------- /docs/assets/gem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/docs/assets/gem.png -------------------------------------------------------------------------------- /lib/patterns/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This module contains the default patterns to redact. 4 | # These patterns are sourced from different places on the internet, some came from https://github.com/l4yton/RegHex 5 | module Patterns 6 | DEFAULT = [ 7 | # RubyGems Token 8 | # https://guides.rubygems.org/api-key-scopes/ 9 | /rubygems_[0-9a-f]{48}/, 10 | 11 | # GitHub Personal Access Token 12 | # https://github.blog/2021-04-05-behind-githubs-new-authentication-token-formats/ 13 | /ghp_[A-Za-z0-9]{36,}|[0-9A-Fa-f]{40,}/, 14 | /github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}/, # Fine Grained 15 | /ghs_[a-zA-Z0-9]{36}/, # Temporary Actions Tokens 16 | 17 | # JWT Token 18 | # https://en.wikipedia.org/wiki/JSON_Web_Token 19 | %r{\b(ey[a-zA-Z0-9]{17,}\.ey[a-zA-Z0-9/\\_-]{17,}\.(?:[a-zA-Z0-9/\\_-]{10,}={0,2})?)(?:['|"|\n|\r|\s|\x60|;]|$)}, 20 | 21 | # PEM Private Keys 22 | # https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail 23 | /(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY( BLOCK)?-----[\s\S-]*KEY( BLOCK)?----/, 24 | 25 | # Slack Webhook 26 | # https://api.slack.com/messaging/webhooks 27 | %r{https://hooks\.slack\.com/services/[a-zA-Z0-9]{9,}/[a-zA-Z0-9]{9,}/[a-zA-Z0-9]{24}}, 28 | 29 | # Slack Workflows 30 | %r{https://hooks\.slack\.com/workflows/[a-zA-Z0-9]{9,}/[a-zA-Z0-9]{9,}/[0-9]+?/[a-zA-Z0-9]{24}}, 31 | 32 | # Slack Trigger 33 | # https://slack.com/help/articles/360041352714-Build-a-workflow--Create-a-workflow-that-starts-outside-of-Slack 34 | %r{https://hooks\.slack\.com/triggers/.+}, 35 | 36 | # Slack Tokens 37 | # https://api.slack.com/authentication/token-types 38 | /xoxp-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9a-f]{6,})/, 39 | /xoxb-(?:[0-9]{7,})-(?:[A-Za-z0-9]{14,})/, 40 | /xoxs-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9a-f]{7,})/, 41 | /xoxa-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9a-f]{7,})/, 42 | /xoxo-(?:[0-9]{7,})-(?:[A-Za-z0-9]{14,})/, 43 | /xoxa-2-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9a-f]{7,})/, 44 | /xoxr-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[0-9a-f]{7,})/, 45 | /xoxb-(?:[0-9]{7,})-(?:[0-9]{7,})-(?:[A-Za-z0-9]{14,})/, 46 | 47 | # Vault Tokens 48 | # https://github.com/hashicorp/vault/issues/27151 49 | /[sbr]\.[a-zA-Z0-9]{24,}/, # <= 1.9.x 50 | /hv[sbr]\.[a-zA-Z0-9]{24,}/, # >= 1.10 51 | 52 | # Authorization bearer tokens 53 | # https://datatracker.ietf.org/doc/html/rfc6750#section-2.1 54 | /(?i)authorization:\s+bearer\s+[A-Za-z0-9\-_\.=~+\/]+/, 55 | ].freeze 56 | end 57 | -------------------------------------------------------------------------------- /lib/redacting_logger.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "logger" 4 | require_relative "patterns/default" 5 | 6 | # RedactingLogger is a custom logger that extends the standard Logger class. 7 | # It redacts specified patterns in the log messages. 8 | class RedactingLogger < Logger 9 | # Initializes a new instance of the RedactingLogger class. 10 | # 11 | # @param logdev [Object] The log device. Defaults to $stdout. 12 | # @param shift_age [Integer] The number of old log files to keep. 13 | # @param shift_size [Integer] The maximum logfile size. 14 | # @param redact_patterns [Array] The patterns to redact from the log messages. Defaults to []. 15 | # @param redacted_msg [String] The message to replace the redacted patterns with. 16 | # @param use_default_patterns [Boolean] Whether to use the default patterns or not. 17 | # @param kwargs [Hash] Additional options to pass to the Logger class. 18 | # 19 | # logdev, shift_age, and shift_size are all using the defaults from the standard Logger class. -> https://github.com/ruby/logger/blob/0996f90650fd95718f0ffe835b965de18654b71c/lib/logger.rb#L578-L580 20 | def initialize( 21 | logdev = $stdout, 22 | shift_age = 0, 23 | shift_size = 1_048_576, 24 | redact_patterns: [], 25 | redacted_msg: "[REDACTED]", 26 | use_default_patterns: true, 27 | **kwargs 28 | ) 29 | super(logdev, shift_age, shift_size, **kwargs) 30 | @redact_patterns = redact_patterns 31 | @redacted_msg = redacted_msg 32 | @redact_patterns += Patterns::DEFAULT if use_default_patterns 33 | 34 | @redact_patterns = Regexp.union(@redact_patterns) 35 | end 36 | 37 | # Adds a message to the log. 38 | # 39 | # @param severity [Integer] The severity level of the message. 40 | # @param message [String|Array|Hash] The message to log. 41 | # @param progname [String] The name of the program. 42 | def add(severity, message = nil, progname = nil) 43 | message, progname = yield if block_given? 44 | 45 | case message 46 | 47 | when String, Symbol, Numeric 48 | message = message.to_s.gsub(@redact_patterns, @redacted_msg) 49 | 50 | when Array 51 | message = message.map do |m| 52 | m.to_s.gsub(@redact_patterns, @redacted_msg) 53 | end 54 | 55 | when Hash 56 | message = message.transform_values do |v| 57 | v.to_s.gsub(@redact_patterns, @redacted_msg) 58 | end 59 | end 60 | 61 | progname = progname.to_s.gsub(@redact_patterns, @redacted_msg) if progname 62 | 63 | super 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /lib/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module RedactingLogger 4 | module Version 5 | VERSION = "1.5.0" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /redacting-logger.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "redacting-logger" 7 | spec.version = RedactingLogger::Version::VERSION 8 | spec.authors = ["GitHub", "GitHub Security"] 9 | spec.email = "opensource@github.com" 10 | spec.license = "MIT" 11 | 12 | spec.summary = "A redacting Ruby logger to prevent the leaking of secrets via logs" 13 | spec.description = <<~SPEC_DESC 14 | A redacting Ruby logger to prevent the leaking of secrets via logs 15 | SPEC_DESC 16 | 17 | spec.homepage = "https://github.com/github/redacting-logger" 18 | spec.metadata = { 19 | "source_code_uri" => "https://github.com/github/redacting-logger", 20 | "documentation_uri" => "https://github.com/github/redacting-logger", 21 | "bug_tracker_uri" => "https://github.com/github/redacting-logger/issues" 22 | } 23 | 24 | spec.add_dependency "logger", "~> 1.6" 25 | 26 | spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0") 27 | 28 | spec.files = %w[LICENSE README.md redacting-logger.gemspec] 29 | spec.files += Dir.glob("lib/**/*.rb") 30 | spec.require_paths = ["lib"] 31 | end 32 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -e # prevent any kind of script failures 4 | 5 | source script/env "$@" 6 | 7 | # bootstrap gem dependencies 8 | if [ "$BUNDLE_WITHOUT" == "" ]; then 9 | echo -e "${BLUE}Installing Gems for ${PURPLE}development${BLUE}...${OFF}" 10 | else 11 | echo -e "${BLUE}Installing Gems for ${GREEN}production${BLUE}...${OFF}" 12 | fi 13 | 14 | # what gets installed is set via the BUNDLE_WITHOUT env var in the script/env file 15 | bundle install --local 16 | bundle binstubs --all 17 | -------------------------------------------------------------------------------- /script/env: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -e # prevent any kind of script failures 4 | 5 | # COLORS 6 | export OFF='\033[0m' 7 | export RED='\033[0;31m' 8 | export GREEN='\033[0;32m' 9 | export BLUE='\033[0;34m' 10 | export PURPLE='\033[0;35m' 11 | 12 | # set RUBY_ENV to development (as a default) if not set 13 | : "${RUBY_ENV:=development}" 14 | 15 | export RUBY_ENV 16 | 17 | # set the working directory to the root of the project 18 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )" 19 | export DIR 20 | 21 | # The name of the repository is the name of the directory (usually) 22 | REPO_NAME=$(basename "$PWD") 23 | export REPO_NAME 24 | 25 | # set the ruby version to the one specified in the .ruby-version file 26 | [ -z "$RBENV_VERSION" ] && RBENV_VERSION=$(cat "$DIR/.ruby-version") 27 | export RBENV_VERSION 28 | 29 | # set the path to include the rbenv shims if they exist 30 | [ -d "/usr/share/rbenv/shims" ] && export PATH=/usr/share/rbenv/shims:$PATH 31 | 32 | # detect OS version and architecture 33 | if [[ "$OSTYPE" == "linux-gnu"* ]]; then 34 | PLATFORM="linux" 35 | VERSION=$(grep '^VERSION_CODENAME=' /etc/os-release | cut -d '=' -f2 || echo "unknown") 36 | elif [[ "$OSTYPE" == "darwin"* ]]; then 37 | PLATFORM="macos" 38 | VERSION=$(sw_vers -productVersion || echo "unknown") 39 | else 40 | PLATFORM="unknown" 41 | VERSION="unknown" 42 | fi 43 | 44 | ARCH=$(uname -m || echo "unknown") 45 | 46 | export PLATFORM 47 | export VERSION 48 | export ARCH 49 | 50 | shopt -s nocasematch # enable case-insensitive matching 51 | if [[ "$RUBY_ENV" == "production" ]]; then 52 | export BUNDLE_WITHOUT="development" 53 | fi 54 | shopt -u nocasematch # disable case-insensitive matching 55 | 56 | # make the vendor/cache directory if it doesn't exist 57 | mkdir -p "$DIR/vendor/cache" 58 | -------------------------------------------------------------------------------- /script/lint: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -e 4 | 5 | source script/env "$@" 6 | 7 | # run linter 8 | echo -e "\n🤖 ${BLUE}Running Rubocop: $(date "+%H:%M:%S")${OFF}\n" 9 | 10 | bundle exec rubocop -c .rubocop.yml lib/ spec/ "$@" 11 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | set -e 4 | 5 | source script/env "$@" 6 | 7 | # run tests 8 | echo -e "\n🧪 ${BLUE}Running tests: $(date "+%H:%M:%S")${OFF}\n" 9 | 10 | bundle exec bin/rspec spec && rspec_exit=$? || rspec_exit=$? 11 | 12 | total_coverage=$(cat "$DIR/coverage/total-coverage.txt") 13 | 14 | if grep -q "100.0" "$DIR/coverage/total-coverage.txt"; then 15 | cov_exit=0 16 | echo -e "\n✅ Total Coverage: ${GREEN}$total_coverage${OFF}" 17 | else 18 | cov_exit=1 19 | echo -e "\n❌ Total Coverage: ${RED}$total_coverage${OFF}" 20 | fi 21 | 22 | echo "" 23 | echo "---------------------------------------" 24 | echo "📊 Summary Results" 25 | echo "---------------------------------------" 26 | echo "" 27 | 28 | if [[ $rspec_exit == 0 ]]; then 29 | echo -e "✅ ${GREEN}rspec: exitcode=${rspec_exit}${OFF}" 30 | else 31 | echo -e "❌ ${RED}rspec: exitcode=${rspec_exit}${OFF}" 32 | fi 33 | 34 | if [[ $cov_exit == 0 ]]; then 35 | echo -e "✅ ${GREEN}coverage: exitcode=${cov_exit}${OFF}" 36 | else 37 | echo -e "❌ ${RED}coverage: exitcode=${cov_exit}${OFF}" 38 | fi 39 | 40 | [ "$rspec_exit" -gt 0 ] && exit 1 41 | [ $cov_exit -gt 0 ] && exit 1 42 | 43 | exit 0 44 | -------------------------------------------------------------------------------- /spec/fixtures/fake.private_key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWgIBAAKBgGoYIuq9HddnNIqkdZODTLvo/XACp39SprGGpG3DdozcKr9f3Zyg 3 | AOrF898TvUaxjIPp7roLpNKH6uyK/mHGwESiM1hVT/KK2YUb0Urwc2hNSCoN9nn4 4 | hN5tSXRh1P0PCjYC8oJhHfvrgEUrAvBnLx1RKJ6cG0OSbBk+y16lEZSbAgMBAAEC 5 | gYBovuu6Vnzf7kUxnK14tmlMHPwbWoOEcVWicAxnUlP5PmX2C/AAcvh00nu0Awkc 6 | gq74jj3j8RsJwKdwYspEPrYTx6Qi+mtTfDAwXkJNWFQCKI3RtGF51fbvj3GL/tcZ 7 | mdMdhSMqZFgOgPcaYxpRIx+q2NDj8wBdSnEsmlidcH/2AQJBAKUpFqGI2oG4y9Ed 8 | hw1V9XyLna1wNZq96Ua9k+YW/Y6MO/pEzEgUxNgF5/tSIVoAgHqw41Y7mWwt1yP/ 9 | jkTC+c0CQQCkcmmW2sokdeF+6ssgAf8cIZqMYZ8ND9yQQlYJZ01MZ/s0OpBWz4jD 10 | 8kePMoBP1nBNPgLq03IlbSNrjQya78AHAkAdRBujghmeFP3gz0eoIExAxoipPBHz 11 | mqVkiKFVi0tg4A6cuWYte6ip0toZmaMZTK93jjKqjCMSnUjbMySloJsdAkBWu9mh 12 | LUiMrnf+vsvf1+274qVnAV4oP4Nvuu0yDIAimn1N8M2MW+2gm7rOdi5i7ZFRzDEx 13 | tdBwmP2jjkNlvKolAkBa/x6jUiLhPMlypTpJvwJdYd7E/w8zEctSSXq6xbrZjUfT 14 | who52YgHVfGnCNkgrjnCSAswsFbJ8d5vLijGFcXM 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /spec/lib/redacting_logger_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "logger" 4 | require "stringio" 5 | require_relative "../spec_helper" 6 | require_relative "../../lib/redacting_logger" 7 | 8 | describe RedactingLogger do 9 | context "#initialize" do 10 | it "ensures the class is initialized properly" do 11 | redact_patterns = ["secret", "password"] 12 | level = Logger::INFO 13 | logger = RedactingLogger.new( 14 | $stdout, 15 | redact_patterns:, 16 | level:, 17 | redacted_msg: "!!!REDACTED!!!", 18 | use_default_patterns: false 19 | ) 20 | 21 | expect(logger.level).to eq(level) 22 | expect(logger.instance_variable_get(:@redact_patterns)).to eq(/secret|password/) 23 | expect(logger.instance_variable_get(:@logdev).dev).to eq($stdout) 24 | expect(logger.instance_variable_get(:@redacted_msg)).to eq("!!!REDACTED!!!") 25 | end 26 | 27 | it "ensures the class is initialized properly with default values" do 28 | logger = RedactingLogger.new(use_default_patterns: false) 29 | expect(logger.level).to eq(Logger::DEBUG) 30 | expect(logger.instance_variable_get(:@redact_patterns)).to eq(/(?!)/) 31 | expect(logger.instance_variable_get(:@logdev).dev).to eq($stdout) 32 | expect(logger.instance_variable_get(:@redacted_msg)).to eq("[REDACTED]") 33 | end 34 | 35 | it "ensures the class is initialized properly with default values and uses built-in patterns" do 36 | logger = RedactingLogger.new($stdout, use_default_patterns: true) 37 | expect(logger.level).to eq(Logger::DEBUG) 38 | expect(logger.instance_variable_get(:@redact_patterns).to_s.length).to be > 0 39 | expect(logger.instance_variable_get(:@logdev).dev).to eq($stdout) 40 | expect(logger.instance_variable_get(:@redacted_msg)).to eq("[REDACTED]") 41 | end 42 | end 43 | 44 | context "#add" do 45 | let(:logdev) { StringIO.new } 46 | let(:logger) { RedactingLogger.new(logdev, redact_patterns: [/secret/, /password/, /token_[A-Z]{5}/, /999999999/]) } 47 | 48 | [ 49 | { 50 | case: "does not redact anything", 51 | message: "This is a non-sensitive message with no redacted patterns", 52 | expected_message: "This is a non-sensitive message with no redacted patterns" 53 | }, 54 | { 55 | case: "secret message", 56 | message: "This is a secret password", 57 | expected_message: "This is a [REDACTED] [REDACTED]" 58 | }, 59 | { 60 | case: "secret progname", 61 | progname: "secret progname", 62 | expected_progname: "[REDACTED] progname" 63 | }, 64 | { 65 | case: "secret substring", 66 | message: "This is a supersecretmessage", 67 | expected_message: "This is a super[REDACTED]message" 68 | }, 69 | { 70 | case: "github token", 71 | message: "token ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890", 72 | expected_message: "token [REDACTED]" 73 | }, 74 | { 75 | case: "github token hidden in another string", 76 | message: "token ghp_aBcdeFghIjklMnoPqRSTUvwXYZ1234567890ohnothisisnotgood", 77 | expected_message: "token [REDACTED]" 78 | }, 79 | { 80 | case: "fine-grained github pat", 81 | message: "token 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", 82 | expected_message: "token [REDACTED]" 83 | }, 84 | { 85 | case: "github action pat", 86 | message: "token ghs_1234567890abcdefghijklmnopqrstuvwxyz123456", 87 | expected_message: "token [REDACTED]123456" 88 | }, 89 | { 90 | case: "custom token", 91 | message: "token token_ABCDE", 92 | expected_message: "token [REDACTED]" 93 | }, 94 | { 95 | case: "custom token only if long enough", 96 | message: "token token_ABCD", 97 | expected_message: "token token_ABCD" 98 | }, 99 | { 100 | case: "JWT token", 101 | message: "token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", 102 | expected_message: "token [REDACTED]" 103 | }, 104 | { 105 | case: "RSA private key", 106 | message: "token #{File.read("spec/fixtures/fake.private_key")}", 107 | expected_message: "token [REDACTED]-\n" 108 | }, 109 | { 110 | case: "list of messages", 111 | message: ["this", "is", "a", "secret"], 112 | expected_message: ["this", "is", "a", "[REDACTED]"] 113 | }, 114 | { 115 | case: "hash of messages", 116 | message: { this: "is", "a" => "secret" }, 117 | expected_message: { this: "is", "a" => "[REDACTED]" } 118 | }, 119 | { 120 | case: "hash of messages more complex", 121 | message: { this: "is", "a" => "super top secret" }, 122 | expected_message: { this: "is", "a" => "super top [REDACTED]" } 123 | }, 124 | { 125 | case: "redacts from a symbol", 126 | message: :top_secret, 127 | expected_message: "top_[REDACTED]" 128 | }, 129 | { 130 | case: "redacts from a Numeric full match", 131 | message: 999_999_999, 132 | expected_message: "[REDACTED]" 133 | }, 134 | { 135 | case: "redacts from a Numeric match with extra numbers", 136 | message: 123_999_999_999_123, 137 | expected_message: "123[REDACTED]123" 138 | }, 139 | { 140 | case: "redacts a Slack webhook", 141 | message: "posting slack message to: https://hooks.slack.com/services/T1BAAA111/B0111AAA111/MMMAAA333CCC222bbbAAA111", 142 | expected_message: "posting slack message to: [REDACTED]" 143 | }, 144 | { 145 | case: "redacts a Slack workflow webhook", 146 | message: "workflow: https://hooks.slack.com/workflows/abc123XYZ/def456UVW/123456789/abcdefghijklmnopqrstuvwx", 147 | expected_message: "workflow: [REDACTED]" 148 | }, 149 | { 150 | case: "redacts a Slack token", 151 | message: "using slack token: xoxb-2444333222111-2444333222111-123456789AbCdEfGHi123456", 152 | expected_message: "using slack token: [REDACTED]" 153 | }, 154 | { 155 | case: "redacts a vault token", 156 | message: "logging into vault with token: s.FakeToken1234567890123456", 157 | expected_message: "logging into vault with token: [REDACTED]" 158 | }, 159 | { 160 | case: "redacts a RubyGems token", 161 | message: "using rubygems token: rubygems_0123456789abcdef0123456789abcdef0123456789abcdef", 162 | expected_message: "using rubygems token: [REDACTED]" 163 | }, 164 | { 165 | case: "redacts authorization bearer token", 166 | message: '-H "Authorization: Bearer ab123456789a1abcd1~_.-+456ABCDE=" -H "Content-Type: application/json"', 167 | expected_message: '-H "[REDACTED]" -H "Content-Type: application/json"' 168 | }, 169 | { 170 | case: "redacts authorization bearer token with case insensitivity", 171 | message: '-H "authorizAtion: beaRer ab123456789a1abcd1~_.-+456ABCDE=" -H "Content-Type: application/json"', 172 | expected_message: '-H "[REDACTED]" -H "Content-Type: application/json"' 173 | }, 174 | { 175 | case: "redacts authorization bearer token with extra spaces and tabs", 176 | message: "authorization: bearer abcd1234", 177 | expected_message: "[REDACTED]" 178 | }, 179 | { 180 | case: "redacts authorization bearer token with special characters", 181 | message: "authorization: bearer aBcD-_=~+/1234", 182 | expected_message: "[REDACTED]" 183 | }, 184 | { 185 | case: "redacts authorization bearer token at start of string", 186 | message: "authorization: bearer tokenatstart", 187 | expected_message: "[REDACTED]" 188 | }, 189 | { 190 | case: "redacts authorization bearer token at end of string", 191 | message: "some text authorization: bearer tokenatend", 192 | expected_message: "some text [REDACTED]" 193 | }, 194 | { 195 | case: "redacts multiple authorization bearer tokens in one string", 196 | message: "authorization: bearer token1 and authorization: bearer token2", 197 | expected_message: "[REDACTED] and [REDACTED]" 198 | }, 199 | { 200 | case: "redacts authorization bearer token with minimum plausible length", 201 | message: "authorization: bearer a", 202 | expected_message: "[REDACTED]" 203 | }, 204 | { 205 | case: "redacts authorization bearer token with maximum plausible length", 206 | message: "authorization: bearer #{'a' * 256}", 207 | expected_message: "[REDACTED]" 208 | } 209 | ].each do |test| 210 | it "redacts #{test[:case]}" do 211 | expect_any_instance_of(Logger).to receive(:add).with(0, test[:expected_message], test[:expected_progname]) 212 | logger.add(0, test[:message], test[:progname]) 213 | end 214 | end 215 | 216 | it "redacts with given block" do 217 | logger.info { ["This is a secret password", nil] } 218 | 219 | logdev.rewind 220 | log_output = logdev.read 221 | 222 | expect(log_output).to match(/This is a \[REDACTED\] \[REDACTED\]/) 223 | end 224 | end 225 | end 226 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ENV["APP_ENV"] = "test" 4 | 5 | require "simplecov" 6 | require "rspec" 7 | require "simplecov-erb" 8 | 9 | COV_DIR = File.expand_path("../coverage", File.dirname(__FILE__)) 10 | 11 | SimpleCov.root File.expand_path("..", File.dirname(__FILE__)) 12 | SimpleCov.coverage_dir COV_DIR 13 | 14 | SimpleCov.formatters = [ 15 | SimpleCov::Formatter::HTMLFormatter, 16 | SimpleCov::Formatter::ERBFormatter 17 | ] 18 | 19 | SimpleCov.minimum_coverage 100 20 | 21 | SimpleCov.at_exit do 22 | File.write("#{COV_DIR}/total-coverage.txt", SimpleCov.result.covered_percent) 23 | SimpleCov.result.format! 24 | end 25 | 26 | SimpleCov.start do 27 | add_filter "spec/" 28 | add_filter "vendor/gems/" 29 | end 30 | -------------------------------------------------------------------------------- /vendor/cache/activesupport-7.1.5.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/activesupport-7.1.5.1.gem -------------------------------------------------------------------------------- /vendor/cache/ast-2.4.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/ast-2.4.3.gem -------------------------------------------------------------------------------- /vendor/cache/base64-0.2.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/base64-0.2.0.gem -------------------------------------------------------------------------------- /vendor/cache/benchmark-0.4.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/benchmark-0.4.0.gem -------------------------------------------------------------------------------- /vendor/cache/bigdecimal-3.1.9.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/bigdecimal-3.1.9.gem -------------------------------------------------------------------------------- /vendor/cache/concurrent-ruby-1.3.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/concurrent-ruby-1.3.5.gem -------------------------------------------------------------------------------- /vendor/cache/connection_pool-2.5.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/connection_pool-2.5.0.gem -------------------------------------------------------------------------------- /vendor/cache/date-3.4.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/date-3.4.1.gem -------------------------------------------------------------------------------- /vendor/cache/diff-lcs-1.6.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/diff-lcs-1.6.2.gem -------------------------------------------------------------------------------- /vendor/cache/docile-1.4.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/docile-1.4.0.gem -------------------------------------------------------------------------------- /vendor/cache/drb-2.2.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/drb-2.2.1.gem -------------------------------------------------------------------------------- /vendor/cache/i18n-1.14.7.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/i18n-1.14.7.gem -------------------------------------------------------------------------------- /vendor/cache/io-console-0.8.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/io-console-0.8.0.gem -------------------------------------------------------------------------------- /vendor/cache/irb-1.15.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/irb-1.15.2.gem -------------------------------------------------------------------------------- /vendor/cache/json-2.12.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/json-2.12.2.gem -------------------------------------------------------------------------------- /vendor/cache/language_server-protocol-3.17.0.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/language_server-protocol-3.17.0.5.gem -------------------------------------------------------------------------------- /vendor/cache/lint_roller-1.1.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/lint_roller-1.1.0.gem -------------------------------------------------------------------------------- /vendor/cache/logger-1.7.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/logger-1.7.0.gem -------------------------------------------------------------------------------- /vendor/cache/minitest-5.25.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/minitest-5.25.5.gem -------------------------------------------------------------------------------- /vendor/cache/mutex_m-0.3.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/mutex_m-0.3.0.gem -------------------------------------------------------------------------------- /vendor/cache/parallel-1.27.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/parallel-1.27.0.gem -------------------------------------------------------------------------------- /vendor/cache/parser-3.3.8.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/parser-3.3.8.0.gem -------------------------------------------------------------------------------- /vendor/cache/pp-0.6.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/pp-0.6.2.gem -------------------------------------------------------------------------------- /vendor/cache/prettyprint-0.2.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/prettyprint-0.2.0.gem -------------------------------------------------------------------------------- /vendor/cache/prism-1.4.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/prism-1.4.0.gem -------------------------------------------------------------------------------- /vendor/cache/psych-5.2.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/psych-5.2.3.gem -------------------------------------------------------------------------------- /vendor/cache/racc-1.8.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/racc-1.8.1.gem -------------------------------------------------------------------------------- /vendor/cache/rack-3.1.14.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rack-3.1.14.gem -------------------------------------------------------------------------------- /vendor/cache/rainbow-3.1.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rainbow-3.1.1.gem -------------------------------------------------------------------------------- /vendor/cache/rdoc-6.13.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rdoc-6.13.1.gem -------------------------------------------------------------------------------- /vendor/cache/regexp_parser-2.10.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/regexp_parser-2.10.0.gem -------------------------------------------------------------------------------- /vendor/cache/reline-0.6.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/reline-0.6.1.gem -------------------------------------------------------------------------------- /vendor/cache/rspec-3.13.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rspec-3.13.1.gem -------------------------------------------------------------------------------- /vendor/cache/rspec-core-3.13.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rspec-core-3.13.4.gem -------------------------------------------------------------------------------- /vendor/cache/rspec-expectations-3.13.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rspec-expectations-3.13.5.gem -------------------------------------------------------------------------------- /vendor/cache/rspec-mocks-3.13.5.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rspec-mocks-3.13.5.gem -------------------------------------------------------------------------------- /vendor/cache/rspec-support-3.13.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rspec-support-3.13.4.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-1.75.7.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-1.75.7.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-ast-1.44.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-ast-1.44.1.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-github-0.23.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-github-0.23.0.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-performance-1.25.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-performance-1.25.0.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-rails-2.30.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-rails-2.30.3.gem -------------------------------------------------------------------------------- /vendor/cache/rubocop-rspec-3.6.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/rubocop-rspec-3.6.0.gem -------------------------------------------------------------------------------- /vendor/cache/ruby-progressbar-1.13.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/ruby-progressbar-1.13.0.gem -------------------------------------------------------------------------------- /vendor/cache/securerandom-0.3.2.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/securerandom-0.3.2.gem -------------------------------------------------------------------------------- /vendor/cache/simplecov-0.22.0.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/simplecov-0.22.0.gem -------------------------------------------------------------------------------- /vendor/cache/simplecov-erb-1.0.1.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/simplecov-erb-1.0.1.gem -------------------------------------------------------------------------------- /vendor/cache/simplecov-html-0.12.3.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/simplecov-html-0.12.3.gem -------------------------------------------------------------------------------- /vendor/cache/simplecov_json_formatter-0.1.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/simplecov_json_formatter-0.1.4.gem -------------------------------------------------------------------------------- /vendor/cache/stringio-3.1.6.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/stringio-3.1.6.gem -------------------------------------------------------------------------------- /vendor/cache/tzinfo-2.0.6.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/tzinfo-2.0.6.gem -------------------------------------------------------------------------------- /vendor/cache/unicode-display_width-3.1.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/unicode-display_width-3.1.4.gem -------------------------------------------------------------------------------- /vendor/cache/unicode-emoji-4.0.4.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/github/redacting-logger/71c3397f13a2f8f20bc95958044960974fdc960d/vendor/cache/unicode-emoji-4.0.4.gem --------------------------------------------------------------------------------