Browser Forms Autofill
Websites are providing a huge variety of services. Frequently, those services requires the personal data of the user. Those personal data could be the personal address, the credit card data, the credentials, etc. Browsers has identified that procedure and are trying to autofill those data. Ofcourse, in order to autofill those fields, the browser has to address 2 issues.
- Identify correctly witch of the fields are personal data and the category that they belong.
- Store those data safely.
Need to Prevent the Autofill
There are many cases that we want to prevent the browser from keeping the personal data. This is something very important for security-related applications. For some reason, browsers does not commonly support a ‘no track’ policy. Consequently, we are trying to hack our html in order to confuse the browser and prevent it from storing credentials.
How does the Browser Recognize the Fields
In order to confuse the autofill functionality, we have to investigate on how the browser works. The browser runs some heuristic algorithms inside form
elements, once, during the initialization. Those algorithms are trying to identify the form structure. Key variables for the algorithms are:
- Input field type, (password)
- Input field names, placeholders, ids (credit-card, password, username)
- Label names,
for
attribute - Sibling correlation
Autocomplete Solution
There is an official documentation from MDN that provides a solution to turn off the autofill functionality.
<form method="post" action="/form" autocomplete="off">
[…]
</form>
The problem with this solution is that modern browsers and password management extensions ignores the autocomplete="off"
parameter. Hence, in most of the cases it is useless.
Proposal
When we study how browsers are trying to recognize the fields, we can draw some conclusions. We can modify the type attribute of the fields and the names before the initialization. After the initialization, we can revert them on the real state. For example, we can change the type='password'
to type='text'
before the form initialization, and later revert the password type.
A minor issue is that browser does not provide any feedback about the html loading state. Thus, we are trying to develop a way to catch the form initialization event. An easy solution is to set a timeout with an acceptable interval, (200 ms). This solution is fine but it cannot guarantee that the form has been loaded.
We observe that we want to change the password type when the user strokes on the password field. Thus, we can somehow change the field on an event like onFocus
I tried the following and it seems that works to any browser:
<input id="passfld" type="text" autocomplete="off" />
<script type="text/javascript">
$(function(){
var passElem = $('#passfld');
passElem.one('focus', function() {
passElem.prop('type', 'password');
});
});
</script>
This way is much more safer than using timeout techniques, because it guaranties that the input field will yield to password when the user focuses it.
In more complicated cases a heavier hack is probably required. A ‘hack’ could be for instance, the modification of the input’s name
field.