auth-sanitizer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48345c9c15c3bcfefec251d9258d1a949ce27ed13f46a23c1458efffa1a20ebe
4
- data.tar.gz: 55a0935c3ac081f62bf9767f3a1157911dbf5fae71e5f7c669954d3dfeffd842
3
+ metadata.gz: a459f96a2569fc0a45f1f0fcc919d6324f64902e4ed7364a617aebed42b6936a
4
+ data.tar.gz: 7e27c3b29c2f47b0afcf740098f14472f3f936828df479e4a3e808d8259523ad
5
5
  SHA512:
6
- metadata.gz: fa2206c9f38364d722d6ddc5cb1d52d626c57f37ee681f4c3dd745b3add67720435f8507033eb9fd6d765532b791723946282ed3fa1da70521df53d86300318e
7
- data.tar.gz: 54a1aaa99bf99ffa69079bf000fbc9ab3b995bfda620eb797f488fefd83fa26f1854bd89428ad91ae25d0cc2c3bd38add165002d2833391d2541dead0bd199a6
6
+ metadata.gz: 86ea9c3a4721881b599ba6e63a50cc0d9f4b5a9d5c8dbe1c7bd140ce802c4d28d1df0278b4f16aee472c7feabe34e30c6d16dc5943c12a4c6a9a429519de9e82
7
+ data.tar.gz: 381e1f25c5bd0301f3d1ba91f6f20a6370e6d6158a87270f166e85a84abc556dc865b0c1a2f8d449ba7b08b82ad34b8c4589601bb8ff09bfc72c96c4ef14b2e0
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,32 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [0.1.2] - 2026-05-15
34
+
35
+ - TAG: [v0.1.2][0.1.2t]
36
+ - COVERAGE: 100.00% -- 134/134 lines in 5 files
37
+ - BRANCH COVERAGE: 100.00% -- 28/28 branches in 5 files
38
+ - 87.50% documented
39
+
40
+ ### Added
41
+
42
+ - gemspec description, summary
43
+
44
+ ### Changed
45
+
46
+ - gemspec contact email
47
+
48
+ ## [0.1.1] - 2026-05-15
49
+
50
+ - TAG: [v0.1.1][0.1.1t]
51
+ - COVERAGE: 100.00% -- 134/134 lines in 5 files
52
+ - BRANCH COVERAGE: 100.00% -- 28/28 branches in 5 files
53
+ - 87.50% documented
54
+
55
+ ### Added
56
+
57
+ - Usage documentation in README.md
58
+
33
59
  ## [0.1.0] - 2026-05-15
34
60
 
35
61
  - TAG: [v0.1.0][0.1.0t]
@@ -41,6 +67,10 @@ Please file a bug if you notice a violation of semantic versioning.
41
67
 
42
68
  - Initial release
43
69
 
44
- [Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.0...HEAD
70
+ [Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.2...HEAD
71
+ [0.1.2]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.1...v0.1.2
72
+ [0.1.2t]: https://github.com//ruby-oauth/auth-sanitizer/releases/tag/v0.1.2
73
+ [0.1.1]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.0...v0.1.1
74
+ [0.1.1t]: https://github.com//ruby-oauth/auth-sanitizer/releases/tag/v0.1.1
45
75
  [0.1.0]: https://github.com/ruby-oauth/auth-sanitizer/compare/21d6165dca7eef8e7b9bb01fdfc4cc8bab4e5b96...v0.1.0
46
76
  [0.1.0t]: https://github.com/ruby-oauth/auth-sanitizer/releases/tag/v0.1.0
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [🖼️oauth2-i]: https://logos.galtzo.com/assets/images/oauth/oauth2/avatar-192px.svg
8
8
  [🖼️oauth2]: https://github.com/ruby-oauth/oauth2
9
9
 
10
- # 🍲 Auth::Sanitizer
10
+ # 🟥 Auth::Sanitizer
11
11
 
12
12
  [![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![CodeCov Test Coverage][🏀codecovi]][🏀codecov] [![Coveralls Test Coverage][🏀coveralls-img]][🏀coveralls] [![QLTY Test Coverage][🏀qlty-covi]][🏀qlty-cov] [![QLTY Maintainability][🏀qlty-mnti]][🏀qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Runtime Dependencies @ HEAD][🚎12-crh-wfi]][🚎12-crh-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Apache SkyWalking Eyes License Compatibility Check][🚎15-🪪-wfi]][🚎15-🪪-wf]
13
13
 
@@ -28,6 +28,36 @@ I've summarized my thoughts in [this blog post](https://dev.to/galtzo/hostile-ta
28
28
 
29
29
  ## 🌻 Synopsis
30
30
 
31
+ `auth-sanitizer` provides small, dependency-light helpers for keeping OAuth and authentication secrets out of object
32
+ inspection and log output.
33
+
34
+ The gem is intentionally narrow in scope. It does not change HTTP requests, token objects, persistence, or application
35
+ configuration for you. Instead, it gives host gems and applications two reusable redaction surfaces:
36
+
37
+ - `Auth::Sanitizer::FilteredAttributes` redacts selected instance variables from `#inspect`.
38
+ - `Auth::Sanitizer::SanitizedLogger` wraps an existing logger and redacts sensitive values from string log messages.
39
+
40
+ Out of the box, logger sanitization filters the key names most commonly found in OAuth and OpenID Connect debug output:
41
+
42
+ ```ruby
43
+ Auth::Sanitizer.default_filtered_keys
44
+ # => [
45
+ # "access_token",
46
+ # "refresh_token",
47
+ # "id_token",
48
+ # "client_secret",
49
+ # "assertion",
50
+ # "code_verifier",
51
+ # "token",
52
+ # ]
53
+ ```
54
+
55
+ Redacted values are replaced with `"[FILTERED]"` by default. The replacement label can be changed globally by installing
56
+ a provider, or per logger by passing `label:` to `Auth::Sanitizer::SanitizedLogger.new`.
57
+
58
+ The library snapshots filter configuration when a redacting object is initialized. That keeps already-created objects
59
+ and logger wrappers stable even if a host application changes its configuration later.
60
+
31
61
  ## 💡 Info you can shake a stick at
32
62
 
33
63
  | Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] |
