@@ -112,4 +112,134 @@ public void GivenTokenWithInvalidExpirationFormat_WhenValidated_ThenReturnsFalse
112112
113113 result . ShouldBeFalse ( ) ;
114114 }
115+
116+ [ Fact ]
117+ public void GivenTokenWithSignatureContainingNewline_WhenValidated_ThenSanitizesNewlineInLog ( )
118+ {
119+ // Create a token with an invalid signature containing a newline character
120+ const string maliciousSignature = "fake\n signature" ;
121+ var token =
122+ $ "r=http%3A%2F%2Flocalhost&e={ DateTimeOffset . UtcNow . AddMinutes ( 5 ) . ToUnixTimeSeconds ( ) } &s={ maliciousSignature } ";
123+ var headers = new HeaderDictionary { { Constants . AegSasTokenHeader , token } } ;
124+
125+ Validator . IsValid ( headers , ValidTopicKey ) ;
126+
127+ // Verify that the logger was called with the sanitized signature (\\n instead of \n)
128+ Logger
129+ . Received ( )
130+ . Log (
131+ LogLevel . Warning ,
132+ Arg . Any < EventId > ( ) ,
133+ Arg . Is < object > ( o =>
134+ ( o . ToString ( ) ?? "" ) . Contains ( "fake\\ nsignature" )
135+ && ! ( o . ToString ( ) ?? "" ) . Contains ( "fake\n signature" )
136+ ) ,
137+ Arg . Any < Exception ? > ( ) ,
138+ Arg . Any < Func < object , Exception ? , string > > ( )
139+ ) ;
140+ }
141+
142+ [ Fact ]
143+ public void GivenTokenWithSignatureContainingCarriageReturn_WhenValidated_ThenSanitizesCarriageReturnInLog ( )
144+ {
145+ // Create a token with an invalid signature containing a carriage return character
146+ const string maliciousSignature = "fake\r signature" ;
147+ var token =
148+ $ "r=http%3A%2F%2Flocalhost&e={ DateTimeOffset . UtcNow . AddMinutes ( 5 ) . ToUnixTimeSeconds ( ) } &s={ maliciousSignature } ";
149+ var headers = new HeaderDictionary { { Constants . AegSasTokenHeader , token } } ;
150+
151+ Validator . IsValid ( headers , ValidTopicKey ) ;
152+
153+ // Verify that the logger was called with the sanitized signature (\\r instead of \r)
154+ Logger
155+ . Received ( )
156+ . Log (
157+ LogLevel . Warning ,
158+ Arg . Any < EventId > ( ) ,
159+ Arg . Is < object > ( o =>
160+ ( o . ToString ( ) ?? "" ) . Contains ( "fake\\ rsignature" )
161+ && ! ( o . ToString ( ) ?? "" ) . Contains ( "fake\r signature" )
162+ ) ,
163+ Arg . Any < Exception ? > ( ) ,
164+ Arg . Any < Func < object , Exception ? , string > > ( )
165+ ) ;
166+ }
167+
168+ [ Fact ]
169+ public void GivenTokenWithSignatureContainingTab_WhenValidated_ThenSanitizesTabInLog ( )
170+ {
171+ // Create a token with an invalid signature containing a tab character
172+ const string maliciousSignature = "fake\t signature" ;
173+ var token =
174+ $ "r=http%3A%2F%2Flocalhost&e={ DateTimeOffset . UtcNow . AddMinutes ( 5 ) . ToUnixTimeSeconds ( ) } &s={ maliciousSignature } ";
175+ var headers = new HeaderDictionary { { Constants . AegSasTokenHeader , token } } ;
176+
177+ Validator . IsValid ( headers , ValidTopicKey ) ;
178+
179+ // Verify that the logger was called with the sanitized signature (\\t instead of \t)
180+ Logger
181+ . Received ( )
182+ . Log (
183+ LogLevel . Warning ,
184+ Arg . Any < EventId > ( ) ,
185+ Arg . Is < object > ( o =>
186+ ( o . ToString ( ) ?? "" ) . Contains ( "fake\\ tsignature" )
187+ && ! ( o . ToString ( ) ?? "" ) . Contains ( "fake\t signature" )
188+ ) ,
189+ Arg . Any < Exception ? > ( ) ,
190+ Arg . Any < Func < object , Exception ? , string > > ( )
191+ ) ;
192+ }
193+
194+ [ Fact ]
195+ public void GivenTokenWithSignatureContainingMultipleControlCharacters_WhenValidated_ThenSanitizesAllControlCharactersInLog ( )
196+ {
197+ // Create a token with an invalid signature containing multiple control characters
198+ const string maliciousSignature = "fake\n \r \t \0 signature" ;
199+ var token =
200+ $ "r=http%3A%2F%2Flocalhost&e={ DateTimeOffset . UtcNow . AddMinutes ( 5 ) . ToUnixTimeSeconds ( ) } &s={ maliciousSignature } ";
201+ var headers = new HeaderDictionary { { Constants . AegSasTokenHeader , token } } ;
202+
203+ Validator . IsValid ( headers , ValidTopicKey ) ;
204+
205+ // Verify that all control characters are sanitized
206+ Logger
207+ . Received ( )
208+ . Log (
209+ LogLevel . Warning ,
210+ Arg . Any < EventId > ( ) ,
211+ Arg . Is < object > ( o =>
212+ ( o . ToString ( ) ?? "" ) . Contains ( "fake\\ n\\ r\\ t\\ 0signature" )
213+ && ! ( o . ToString ( ) ?? "" ) . Contains ( "fake\n \r \t \0 signature" )
214+ ) ,
215+ Arg . Any < Exception ? > ( ) ,
216+ Arg . Any < Func < object , Exception ? , string > > ( )
217+ ) ;
218+ }
219+
220+ [ Fact ]
221+ public void GivenTokenWithSignatureContainingDelCharacter_WhenValidated_ThenSanitizesDelInLog ( )
222+ {
223+ // Create a token with an invalid signature containing the DEL character (ASCII 127)
224+ var maliciousSignature = $ "fake{ ( char ) 127 } signature";
225+ var token =
226+ $ "r=http%3A%2F%2Flocalhost&e={ DateTimeOffset . UtcNow . AddMinutes ( 5 ) . ToUnixTimeSeconds ( ) } &s={ maliciousSignature } ";
227+ var headers = new HeaderDictionary { { Constants . AegSasTokenHeader , token } } ;
228+
229+ Validator . IsValid ( headers , ValidTopicKey ) ;
230+
231+ // Verify that the DEL character is sanitized as \x7F
232+ Logger
233+ . Received ( )
234+ . Log (
235+ LogLevel . Warning ,
236+ Arg . Any < EventId > ( ) ,
237+ Arg . Is < object > ( o =>
238+ ( o . ToString ( ) ?? "" ) . Contains ( "fake\\ x7Fsignature" )
239+ && ! ( o . ToString ( ) ?? "" ) . Contains ( $ "fake{ ( char ) 127 } signature")
240+ ) ,
241+ Arg . Any < Exception ? > ( ) ,
242+ Arg . Any < Func < object , Exception ? , string > > ( )
243+ ) ;
244+ }
115245}
0 commit comments