Keepassxc-browser: Encapsulate `<div id="kpxcAutocomplete-list" ...>` in shadow DOM for privacy!

Created on 31 Aug 2019  路  8Comments  路  Source: keepassxreboot/keepassxc-browser

Expected Behavior


The DOM tree that is added to a page and that contains the list of accounts you can log in with (<div id="kpxcAutocomplete-list" ...>, anything else?) should be hidden from the page's code, so it can't be read out.

Current Behavior


Currently, a website can see all your accounts for that website by simply reading the DOM and connect the dots, which is a major privacy concern, especially in Tor Browser which has a function to renew your identity from the website's point of view.

Possible Solution


The DOM additions of this software can be hidden with a shadow DOM. See MDN article "Using shadow DOM".

The shadow host should be completely anonymous without any kpxc or something like that, so that not even the information is available that KeePassXC is used. In case an id is somehow necessary on the shadow host as a contrast to the page's regular DOM, maybe a random string would be best, in a format that other browser plugins could adopt (for obfuscation).

In case support for older browsers without shadow DOM support is provided, there should be a warning that the website will be able to see the fields "Title" and "Username" of all your account entries.

Debug info


KeePassXC - 2.4.3
KeePassXC-Browser - 1.4.7
Operating system: Win 10
Browser: Firefox Developer Edition

PR pending feature request security

Most helpful comment

I tried this with a local site overriding the prototype. The mode still stayed closed when using attachShadow from the extension. And to make sure, you can also override the prototype in the extension code. Not sure what happens if the page triggers that override after the extension (using a timer). Gotta try that one too.

All 8 comments

It's true that autocomplete writes usernames to the DOM, but it should be noted that your passwords are never visible anywhere, if someone is concerned. Using Shadow DOM would be a nice addition indeed.

As a workaround, you can disable the Autocomplete menu from the extension settings and use the extension popup for filling the credentials. Then DOM should be clean.

After reading some more about the Shadow DOM, it seems it doesn't really give much more protection to the data inserted to DOM. Shadow DOM can also be read by the main page. For example, using the following before anything is inserted to Shadow DOM could cause some leaks:

Element.prototype._attachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function () {
    return this._attachShadow( { mode: "open" } );
};

EDIT: I could inspect if I can override the same prototype in the extension to use 'closed' every time, and does it override the page's own script or not.

Tried it. Seems to work quite nicely. One benefit for Shadow DOM is that the content script CSS doesn't collide with page's own stylesheet. And that is very nice. No need for any additional !important stuff.

Yeah, { mode: "closed" } seems to be obligatory for this purpose.

Am I right that your code now also protects against website code that replaces Element.prototype.attachShadow for spying by saving the original attachShadow earlier than a website can do it? Otherwise, the mode could even be changed from "closed" to "open".

I tried this with a local site overriding the prototype. The mode still stayed closed when using attachShadow from the extension. And to make sure, you can also override the prototype in the extension code. Not sure what happens if the page triggers that override after the extension (using a timer). Gotta try that one too.

Here's a branch for Shadow DOM feature: https://github.com/keepassxreboot/keepassxc-browser/tree/feature/shadow_dom

Feel free to test it.

Thank you very much. I tested it and the protection of the list of usernames works very well; no JS access from outside. Logging in also still works.

<div>
    <!--
    This is the element containing: <div class="kpxc kpxc-username-icon ..." ...>
    -->
</div>
<div class="kpxc">
    <!--
    This is the element containing: <div id="kpxcAutocomplete-list" ...>
    -->
</div>

Do you think class="kpxc" is really necessary? The KeePassXC icon in the username textbox seems to be fine without it (just <div>). It increases fingerprintability.

@h-h-h-h The class is not necessary. As you can see, I didn't use it later at all. The branch still needs some small fixes, so I'll fix that issue too.

I'm more curious about hacking this feature. I couldn't access the elements added to Shadow DOM even if I overwrote the attachShadow in the page script. The extension also overrides it, and always calls it with closed mode.

Was this page helpful?
0 / 5 - 0 ratings