Repository navigation
Conversation
The fill script set both the value attribute and the value property. The attribute ends up in the serialised DOM, where a CSS attribute selector can read the password back character by character. Only the property is needed to fill the field.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The action extension fills a login form by writing the decrypted password to
both the
valuecontent attribute and thevalueIDL property(
passExtension/passProcessor.js:31and:32, and the same pair for the username at
:41and:42). Only the property is read when the form issubmitted. The attribute is part of the serialised DOM, so after a fill the
page markup contains the plaintext password, and a CSS attribute selector can
match on it one character at a time.
Why
The value the extension hands over is the decrypted secret itself
(
passExtension/Services/CredentialProvider.swift:48). Writing it to theattribute adds nothing:
element.value = ...sets what the browser submits andwhat scripts read, which is why the next two lines dispatch
inputandchangeon the element.How
The two
setAttribute('value', ...)calls are removed. The propertyassignments and the event dispatch are unchanged, so the fill behaves the same
for the page and for any framework listening on those events.
Testing
The repository has no JavaScript test setup, so no test file was added.
The script was exercised under jsdom against a form with a text and a password
input. With the current script the serialised body contains
value="<password>"and an attribute selector matches it. With the change thepassword is absent from the markup,
input.valuestill carries it, bothinputandchangestill fire on both elements, and the password field has novalueattribute at all.The iOS test suite was not run, this host has no macOS toolchain.
References
GHSA-gxf7-ph6f-4fg6 (reported privately, unpublished at time of writing)
Found during a penetration test by turingpoint.