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

linvail

v6.0.12

Published

Access Control System

Downloads

53

Readme

Linvail

Linvail is a npm module which implements a transitive access control system based on proxies known as membrane. This module's motivation was to build dynamic analyses capable of tracking primitive values across the object graph. Originally it was hard-coupled with the JavaScript code instrumenter Aran. Now, this module can be used on its own.

Wild Values, Tame Values and Dirty Values

Using Linvail requires to juggle between three sets of values: Wild, Tame and Dirty. Dirty values can only be obtained by calling the user-defined function membrane.taint. There is no restriction on dirty values because Linvail always passes them to the other used-defined function membrane.clean before using them them in any operation. Wild values are values which seem to contain only other wild values. By opposition, tame values seem to only contain dirty values. A wild value can be converted to a tame value with the Linvail-defined function capture and a tame value can be converted to a wild value with the Linvail-defined function release. These two functions involve wrapping objects into ECMAScript proxies which perform the appropriate conversion.

category

  • A wild value is either:
    • A primitive.
    • An object which satisfies the below constraints:
      • Its prototype is a wild value.
      • The value of its data properties are wild values.
      • The getter and setter of its accessor properties are wild values.
      • Applying it with a wild value this-argument and wild value arguments will return a wild value or throw a wild value.
      • Constructing it with a wild value new-target and wild value arguments will return a wild value or throw a wild value.
  • A tame value is either:
    • A primitive.
    • An object which satisfies the below constraints:
      • Its prototype is a tame value.
      • The value of its data properties are dirty values except if the reference is an array; in that case, it's length property remains a wild value.
      • The getter and setter of its accessor properties are tame values.
      • Applying it with a dirty value this-argument and dirty value arguments will return a dirty value or throw a wild value.
      • Constructing it with a tame value new-target and dirty value arguments will return a dirty value or throw a wild value.
  • The dirty value set is defined by the user through the functions membrane.taint and membrane.clean.
npm install linvail
const Linvail = require("linvail");
let counter = 0;
const membrane = {
  taint: (tame) => {
    counter++;
    console.log("@"+counter+" := "+(typeof tame));
    return {base:tame, meta:counter};
  },
  clean: (dirty) => {
    console.log("using @"+dirty.meta);
    return dirty.base;
  }
};
const {capture, release} = Linvail(membrane);
const tame = Object.create(null);
const wild = release(tame);
const dirty = membrane.taint(tame);
tame.foo = membrane.taint(123);
wild.bar = 456;
console.log("A tame object: ", tame);
console.log("Its cleaned values: ", Object.values(wild));
console.log("Its tainted values: ", capture(Object.values)(dirty));
@1 := object
@2 := number
@3 := number
A tame object:  { foo: { base: 123, meta: 2 }, bar: { base: 456, meta: 3 } }
using @2
using @2
using @3
using @3
Its cleaned values:  [ 123, 456 ]
using @1
@4 := object
@5 := function
@6 := function
@7 := function
Its tainted values:  { base: [ { base: 123, meta: 2 }, { base: 456, meta: 3 } ], meta: 4 }

Note how the tamed Object.values function was able to conserve the meta tag of its argument's values. This is possible because Linvail knows about the semantic of several builtin functions to optimize the behavior of their tame counter-part. This semantic is encoded as a collection of closures collectively named the oracle.

The oracle

In the general case, applying a foreign tame function involves cleaning-releasing arguments and capturing-tainting the result. This algorithm always prevent clashes between value sets but it may induce needless cleaning/re-tainting operations. Consider the wild identity function: (x) => x. Knowing its semantic, we could deduce that it is not needed to clean its argument. More specifically, in the code below, we would like that dirty1 always resolve to the same value as dirty2.

const dirty1 = membrane.taint("foo");
const wild = (x) => x;
const tame = access.capture(wild);
const dirty2 = tame(dirty1);

As for the identity function, the default application algorithm performs many unnecessary cleaning/re-tainting operations for many functions of the global object. For instance, Object.values does not perform any operation on an object's values but simply push them in an array. Currently, Linvail uses a very rudimentary oracle which simply specifies the cleaning/tainting operations for every builtin function it supports. At the moment the oracle contains:

  • Reflect
    • Reflect.apply
    • Reflect.construct
    • Reflect.defineProperty
    • Reflect.get
    • Reflect.getOwnPropertyDescriptor;
    • Reflect.ownKeys
    • Reflect.preventExtensions
    • Reflect.set
  • Object
    • Object
    • Object.assign
    • Object.create
    • Object.defineProperties
    • Object.defineProperty
    • Object.entries
    • Object.getOwnPropertyDescriptor
    • Object.getOwnPropertyDescriptors
    • Object.getOwnPropertyNames
    • Object.getOwnPropertySymbols
    • Object.keys
    • Object.values
  • Array
    • Array
    • Array.from
    • Array.of

API

linvail = require("linvail")(membrane, [options])

{capture, release} = require("linvail")(membrane, {check, "aran-builtins":builtins});
  • tainted = membrane.taint(tame): User-defined function to convert a tame value to a dirty value.
  • tame = membrane.clean(tainted): User-defined function to convert a dirty value to a tame value.
  • check :: boolean, default false: Indicates whether runtime checks should be performed to detect clashes between tame values, wild values and dirty values. These checks will be performed in capture, release but also in membrane.taint and membrane.clean. The original function of the membrane will be respectively set to membrane._taint and membrane._clean. This option is for debugging purpose and comes at the cost of performance overhead.
  • builtins :: object, default null: This option is used to augment the oracle with aran-defined functions.
  • tame = capture(wild): Linvail-defined function to convert a wild value into a tame value.
  • wild = release(tame): Linvail-defined function to convert a tame value into a wild value.