Implement sanitization of control characters in user input for hackerone (#32521)

GitOrigin-RevId: 859299da44b1c60220592c8f71a90536a5aa34a3
This commit is contained in:
Anna Claire Fields
2026-04-14 08:04:36 +00:00
committed by Copybot
parent 1a7de4ddd8
commit 2487b73962
5 changed files with 100 additions and 8 deletions
@@ -148,6 +148,30 @@ describe('AuthenticationManager', function () {
})
})
describe('when the password contains control characters', function () {
it('should escape control characters before comparing', async function (ctx) {
const { user } =
await ctx.AuthenticationManager.promises.authenticate(
{ email: ctx.email },
'test\u0000password',
null,
{ enforceHIBPCheck: false }
)
expect(user).to.equal(null)
})
it('should escape zero-width spaces before comparing', async function (ctx) {
const { user } =
await ctx.AuthenticationManager.promises.authenticate(
{ email: ctx.email },
'test\u200bpassword',
null,
{ enforceHIBPCheck: false }
)
expect(user).to.equal(null)
})
})
describe('when the encrypted passwords do not match', function () {
beforeEach(async function (ctx) {
;({ user: ctx.result } =
@@ -251,6 +275,42 @@ describe('AuthenticationManager', function () {
expect(hashedPassword.length).to.equal(60)
expect(hashedPassword).to.match(/^\$2a\$04\$[a-zA-Z0-9/.]{53}$/)
})
it('should escape control characters before hashing so login matches', async function (ctx) {
ctx.settings.passwordStrengthOptions = { allowAnyChars: true }
await ctx.AuthenticationManager.promises.setUserPasswordInV2(
ctx.user,
'test\u0000password'
)
const { hashedPassword } = ctx.db.users.updateOne.lastCall.args[1].$set
const matchEscaped = await bcrypt.compare(
'test\\u0000password',
hashedPassword
)
expect(matchEscaped).to.equal(true)
const matchRaw = await bcrypt.compare(
'test\u0000password',
hashedPassword
)
expect(matchRaw).to.equal(false)
})
it('should escape zero-width characters before hashing', async function (ctx) {
ctx.settings.passwordStrengthOptions = { allowAnyChars: true }
await ctx.AuthenticationManager.promises.setUserPasswordInV2(
ctx.user,
'test\u200bpassword'
)
const { hashedPassword } = ctx.db.users.updateOne.lastCall.args[1].$set
const matchEscaped = await bcrypt.compare(
'test\\u200bpassword',
hashedPassword
)
expect(matchEscaped).to.equal(true)
})
})
})