Text exceeding maxlength will no longer be truncated when pasted in Firefox 77
fxsitecompat.dev
fxsitecompat.dev
function shorten(text, length)
const t = document.createElement('input')
t.maxlength = length
t.value = text
return t.value
} const shorten = (text, length) => text.substring(0, length);I even has the possibility to inspect the element and actually see what's going on.
Needs more Kubernetes and a service mesh.
function shorten(text, length) {
return new Promise((a, r) =>
fetch(`http://leftpad.io/shorten?l=${length}&v=${encodeURIComponent(text)}`).then(rx=>rx.text().then(a, r), r));
} $ host leftpad.io
Host leftpad.io not found: 3(NXDOMAIN)
i_do_not_know_what_i_expected.png> Constraint validation: If an element has a maximum allowed value length, its dirty value flag is true, its value was last changed by a user edit (as opposed to a change made by a script), and the code-unit length of the element’s value is greater than the element’s maximum allowed value length, then the element is suffering from being too long. > User agents may prevent the user from causing the element’s value to be set to a value whose code-unit length is greater than the element’s maximum allowed value length.
The key word, I think, is "may" in that user agents do not seem to be obligated to truncate text from what I can find in the standard.
While this does break the expectations from a developer point of view, I think it is perfectly in line with what users expect when they paste text. I think text falling off at the end after a paste with no explanation is more confusing than an the field glowing red with a message "you can only enter X characters here".
The old behaviour famously made people lose access to their PayPal account where the login form had a different maxlength as the registration form and where the password manager had put in a nice, long password. Preventing this sounds like a fine change for me, despite the compatibility break.
I also hope it will make at least some developers realise that client-side validation is a bad idea.
Big if, of course, but a man can dream...
>If the input element has a maximum allowed value length, then the length of the value of the element's value attribute must be equal to or less than the element's maximum allowed value length.
I'm a little bit confused, Which one should we follow?
[1] https://html.spec.whatwg.org/multipage/input.html#attr-input...
> A control's value is its internal state. As such, it might not match the user's current input.
The example goes on to describe cases where a browser might remove padding spaces from a field, or refuse to register (as a value) a text entry in a numeric field.
When it comes to password inputs, where you can't necessarily see what you're pasting, it's extremely important than the user knows when truncation occurs. But could that be achieved while still respecting maxlength? Yes, I think it would be decent UX to alert the user when they attempt to paste text that exceeds the maxlength, without actually completing the paste. That way, the input remains empty so there's no confusion about whether the full password or a truncated password has been entered, and the user can take appropriate action.
Your web app should also not engage with the password field as much as possible. Don’t make it a component, just leave it a password field. Don’t read it except to immediately send the contents to the server. Bonus points for just having that be a form submission.
- HTML spec allows it; says MAY, not MUST [3]
- Affects only user pastes, not javascript edits
- Affects all input boxes, not just password ones
- New preference editor.truncate_user_pastes can restore old behavior
As a developer, I personally find the inconsistent behavior of maxLength unintuitive and am surprised a potentially-breaking change like this didn't have more discussion (although, the original bug report was open for 4 years). But as a user, I have some empathy for the team's desire to fix "broken" websites (e.g. where the login page has a shorter limit than the account creation page or backend).[1] https://phabricator.services.mozilla.com/D71689
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1320229
[3] https://html.spec.whatwg.org/multipage/form-control-infrastr...
Or even better, some kind of warning when the paste happens, giving the user the option of truncating, canceling or continuing anyway?
[1] https://stackoverflow.com/questions/33080103/ios-safari-igno... [2] https://stackoverflow.com/questions/27319642/is-there-a-work...
Also many bcrypt implementations truncate input longer than 72 characters.
It should be though, the backend should reject overlong passwords, and the frontend should have such limits as well.
Though by "overlong" I mean kbyte range, not 32 character. The point of the limitation is to avoid randos feeding megabytes of data into your KDF and DOSing your server.
> Also many bcrypt implementations truncate input longer than 72 characters.
The alternative would be to error as bcrypt works on 18 words (of 32 bits). You need special handling (pre-hashing with a non-broken cryptographic hash function) to fix this issue.
Also it's 72 bytes not characters. And your pre-hash needs to generate some sort of textual representation (hex, base64, base85, …), as bcrypt will also truncate at the first NUL byte.
The original paper actually specifies 56 bytes.
> The point of the limitation is to avoid randos feeding megabytes of data into your KDF and DOSing your server.
You shouldn't be using a KDF that takes significantly longer when the password gets bigger. If you make that mistake, even a kilobyte is going to be annoyingly slow. If you don't make that mistake, then even MAX_POST_SIZE passwords won't DOS you.
Your KDF necessarily takes longer when the password gets longer as it's a hash function and thus O(n).
For typical password sizes (typically under 64 bytes), you're below the hash's blocksize so the effect is nil and you can treat it as a constant but it will start coming into play as the size of the key and thus the number of blocks to feed into the hash increases.
If adding a megabyte of input causes the original megabyte to get hashed or otherwise processed once, then you pass the test.
If adding a megabyte of input causes the original megabyte to get fed into your algorithm 100000 times, then you fail the test.
If you're really paranoid about cryptography then reject it. If you're slightly less paranoid then pass it through SHA512 before bcrypting it. Never silently truncate a password.
In any case this doesn’t preclude client-side validation.
Two weeks later, an angry user (the only one with a 100-digit password) complains that they can't log in anymore. The guy is the company's best-paying customer; the boss is furious. The whole team goes on a wild goose chase for two days and nights just to find out what happened, as clearly there's nothing wrong with their code.
A few years later, a former colleague shares the episode on HN. As you read the comments, it dawns on you that the idiot antagonist of the story is you. In this moment, you are enlightened.
If you switch to a different bcrypt implementation that does/does not truncate at 72 characters, the server-side truncation keeps all those 73 character passwords working.
If the server-side truncation were not in place, you'd get angry users.
But it's the same principle no matter where you cut. User thinks they can use an arbitrarily long password, puts a long but low entropy or easily guessable string at the front and makes up for it by having some good entropy at the end, and then you chop off the end.
> Lest a user submit a 50,000 character password?
What's wrong with that?
Edit: Hunh, apparently bcrypt only handles 72 chars anyways.
Exactly. You aren't storing those bytes.
> Maybe not an issue for a 50k char password, but how about a 50 billion char password?
We're back to a place where the response to the question is another question, but it just ends up failing to give an answer, opting to just keep throwing out larger and larger numbers. My response: "Yeah, okay. How about it?" Why stop at 50 billion? 99 trillion, let's go there next. Again: why not?
Because 50 billion chars is over 46 GiB of data. There are natural consequences of very large payloads and limits that you're going to reach as a result of those consequences (e.g. being prohibitively expensive for the client to send in the first place, or it will max out the server's connectivity lifetimes for extant requests before the payload can be delivered). If "CPU utilization crosses threshold" is the real reason, then let that be the real reason—and let the safeguards you have in place for handling those problems do their jobs. And if "we cap passwords to X chars" is your safeguard, then you have bigger problems.
To me, this feels a bit like passing the buck.
If you want to test your backend with 50-billion-character passwords as a safeguard in case things get screwy, that makes sense to me! But, has that test been done? Are you sure?
I see this as analogous to the concept of "defense in depth". Safeguarding against very weird edge-cases which do not provide utility to anyone is a good idea. If you assume the other part of the chain can deal with it, and you're wrong, things blow up. If you assume the worst, all will be well regardless.
[1] To that point, most people want to spend time on useless optimizations like truncating a password when they should be spending time reducing the size of their images, making sure requests are gzipped, or reducing their obscenely complex front-end bundle. It's just that most of those optimizations which are useful, only make you feel stupid for not implementing them sooner because they're obvious and easy, while truncating a password feels like YOU outsmarted something (when in fact you didn't)
More importantly though, a 50k character password is barely more secure than a 20 character one, but it gives the user a false sense of security. Passwords are inherently flawed and we shouldn't kid ourselves that just making them longer makes a difference.
If you're in a situation that calls for a 2^400 keyspace, you probably shouldn't be using passwords anyways.
You're probably thinking 50MB. Hashing 50kB should be almost instantaneous.
That being said, I just ran a very simple test with just sha256sum and broke 0.3s only at 32MiB, so either crypt() is doing much more than I tought (is salting _that_ expensive?) or I am reading that post completely wrong.
It should give you much more than that, considering that the green (SHA256) graph hits almost 0.1s at just 1000 bytes of input.
>either crypt() is doing much more than I tought (is salting _that_ expensive?)
glibc crypt() is probably doing more than you thought, but it's not salting: in SHA256 mode, various combinations of the key and intermediate hash digests are repeatedly hashed in a certain pattern for 5000 times, although the number of rounds can be changed just like the hashing algorithm. (This is a glibc implementation detail; not all crypt() implementations support extensions like SHA256 mode.)
In general, all general purpose cryptographic hash functions are reasonably fast.
Thanks for the info on what crypt() actually does. I definitely need to look into that some more...
I welcome responses explaining why passwords of hundreds of characters would ever be necessary or useful.
So long as you're using a password manager that generates unique passwords for every site you visit, there's no real reason to have those generated passwords be particularly long. Ten random characters (with enforced complexity rules) is more than ample for any normal, plausible scenario. If you're a high value individual, you might want to eliminate any doubt and use 12–15 characters. Exceeding that is security masturbation—but also lacks any downside so long as you never have to transcribe it.
Or if you fear worldwide retribution, 20 characters is enough to withstand all compute power on earth suddenly dedicated to the task of cracking your Spotify password.
The only scenario I can imagine where the length of random+unique passwords matters AT ALL is if (1) the website uses a very weak/naive password hash implementation (2) a hacker manages to acquire a copy of your hashed password and (3) the account is of sufficiently high value to justify a large investment in computing resources to brute force the hash. Hitting that trifecta is very unlikely indeed.
Seems like win/win for everyone. In-spec, less confusing for users, and doesn't change behavior for normal form submissions (JS submitters are clearly opting out of browser safety nets).
I've been setting maxlength to generous values on my fields in applications since I started coding HTML, if now suddenly I have to revisit everything and add JavaScript magic to check form validity where previously the page was completely free of JS, well, I think I'd frankly refuse where possible and tell people to complain to their faulty implementation.
Edit: Yes, indeed:
> The form cannot be submitted until the user fixes the error, so the server shouldn’t receive an excessively long text
Thanks for pointing that out!
I'm well aware of the risks in client-side validation, but indeed, as I see in my job often enough (I'm a security consultant), it's a valid remark that not everyone has taken to heart quite yet so thanks for the comment :)
What century are Mozilla living in? Most, even simple forms, don't use <form> elements and submit buttons anymore, they're all aJax. Therefore this workaround will be commonly bypassed.
People can debate if this is a good or bad thing, but ultimately the problem remains: This change will cause unexpected behavior when maxlength-ed stuff no longer obeys on thousands of popular websites.
Even if sites check it server-side, that doesn't mean the user experience isn't substantially degraded relative to obeying HTML standards.
Their justification for this change is nonsensical too:
> This change mainly aims at preventing an unexpectedly truncated password from being saved.
So why not limit it to input type=password? Heck why include textareas in this change, who is using a textarea for a password box?!
> No putting them in a form also breaks accessibility
Nope. Screen readers have no concept of <form> fields, nor any concept of how the piping works below the surface when a <button> is pressed. I run a screen reader every single day.
Their justification for this change is the only user-win (password truncation), and they could have trivially restricted this to passwords then body is hurt.
https://dev.to/addyosmani/accessibility-tips-for-web-develop...
If you have an article that does explain your argument, please link it.
> Also at least for me its a lot better to use the built in form validation then creating your own.
This change removes that very validation.
How? The form can't be submitted until it's fixed.
>The form cannot be submitted until the user fixes the error [...]. The user will typically see a red border around the text field along with a validation message [...]
Even for this site, why is Mozilla not limiting this breaking change designed to fix password fields to: Password fields. They haven't described why type=text or even textarea should be non-standard, only why type=password should be.
If they limited this to password fields, I'd have no issue. But per the code change they did not.
If the change really does get bypassed by everyone, that only underlines the sad state of modern website design relying completely on javascript.
I'm not sure why they don't limit this to just passwords but I can imagine it's easier to change the behaviour for all form elements than it is to change the behaviour of just password fields.
You don't even need to use "the proper form validation API". It's as simple as changing your ajax call from an onclick (on the submit button) to an onsubmit (on the form).
I do consider using the HTML5 form validation to be the proper validation API. Browser can do a lot without javascript and relying on their default behaviour is still making use of the validation API.
I do think that people generally overlook the built-in form validation though, and I like to use them as a fallback for Javascriptless environments to ensure everyone can get proper validation.
> This change will cause unexpected behavior when maxlength-ed stuff no longer obeys on thousands of popular websites.
Does nobody or "thousands of popular websites" use <form>? Which one is it?