auth-sanitizer 0.1.0 → 0.1.1
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +14 -1
- data/README.md +257 -0
- data/REEK +1 -2
- data/lib/auth/sanitizer/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 82404648ebaf0dca9ca6fe3862f28a9a40ecb19a28c40490acede95d4a99b457
|
|
4
|
+
data.tar.gz: 67be7cc8612f8802b948083a02f7970b0cb86832cee7ac0b1827e15364f6c189
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e306278d81c5b98b0d2611faf13afa198dec6847207a4f29fecbc0d1b8af55e2b4e917b37bce1a29d5f0f930f60dad979d80b36fd389a89d5703e671142d1cf
|
|
7
|
+
data.tar.gz: 14829bc1a17358726e62948e47b900d9ed02e222c73433f3b65cd98d9131e0202a11b3810b7864175bb82ac3e83303666cbcd80cd085b25a27ddc12c0e0351d9
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,17 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [0.1.1] - 2026-05-15
|
|
34
|
+
|
|
35
|
+
- TAG: [v0.1.1][0.1.1t]
|
|
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
|
+
- Usage documentation in README.md
|
|
43
|
+
|
|
33
44
|
## [0.1.0] - 2026-05-15
|
|
34
45
|
|
|
35
46
|
- TAG: [v0.1.0][0.1.0t]
|
|
@@ -41,6 +52,8 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
41
52
|
|
|
42
53
|
- Initial release
|
|
43
54
|
|
|
44
|
-
[Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.
|
|
55
|
+
[Unreleased]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.1...HEAD
|
|
56
|
+
[0.1.1]: https://github.com//ruby-oauth/auth-sanitizer/compare/v0.1.0...v0.1.1
|
|
57
|
+
[0.1.1t]: https://github.com//ruby-oauth/auth-sanitizer/releases/tag/v0.1.1
|
|
45
58
|
[0.1.0]: https://github.com/ruby-oauth/auth-sanitizer/compare/21d6165dca7eef8e7b9bb01fdfc4cc8bab4e5b96...v0.1.0
|
|
46
59
|
[0.1.0t]: https://github.com/ruby-oauth/auth-sanitizer/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -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.
|
data/REEK
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Error: No such file - empty
|
|
1
|
+
reek is empty
|
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.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -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.
|
|
253
|
-
changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.
|
|
252
|
+
source_code_uri: https://github.com/ruby-oauth/auth-sanitizer/tree/v0.1.1
|
|
253
|
+
changelog_uri: https://github.com/ruby-oauth/auth-sanitizer/blob/v0.1.1/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.
|
|
255
|
+
documentation_uri: https://www.rubydoc.info/gems/auth-sanitizer/0.1.1
|
|
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
|
metadata.gz.sig
CHANGED
|
Binary file
|