Hacker News new | ask | show | jobs
by oblosys 3038 days ago
If you use React, updating the value on every change is a very common pattern.
4 comments

This is speculative as I haven't tested out this vulnerability or attempted to avoid it (yet), but I imagine this means it would be a good idea to make password fields "uncontrolled"[1] if you're using react.

1: https://reactjs.org/docs/uncontrolled-components.html

That seems reasonable.

The apps I've worked on weren't full SPAs, so I just used plain HTML for the login form.

One option is to make the input component uncontrolled by removing the value={this.state.password} prop, but keeping the onChange handler to maintain the password in the state for validation & strength checking. Typically, the only time you need to programmatically change a password field is when clearing it, which can be done by setting the DOM attribute directly.
Or just use correctly defined CSP
I hadn't realized a CSP could protect against this sort of thing. Thanks for the tip!
Hopefully most are updating the property and not the attribute.
For those that are confused, updating the property would mean:

  this.input.value = 'password'; 
This would be fine. However updating the attribute (the way React recommends it with controlled components) would be something like:

  <input type="text" value={this.state.value} onChange={this.handleChange} />
This would be vulnerable to the the CSS keylogger.
That being said, you might be thinking about this incorrectly if you're doing this.

You can use a form and grab the values on submission.

    <form onSubmit={this.handleSubmission}>
      <input type="password" name="password" />
    </form>

    this.handleSubmission = event => {
      // access to event.target.password.value
    }
You still lose things like validation on blur and displaying real-time password strength.
It might be a fair workaround, but it sucks to regress to storing truth in the DOM.
I believe using `defaultValue` instead of `value` would be an appropriate remediation.
Do you mind expanding on this a little? Or linking to a documentation or something
I think he/she essentially means using an uncontrolled input instead of a controlled one.

https://reactjs.org/docs/uncontrolled-components.html#defaul...

Thanks!
It updates the attribute, you can see this pretty easily by going to the Instagram website. If you inspect the password field in the browser, when you type in a value you can see it reflected on the `value` attribute of the input element.
But that requires extra work, compared to simple JSX-based React code, doesn't it?
Maybe they will have to rethink it. It seemed odd when they introduced it and at least in the early React version kept making problems e.g. when entering German Umlaute on US keyboards. Not working much on Frontend anymore but when I do inputs, I only use uncontrolled ones - it's much less hassle and more flexible anyways.
So with frameworks like React/Vue, every change to a field generates a request? Or are those handled locally in the shadow dom?
The pattern is to handle form fields locally in the browser as part of the application state.

Basically, the value of the input is tied to a "state engine" that acts as a single source of truth and when the user types in the input you'll update the state so that the rest of the application can know what's going on in the form without accessing the DOM.

The state engine is a fancy word for a variable that has a special setter function so that the changes can be reflected globally.

Can’t speak about Vue, but that’s pretty much the recommended pattern for most input fields in React. But, as others have commented, it might be prudent to leave password inputs completely uncontrolled, i.e. let the browser do its normal thing for updating the DOM based on user input.
Unfortunately, that’s very inconvenient with React because you’ll have to start thinking about dom elements lifecycle separately of the react app lifecycle.
Definitely. It’s going to be a struggle to implement things like password confirmation validation or a real-time password strength indicator.
Technically yes. You can see it in the network panel.
Not at all. Sending off requests is a different thing entirely to controlled inputs, and you don't need a controlled input to do a request every keypress.
Damn you're right. Thanks!