4

Reading how Spotify was normalizing unicode inconsistently, and now I'm questioning if I am overlooking any issue on accepting non-normalized usernames.

From what I can tell, lowercase was first used on unix because users had to log in from systems that could either send everything in uppercase or everything in lowercase. The system normalized for this cross-compatibility then.

Nowadays I assume that the reduction in security (easier to guess usernames, risk of bugs like the above) was valid for how it prevents against impersonations (e.g. @me vs @Me) --probably also with a largely insignificant ease-of-sign-in for the 2 people who happen to press caps lock in their lifetime)

I did opt to not normalize and to allow unicode because I want international users to be called, even by the system, by whatever they choose. And because if someone abuses the uppercase to impersonate, well, I believe in user complaints and easy-to-generate reports before I would block some action that might have a valid use-case, small as it may be.

But now I am thinking. Is there any security advantage to normalizing username in lowercase that I am missing? (or any accessibility issue for people on other scripts?)

1 Answer 1

1

Is there any security advantage to normalizing username in lowercase that I am missing?

If you choose to do normalization, especially when using those values for some authentication process, then the process must be unambiguous.

  1. The normalization output of an input must have only one possible result (If you normalize "Bob" on your machine on Monday, that should have the same result on Tuesday using Susan's machine).

  2. Each possible representation for an entity / user must map to a unique result (If Bob Bogart's username is "BobB", and Bobby's username is "Bobb" then they should not have the same result after normalization). To make this true, a simple forced-casing type of normalization would not work.

  3. For each possible representation, each possible entity / user must have a unique address from all other entities (If I want to find Bobby in the system, and either Bobby's username, "Bobb", or email address, "[email protected]", are used to uniquely represent Bobby, then only using either Bobby's unique username or email address will lead to Bobby's data in the system).

  4. User inputs must be sanitized so that processing inputs doesn't get the system to behave in unintended and harmful ways (Zander's username should probably not be allowed to be "echo zanderrr && sudo rm -rf '/'").

Satisfying these requirements makes it difficult to be flexible. Although there's plenty of valid use-cases for all kinds of monikers, it can be a point of confusion and vulnerability. Every part of the system must to be able to distinguish the difference between distinct users. Any ambiguity and unnecessary complexity should be avoided. Being strict about possible usernames makes it easier to ensure everything in the system remains consistent and safe.


any accessibility issue for people on other scripts?

Enforcing uniqueness under forced-casing would still allow for Unicode characters and other languages. So, that shouldn't impact accessibility. Though, it may be a challenge to make a script which understands how casing works in each language / character set. Write lots of tests for each language, or use a library which already understands that kind of context.

Similarly for input sanitization, it's probably best to use a library which is well vetted to do the job. In either case, make sure the sanitization doesn't violate the other requirements [1-3].


if someone abuses the uppercase to impersonate, well, I believe in user complaints

User complaints could be helpful. But they shouldn't be relied upon for the internal security of the system. It's likely they don't even know how the internals work. The system should be secure even in the absence of user feedback. So, ensure new usernames don't collide with existing usernames under any combinations of normalization / sanitization techniques used by your system.


Conclusion:

Normalization of usernames does help with security. When done correctly, it mitigates canonicalization attacks (and other exploitable confusion), e.g. prevents ambiguous internal representations by bundling similar inputs, and mapping those bundles to unique and unambiguous internal representations. Sanitization is also critical. Though, normalization and sanitization should not interfere with each other's goals.

Without normalization & sanitization, a lot of faith is put into the defenses of other parts of a system, along with all the things which interface with it. Everything in an ecosystem handling such data needs to be immune to command injection, and avoid doing their own normalizations, lest they wind up altering the intended entities referred to. On the other hand, if the sanitization and normalization happens upon entering the system, then all of the other internals can be reasonably assured that they're handling safe, constant, and unambiguous data.

4
  • thanks! that was very complete. But i was asking on the other direction. Understand all the requirements and caveats of sanitization (don't agree with denying user name rm -fr / tho)... and i will outright avoid all that by not normalizing. My question is more in lines if normalizing DO HELP prevent some security issue other than impersonation... and if normalization helps people on other scripts access their account from machines without full i18n support for example.
    – gcb
    Aug 21, 2023 at 14:55
  • @gcb don't agree with denying user name 'rm -fr /' tho. Yikes! I think you should read the answer again and follow the linked resources. I say that because the answer clearly states why normalization is important to security. I added a conclusion to hopefully make that clearer. It's not clear what platforms your users will have access to. Answering the question of whether or not their access-points will support localizations of other users is out of scope of the question.
    – aiootp
    Aug 21, 2023 at 15:20
  • thanks again. I'm still unsure how that explain it. you did an awesome job of explaining how to do normalization right and the caveats and pitfalls. but again, all that is also avoided by not-normalizing (and trusting validation on input/encoding on output). Even things like canonicalization and confused-deputy attacks are only possible if you do normalization wrong.
    – gcb
    Aug 22, 2023 at 15:35
  • 1
    @gcb That's a good point, something which I did not make clear in the post. The only thing I can say to that is without normalization & sanitization: you're putting a lot of faith in the defenses of other parts of your system, and other systems that interface with it. Everything in the ecosystem which passes that information around needs to be immune to command injection. And, they all need to avoid doing normalization. If it's sanitized and normalized upon entering the system, then all of the other internals know they're handling safe, constant, and unambiguous data.
    – aiootp
    Aug 22, 2023 at 16:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .