Skip to content

Commit 1d55cb1

Browse files
fix: redact sensitive auth failure logs
1 parent 19ccba1 commit 1d55cb1

2 files changed

Lines changed: 57 additions & 2 deletions

File tree

‎src/booru/services/booru-auth-manager.service.spec.ts‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,39 @@ describe('BooruAuthManagerService', () => {
115115
expect(loggedMessage).toContain('auth_user=REDACTED')
116116
expect(loggedMessage).toContain('auth_pass=REDACTED')
117117
expect(loggedMessage).not.toContain('auth_pass=secret123')
118+
expect(loggedMessage).not.toContain('www-gel-user')
119+
120+
errorSpy.mockRestore()
121+
warnSpy.mockRestore()
122+
})
123+
124+
it('should redact sensitive key=value pairs outside of URLs in auth failure logs',()=>{
125+
consterrorSpy=jest.spyOn(console,'error').mockImplementation(()=>undefined)
126+
constwarnSpy=jest.spyOn(console,'warn').mockImplementation(()=>undefined)
127+
128+
service.reportAuthFailure({
129+
domain: 'https://www.gelbooru.com/index.php?page=dapi',
130+
user: 'www-gel-user',
131+
password: 'www-gel-pass',
132+
error:
133+
'HTTP 403: Forbidden auth_user=www-gel-user auth_pass=secret123 token=abc123 api_key=xyz789 user_id=42 key=plain-key limit=10',
134+
timestamp: newDate()
135+
})
136+
137+
constloggedMessage=errorSpy.mock.calls[0][0]
138+
139+
expect(loggedMessage).toContain('auth_user=REDACTED')
140+
expect(loggedMessage).toContain('auth_pass=REDACTED')
141+
expect(loggedMessage).toContain('token=REDACTED')
142+
expect(loggedMessage).toContain('api_key=REDACTED')
143+
expect(loggedMessage).toContain('user_id=REDACTED')
144+
expect(loggedMessage).toContain('key=REDACTED')
145+
expect(loggedMessage).toContain('limit=10')
146+
expect(loggedMessage).not.toContain('www-gel-user')
147+
expect(loggedMessage).not.toContain('secret123')
148+
expect(loggedMessage).not.toContain('abc123')
149+
expect(loggedMessage).not.toContain('xyz789')
150+
expect(loggedMessage).not.toContain('plain-key')
118151

119152
errorSpy.mockRestore()
120153
warnSpy.mockRestore()

‎src/booru/services/booru-auth-manager.service.ts‎

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export class BooruAuthManagerService implements OnModuleInit {
9393
publicreportAuthFailure(authFailure: AuthFailureEvent): void{
9494
constnormalizedDomain=this.normalizeDomain(authFailure.domain)
9595
constsanitizedError=this.sanitizeErrorMessage(authFailure.error)
96+
constsanitizedUser=this.sanitizeUserIdentifier(authFailure.user)
9697

9798
if(this.isCredentialDisabled(normalizedDomain,authFailure.user,authFailure.password)){
9899
return
@@ -110,7 +111,7 @@ export class BooruAuthManagerService implements OnModuleInit {
110111
this.broadcastDisabledCredential(disabledCredential)
111112

112113
conststats=this.getDomainStats(normalizedDomain)
113-
console.error(`❌ Auth failure for ${normalizedDomain}:${authFailure.user} - ${sanitizedError}`)
114+
console.error(`❌ Auth failure for ${normalizedDomain}:${sanitizedUser} - ${sanitizedError}`)
114115
console.warn(
115116
`📊 ${normalizedDomain} credentials: ${stats.available}/${stats.total} available, ${stats.disabled} disabled`
116117
)
@@ -222,7 +223,28 @@ export class BooruAuthManagerService implements OnModuleInit {
222223
}
223224

224225
consturlPattern=/https?:\/\/[^\s]+/gi
225-
returnmessage.replace(urlPattern,(url)=>this.sanitizeUrl(url))
226+
constsanitizedUrlMessage=message.replace(urlPattern,(url)=>this.sanitizeUrl(url))
227+
returnthis.sanitizeKeyValueTokens(sanitizedUrlMessage)
228+
}
229+
230+
privatesanitizeUserIdentifier(user: string): string{
231+
if(!user){
232+
return'REDACTED'
233+
}
234+
235+
return`REDACTED(${user.length})`
236+
}
237+
238+
privatesanitizeKeyValueTokens(message: string): string{
239+
letsanitizedMessage=message
240+
241+
for(constkeyofthis.sensitiveParams){
242+
constescapedKey=key.replace(/[.*+?^${}()|[\]\\]/g,'\\$&')
243+
constpattern=newRegExp(`\\b(${escapedKey})(\\s*=\\s*)([^\\s&#,;\\]\\)\\}]+)`,'gi')
244+
sanitizedMessage=sanitizedMessage.replace(pattern,'$1$2REDACTED')
245+
}
246+
247+
returnsanitizedMessage
226248
}
227249

228250
privatesanitizeUrl(url: string): string{

0 commit comments

Comments
 (0)