npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lavadome

v0.0.0

Published

Secure DOM trees isolation and encapsulation leveraging ShadowDOM

Downloads

2

Readme

⚠️ EXPERIMENTAL [WIP] - USE AT YOUR OWN RISK (learn more)

Usage

TBD

Develop

npm && npm install --global serve or yarn && yarn global add serve

Motivation

As of today, standards of the web do not offer a way to selectively isolate subtrees of the DOM from some parties while granting access to others in a secured manner when both parties share the same JavaScript execution environment.

In a world where we no longer trust the code in our app, even when is executed in the same origin we consider to be trustworthy, we need to be able to present the user with content we trust that other JavaScript code cannot compromise.

Example

At that stage, this sensitive content is attached to DOM and is fully accessible to all entities running in the same app.

So if some parts in the app are compromised, parts that don't have default access to the private key but do have access to the DOM, they could easily steal the private key from the DOM the minute it's being attached to it.

We believe this is solvable. Worth a shot.

Solution

In terms of successfully isolating DOM nodes,ShadowDOM technology comes very close to that, and although it isn't designed with security in mind, it does a pretty good job in isolating subtrees of the DOM from the rest of it.

Therefore, we believe leveraging ShadowDOM while carefully addressing potential security gaps, LavaDomEncapsulation should be a security tool to join the LavaMoat toolbox to allow developers to implement frontend-only components that will aspire to only allow their code and the user to access/interact with, while not allow similar access to other untrusted JavaScript code in the app.

Shout-out @arxenix for his research on ShadowDOM security on top of which important security principles were implemented in LavaDome

Goals

This project follows some core principles to successfully serve the main goals of LavaDome:

Secure

The most important part here is to make a secure solution, which is why we take ShadowDOM and wrap it with advanced security properties so that it's safe to present sensitive info in it.

Visit Security to learn more about this effort.

DX

We want to achieve as simple Developer Experience as possible by:

  1. Support as many popular frameworks (React, Angular, etc) as possible;
  2. Make the API as easy and simple and easy to use as possible.

Read - not write

At this stage, we're not going to support write-mode, meaning the content LavaDome is willing to support is plain text and nothing more complex than that.

This is because supporting write mode - meaning an intractable isolated DOM - introduces multiple security complications we're not yet ready to face at this point, such as:

  1. Event listeners security - prevent outer code from stealing input destined to LavaDome inner nodes;
  2. Overlay security - prevent malicious code from laying phishing DOM on top of LavaDome, thus making the user serve sensitive input to the wrong entity;
  3. etc - Probably more stuff.

Design

The design complexity level of this project isn't this high - it's the combination of the different principles in this project that make it non-trivial (see Security).

Nevertheless, it's worth explaining the design in high level by listing the different packages:

Core

Implements the basic API layer that mediates the communication between the consumer and the protected isolated component. The API aspires to allow as much external manipulation of the isolated component as possible without providing actual DOM nodes from within it to anyone - not even the consumer of LavaDome - to maintain the highest security level possible.

In addition, it takes the responsibility of implementing all necessary security hardening to make ShadowDOM feature usage truly secure in contrast to its native nature of not being a security feature by default (see Security).

JavaScript / React / etc

Export functionalities for developers to consume LavaDome however they prefer, whether by javascript JavaScript or as a React component (or any other platform - ask away!)

NOTE: Delivering LavaDome support for frameworks integrates third party code that is out of our control, which results in "security blank spots" - please read the Security section to learn what to do to remain as safe as possible.

Security

Whether you plan on using LavaDome or just interested in what we're trying to achieve here, these are the security aspects to be aware of

ShadowDOM vs iframes

Again, this is still an experimental project, but we did put some thought into this decision. A natural alternative was leveraging cross-origin iframes.

The upside to those is that infiltrating a cross-origin iframe is impossible, and is recognized as a security critical mechanism by W3C spec, which means that if it gets breached somehow, that will be treated as a security vulnerability and will be addressed and fixed by browser vendors urgently.

