-
-
Notifications
You must be signed in to change notification settings - Fork 226
fix: Redact Authorization header before sending events to Sentry #4164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
24037a1
fix: Never capture authorization headers (even if SendDefaultPii is t…
jamescrosswell 5825a24
Redact rather than skip Authorization headers
jamescrosswell bab48d3
Format code
getsentry-bot a47c989
Merge branch 'main' into exclude-auth-cookies
jamescrosswell fe4d9cb
Update RedactedHeaders.cs
jamescrosswell 3d62f93
Review feedback
jamescrosswell 5aef44f
Merge branch 'main' into exclude-auth-cookies
jamescrosswell f42a3a5
Update CHANGELOG.md
jamescrosswell File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| using Sentry.Internal.Extensions; | ||
|
|
||
| namespace Sentry.Internal; | ||
|
|
||
| internal class RedactedHeaders : IDictionary<string, string> | ||
| { | ||
| private static readonly string[] SensitiveKeys = ["Authorization", "Proxy-Authorization"]; | ||
|
|
||
| private readonly Dictionary<string, string> _inner = new(StringComparer.OrdinalIgnoreCase); | ||
|
|
||
| private static string Redact(string key, string value) => | ||
| SensitiveKeys.Contains(key, StringComparer.OrdinalIgnoreCase) ? "[Filtered]" : value; | ||
|
|
||
| public string this[string key] | ||
| { | ||
| get => _inner[key]; | ||
| set => _inner[key] = Redact(key, value); | ||
| } | ||
|
|
||
| public void Add(string key, string value) => _inner.Add(key, Redact(key, value)); | ||
|
|
||
| // Delegate rest to _inner | ||
| public bool ContainsKey(string key) => _inner.ContainsKey(key); | ||
| public bool Remove(string key) => _inner.Remove(key); | ||
| #if NET8_0_OR_GREATER | ||
| public bool TryGetValue(string key, [MaybeNullWhen(false)] out string value) => _inner.TryGetValue(key, out value); | ||
| #else | ||
| public bool TryGetValue(string key, out string value) => _inner.TryGetValue(key, out value); | ||
| #endif | ||
| public ICollection<string> Keys => _inner.Keys; | ||
| public ICollection<string> Values => _inner.Values; | ||
| public int Count => _inner.Count; | ||
| public bool IsReadOnly => false; | ||
|
|
||
| public void Add(KeyValuePair<string, string> item) => Add(item.Key, item.Value); | ||
| public void Clear() => _inner.Clear(); | ||
| public bool Contains(KeyValuePair<string, string> item) => _inner.Contains(item); | ||
| public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex) => | ||
| ((IDictionary<string, string>)_inner).CopyTo(array, arrayIndex); | ||
| public bool Remove(KeyValuePair<string, string> item) => _inner.Remove(item.Key); | ||
| public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => _inner.GetEnumerator(); | ||
| IEnumerator IEnumerable.GetEnumerator() => _inner.GetEnumerator(); | ||
|
|
||
| public static implicit operator RedactedHeaders(Dictionary<string, string> source) | ||
| { | ||
| var result = new RedactedHeaders(); | ||
| foreach (var kvp in source) | ||
| { | ||
| result[kvp.Key] = kvp.Value; // This will sanitize | ||
| } | ||
| return result; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| namespace Sentry.Tests.Internals; | ||
|
|
||
| public class RedactedHeadersTests | ||
| { | ||
| [Fact] | ||
| public void Add_WithAuthorizationKey_ShouldStoreFilteredValue() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| headers.Add("Authorization", "Bearer 123"); | ||
|
|
||
| // Assert | ||
| headers["Authorization"].Should().Be("[Filtered]"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void IndexerSet_WithAuthorizationKey_ShouldStoreFilteredValue() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| headers["Authorization"] = "Bearer 456"; | ||
|
|
||
| // Assert | ||
| headers["Authorization"].Should().Be("[Filtered]"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void Add_WithOtherKey_ShouldStoreOriginalValue() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| headers.Add("User-Agent", "TestAgent"); | ||
|
|
||
| // Assert | ||
| headers["User-Agent"].Should().Be("TestAgent"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void IndexerGet_WithMissingKey_ShouldThrowKeyNotFoundException() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| var act = () => _ = headers["Missing"]; | ||
|
|
||
| // Assert | ||
| act.Should().Throw<KeyNotFoundException>(); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryGetValue_WithExistingKey_ShouldReturnTrueAndValue() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders | ||
| { | ||
| ["Authorization"] = "secret" | ||
| }; | ||
|
|
||
| // Act | ||
| var success = headers.TryGetValue("Authorization", out var value); | ||
|
|
||
| // Assert | ||
| success.Should().BeTrue(); | ||
| value.Should().Be("[Filtered]"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void TryGetValue_WithMissingKey_ShouldReturnFalse() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| var success = headers.TryGetValue("Nonexistent", out var value); | ||
|
|
||
| // Assert | ||
| success.Should().BeFalse(); | ||
| value.Should().BeNull(); // nullable context may allow this | ||
| } | ||
|
|
||
| [Fact] | ||
| public void ImplicitConversion_FromDictionary_ShouldRedactAuthorization() | ||
| { | ||
| // Arrange | ||
| var dict = new Dictionary<string, string> | ||
| { | ||
| { "Authorization", "Token xyz" }, | ||
| { "Custom", "Value" } | ||
| }; | ||
|
|
||
| // Act | ||
| RedactedHeaders headers = dict; | ||
|
|
||
| // Assert | ||
| headers["Authorization"].Should().Be("[Filtered]"); | ||
| headers["Custom"].Should().Be("Value"); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void CaseInsensitiveKeyMatching_ShouldRedactAuthorization() | ||
| { | ||
| // Arrange | ||
| var headers = new RedactedHeaders(); | ||
|
|
||
| // Act | ||
| headers.Add("authorization", "should be filtered"); | ||
|
|
||
| // Assert | ||
| headers["AUTHORIZATION"].Should().Be("[Filtered]"); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could be a bit more aggressive there. The Python SDK redacts a bunch of headers.
See Potential suspects.