@@ -143,8 +173,235 @@ NOTE: Be prepared to track down certs for signed gems and add them the same way
143
173
 
144
174
  ## ⚙️ Configuration
145
175
 
176
+ Most applications can use the defaults. Configuration is available when a host gem or application wants to align
177
+ redaction with its own logging conventions.
178
+
179
+ ### Filtered Label
180
+
181
+ The default replacement label is:
182
+
183
+ ```ruby
184
+ Auth::Sanitizer.filtered_label
185
+ # => "[FILTERED]"
186
+ ```
187
+
188
+ To use a different label globally, install a callable provider:
189
+
190
+ ```ruby
191
+ Auth::Sanitizer.filtered_label_provider = -> { "[REDACTED]" }
192
+ ```
193
+
194
+ The provider is called when a `FilteredAttributes` object or `SanitizedLogger` wrapper is initialized. Existing
195
+ instances keep the label they captured at initialization time:
196
+
197
+ ```ruby
198
+ Auth::Sanitizer.filtered_label_provider = -> { "[FILTERED]" }
199
+ logger = Auth::Sanitizer::SanitizedLogger.new(Logger.new($stdout))
200
+
201
+ Auth::Sanitizer.filtered_label_provider = -> { "[REDACTED]" }
202
+
203
+ # `logger` still uses "[FILTERED]"; new wrappers use "[REDACTED]".
204
+ ```
205
+
206
+ This makes it safe for libraries to delegate the label to host configuration:
207
+
208
+ ```ruby
209
+ Auth::Sanitizer.filtered_label_provider = -> { MyGem.config.filtered_label }
210
+ ```
211
+
212
+ ### Logger Keys
213
+
214
+ `Auth::Sanitizer::SanitizedLogger` defaults to `Auth::Sanitizer.default_filtered_keys`. Pass `filtered_keys:` when your
215
+ application logs additional sensitive fields:
216
+
217
+ ```ruby
218
+ logger = Auth::Sanitizer::SanitizedLogger.new(
219
+ Logger.new($stdout),
220
+ filtered_keys: Auth::Sanitizer.default_filtered_keys + %w[
221
+ api_key
222
+ private_key
223
+ session_secret
224
+ ],
225
+ )
226
+ ```
227
+
228
+ You can also replace the list entirely:
229
+
230
+ ```ruby
231
+ logger = Auth::Sanitizer::SanitizedLogger.new(
232
+ Logger.new($stdout),
233
+ filtered_keys: %w[my_secret],
234
+ label: "[GONE]",
235
+ )
236
+ ```
237
+
238
+ Logger key matching is case-insensitive for supported string formats. The keys are used to redact:
239
+
240
+ - JSON-style pairs, such as `"access_token": "abc123"` and `'client_secret': 'abc123'`
241
+ - query-string and form-encoded pairs, such as `access_token=abc123&scope=read`
242
+ - `Authorization:` header values, regardless of `filtered_keys`
243
+
244
+ Only string payloads are sanitized. Non-string log payloads are delegated unchanged to the wrapped logger.
245
+
246
+ ### Inspect Attributes
247
+
248
+ Classes opt in to inspect redaction by including `Auth::Sanitizer::FilteredAttributes` and declaring the attribute names
249
+ that should be hidden:
250
+
251
+ ```ruby
252
+ class OAuthCredential
253
+ include Auth::Sanitizer::FilteredAttributes
254
+
255
+ attr_reader :access_token, :expires_at
256
+
257
+ filtered_attributes :access_token
258
+
259
+ def initialize(access_token, expires_at)
260
+ @access_token = access_token
261
+ @expires_at = expires_at
262
+ end
263
+ end
264
+ ```
265
+
266
+ Declared names are matched against instance variable names. For example, `filtered_attributes :access_token` redacts
267
+ `@access_token` in `#inspect`.
268
+
269
+ Calling `filtered_attributes` again replaces the class-level list:
270
+
271
+ ```ruby
272
+ OAuthCredential.filtered_attributes(:access_token, :refresh_token)
273
+ OAuthCredential.filtered_attribute_names
274
+ # => [:access_token, :refresh_token]
275
+ ```
276
+
277
+ Passing no attributes clears the class-level list for subsequently initialized objects:
278
+
279
+ ```ruby
280
+ OAuthCredential.filtered_attributes
281
+ OAuthCredential.filtered_attribute_names
282
+ # => []
283
+ ```
284
+
285
+ As with logger wrappers, the per-object filter is captured during initialization. Objects that already exist keep their
286
+ original inspect behavior.
287
+
146
288
  ## 🔧 Basic Usage