The downside however, is that integrating an iframe-based solution is significantly harder, in terms of UI/UX/DX, especially as a tool aimed at mass adoption.

Because eventually, this is about being able to integrate DOM nodes within DOM trees in the most natural and smooth way - ShadowDOM API is built exactly for that purpose - being a DOM oriented API aimed to easily integrate within DOM trees while belonging to the same realm as the encapsulating DOM tree.

The alleged downside to the ShadowDOM API is that it isn't originally designed for security goals, but in reality its implementation is introduced in a highly secured manner, not leaking anything from within it except for very specific scenarios.

We believe that by addressing these scenarios securely and carefully, we can take ShadowDOM another step closer to being a secured DOM encapsulation API (worth a shot).

ShadowDOM security gaps

It's important to address the current security threats that do exist with ShadowDOM.

Injection

Developers might provide LavaDome with HTML/JS/CSS content that can accidentally or intentionally leak DOM nodes from within the ShadowDOM when loaded, for example by adding JavaScript code.

In order to not allow this to happen, LavaDome does not accept DOM nodes, but merely plain text, as we want to avoid attempting to trust HTML/JS/CSS content.

We'd love to revisit this decision in the future when we research and find a stable and secure way to achieve that.

window.find()

This API allows developers to find and extract DOM nodes by finding some text inside them, and is the only API that is known (so far) to successfully leak DOM nodes from within a ShadowDOM.

// attacker setTimeout(() => { find('Secret is:'); // assuming the Shadow includes predictable text console.log('stolen secret: ', getSelection().anchorNode.textContent); });

To defend against that, for starters this means consumer of LavaDome must not pass predictable content to LavaDome API. This might sound obvious, but developers can easily be tempted to pass LavaDome something like The secret is: ldsjf9304rjdkn, but that would compromise everything, because even though the ldsjf9304rjdkn part clearly changes, the phrase The secret is: can be exploited to get to the real secret.

Therefore, when using LavaDome, developers MUST only pass it 100% unpredictable text.

// attacker setTimeout(() => { console.log(1, 'stolen secret:'); const bypass = '<audio/src/onerror=console.log(2,this.nextSibling.innerHTML)>'; find('Secret is:'); // assuming the Shadow includes predictable text // assuming the found node is contenteditable=true document.execCommand("insertHTML", false, bypass); });

To defend against that, LavaDome will apply to its custom elements the highest priority style possible for -webkit-user-modify: unset; so that no elements of it are vulnerable to injection of malicious outer style making it contenteditable. Otherwise, malicious outer style applying -webkit-user-modify:read-write might make the ShadowDOM elements contenteditable and vulnerable to this attack vector.

Needless to say that the other technique of using contenteditable as an attribute isn't currently relevant as LavaDome does not support accepting actual DOM nodes by design.

Defensive coding

Hard to achieve an actual secured solution without writing the code defensively. This means that all the native APIs we use are cached for internal usage, so that it isn't possible to reconfigure global APIs to sabotage the legit flow of LavaDome.

If you see some weird code style choices in the sourcecode, there's a good chance it was done out of having defensive coding in mind.

As long as we remain in the realms of Vanilla JavaScript, defensive coding is something we can (do our very best to) control.

However, when using the framework versions of LavaDome, this means these frameworks aren't defensively written which means the native APIs they make use of aren't safe from malicious interference - and that is out of LavaDome's control.

Which is why we recommend to always integrate such security solutions with SES technology by
@agoric - same as we do at LavaMoat and MetaMask.

Disclaimers

If you read everything above, you should have a good sense of why this is still very experimental. Ensuring security to a non-security feature by nature is risky, and this project is merely an experimental attempt to solve a problem with no current great answer.

You should still use it - because it's probably better than what the web has to offer currently. But even if it's safer than other solutions, it should not be mistaken for "safe" but rather "safer".