147
289
 
290
+ Require the gem:
291
+
292
+ ```ruby
293
+ require "auth/sanitizer"
294
+ ```
295
+
296
+ ### Redact `#inspect`
297
+
298
+ Use `Auth::Sanitizer::FilteredAttributes` for objects that may appear in exception messages, console sessions, or debug
299
+ output through `#inspect`:
300
+
301
+ ```ruby
302
+ class TokenResponse
303
+ include Auth::Sanitizer::FilteredAttributes
304
+
305
+ attr_reader :access_token, :refresh_token, :scope
306
+
307
+ filtered_attributes :access_token, :refresh_token
308
+
309
+ def initialize(access_token:, refresh_token:, scope:)
310
+ @access_token = access_token
311
+ @refresh_token = refresh_token
312
+ @scope = scope
313
+ end
314
+ end
315
+
316
+ response = TokenResponse.new(
317
+ access_token: "access-token-value",
318
+ refresh_token: "refresh-token-value",
319
+ scope: "profile email",
320
+ )
321
+
322
+ response.inspect
323
+ # => #<TokenResponse:123456 @access_token=[FILTERED], @refresh_token=[FILTERED], @scope="profile email">
324
+ ```
325
+
326
+ Only the configured attributes are redacted. Other instance variables remain visible so inspected objects are still
327
+ useful while debugging.
328
+
329
+ ### Redact Logger Output
330
+
331
+ Wrap an existing logger with `Auth::Sanitizer::SanitizedLogger`:
332
+
333
+ ```ruby
334
+ require "logger"
335
+ require "auth/sanitizer"
336
+
337
+ logger = Auth::Sanitizer::SanitizedLogger.new(Logger.new($stdout))
338
+
339
+ logger.debug("access_token=abc123&scope=profile")
340
+ # Logs: access_token=[FILTERED]&scope=profile
341
+
342
+ logger.debug('{"client_secret": "super-secret", "grant_type": "client_credentials"}')
343
+ # Logs: {"client_secret": "[FILTERED]", "grant_type": "client_credentials"}
344
+
345
+ logger.debug("Authorization: Bearer abc123")
346
+ # Logs: Authorization: "[FILTERED]"
347
+ ```
348
+
349
+ The wrapper implements the common Ruby logger methods and sanitizes string values passed through them:
350
+
351
+ ```ruby
352
+ logger.add(Logger::DEBUG, "refresh_token=abc123", "oauth")
353
+ logger << "id_token=abc123"
354
+
355
+ logger.debug { "code_verifier=abc123" }
356
+ logger.info("token=abc123")
357
+ logger.warn("client_secret=abc123")
358
+ logger.error("assertion=abc123")
359
+ logger.fatal("Authorization: Bearer abc123")
360
+ logger.unknown("access_token=abc123")
361
+ ```
362
+
363
+ The wrapper also delegates common logger configuration to the wrapped logger when supported:
364
+
365
+ ```ruby
366
+ logger.level = Logger::WARN
367
+ logger.progname = "my-app"
368
+ logger.formatter = proc { |_severity, _time, _progname, message| "#{message}\n" }
369
+ logger.close
370
+ ```
371
+
372
+ Methods not implemented by the wrapper are delegated to the underlying logger when that logger responds to them.
373
+
374
+ ### Custom Logger Keys
375
+
376
+ Use `filtered_keys:` for application-specific secrets:
377
+
378
+ ```ruby
379
+ logger = Auth::Sanitizer::SanitizedLogger.new(
380
+ Logger.new($stdout),
381
+ filtered_keys: %w[access_token api_key signing_secret],
382
+ label: "[SECRET]",
383
+ )
384
+
385
+ logger.debug("api_key=12345&access_token=abc123")
386
+ # Logs: api_key=[SECRET]&access_token=[SECRET]
387
+ ```
388
+
389
+ `filtered_keys:` applies to JSON-style, query-string, and form-encoded key/value pairs. `Authorization:` headers are
390
+ always redacted by `SanitizedLogger`, even if `Authorization` is not listed as a filtered key.
391
+
392
+ ### Important Limits
393
+
394
+ `auth-sanitizer` is a logging and inspection helper, not a complete secret-management system.
395
+
396
+ - It redacts supported string patterns before delegating to a logger.
397
+ - It does not mutate source hashes, token objects, HTTP requests, or HTTP responses.
398
+ - It does not recursively sanitize arbitrary Ruby objects passed to a logger as non-string payloads.
399
+ - It cannot protect secrets that are logged through a different logger, printed directly, or interpolated into an
400
+ unsupported format.
401
+
402
+ For best results, wrap the logger as close as possible to the code that emits authentication debug output, and avoid
403
+ logging raw token structures unless they pass through the sanitizer first.
404
+
148
405
  ## 🦷 FLOSS Funding
149
406
 
150
407
  While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding.
@@ -3,7 +3,7 @@
3
3
  module Auth
4
4
  module Sanitizer
5
5
  module Version
6
- VERSION = "0.1.0"
6
+ VERSION = "0.1.2"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auth-sanitizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -213,9 +213,9 @@ dependencies:
213
213
  - - ">="
214
214
  - !ruby/object:Gem::Version
215
215
  version: 1.0.3
216
- description: "\U0001F372 TODO: Write a longer description or delete this line."
216
+ description: "\U0001F7E5 Configurable KV output redaction. Sanitize/filter your secrets."
217
217
  email:
218
- - peter.boling@gmail.com
218
+ - floss@galtzo.com
219
219
  executables: []
220
220
  extensions: []
221
221
  extra_rdoc_files:
@@ -249,10 +249,10 @@ licenses:
249
249
  - MIT
250
250
  metadata:
251
251
  homepage_uri: https://auth-sanitizer.galtzo.com/
252
- source_code_uri: https://github.com/ruby-oauth/auth-sanitizer/tree/v0.1.0
253
- changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.0/CHANGELOG.md
252
+ source_code_uri: https://github.com/ruby-oauth/auth-sanitizer/tree/v0.1.2
253
+ changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.2/CHANGELOG.md
254
254
  bug_tracker_uri: https://github.com/ruby-oauth/auth-sanitizer/issues
255
- documentation_uri: https://www.rubydoc.info/gems/auth-sanitizer/0.1.0
255
+ documentation_uri: https://www.rubydoc.info/gems/auth-sanitizer/0.1.2
256
256
  funding_uri: https://github.com/sponsors/pboling
257
257
  wiki_uri: https://github.com/ruby-oauth/auth-sanitizer/wiki
258
258
  news_uri: https://www.railsbling.com/tags/auth-sanitizer
@@ -260,8 +260,7 @@ metadata:
260
260
  rubygems_mfa_required: 'true'
261
261
  rdoc_options:
262
262
  - "--title"
263
- - "auth-sanitizer - \U0001F372 TODO: Write a short summary, because RubyGems requires
264
- one."
263
+ - "auth-sanitizer - \U0001F7E5 Configurable KV output redaction"
265
264
  - "--main"
266
265
  - README.md
267
266
  - "--exclude"
@@ -284,5 +283,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
284
283
  requirements: []
285
284
  rubygems_version: 4.0.11
286
285
  specification_version: 4
287
- summary: "\U0001F372 TODO: Write a short summary, because RubyGems requires one."
286
+ summary: "\U0001F7E5 Configurable KV output redaction"
288
287
  test_files: []
metadata.gz.sig CHANGED
Binary file