Remix.run Logo
l___l 4 hours ago

Is there a theoretical framework that can prevent this from happening? Proof-carrying code?

killerstorm 4 hours ago | parent | next [-]

Object-capability model / capability-based security.

Do not let code to have access to things it's not supposed to access.

It's actually that simple. If you implemented a function which formats a string, it should not have access to `readFile`, for example.

Retrofitting it into JS isn't possible, though, as language is way too dynamic - self-modifying code, reflection, etc, means there's no isolation between modules.

In a language which is less dynamic it might be as easy as making a white-list for imports.

pjc50 4 hours ago | parent [-]

People have tried this, but in practice it's quite hard to do because then you have to start treating individual functions as security boundaries - if you can't readFile, just find a function which does it for you.

The situation gets better in monadic environments (can't readFile without the IO monad, and you cant' call anything which would read it).

killerstorm 3 hours ago | parent [-]

Well, to me it looks like people are unreasonably eager to use "pathologically dynamic" languages like JS & Python, and it's an impossible problem in a highly dynamic environment where you can just randomly traverse and change objects.

Programming languages which are "static" (or, basically, sane) you can identify all imports of a module/library, and, basically, ban anything which isn't "pure" part of stdlib.

If your module needs to work with files, it will receive an object which lets it to work with files.

A lot of programming languages implement object-capability model: https://en.m.wikipedia.org/wiki/Object-capability_model it doesn't seem to be hard at all. It's just programmers have preference for shittier languages, just like they prefer C which doesn't even have language-level array bound checking (for a lack of a "dynamic array" concept on a language level).

I think it's sort of orthogonal to "pure functional" / monadic: if you have unrestricted imports you can import some shit like unsafePerformIO, right? You have another level of control, of course (i.e. you just need to ban unsafePerformIO and look for unlicensed IO) but I don't feel like ocap requires Haskell

viraptor 4 hours ago | parent | prev | next [-]

You can protect yourself using existing tools, but it's not trivial and requires serious custom work. Effectively you want minimal permissions and loud failures.

This is something I'm trying to polish for my system now, but the idea is: yarn (and bundler and others) needs to talk only to the repositories. That means yarn install is only allowed outbound connections to localhost running a proxy for packages. It can only write in tmp, its caches, and the current project's node_packages. It cannot read home files beyond specified ones (like .yarnrc). The alias to yarn strips the cloud credentials. All tokens used for installation are read-only. Then you have to do the same for the projects themselves.

On Linux, selinux can do this. On Mac, you have to fight a long battle with sandbox-exec, but it's kinda maybe working. (If it gained "allow exec with specified profile", it would be so much better)

But you may have guessed from the description so far - it's all very environment dependent, time sink-y, and often annoying. It will explode on issues though - try to touch ~/.aws/credentials for example and yarn will get killed and reported - which is exactly what we want.

But internally? The whole environment would have to be redone from scratch. Right now package installation will run any code it wants. It will compile extensions with gyp which is another way of custom code running. The whole system relies on arbitrary code execution and hopes it's secure. (It will never be) Capabilities are a fun idea, but would have to be seriously improved and scoped to work here.

chrisweekly 3 hours ago | parent [-]

Why yarn instead of pnpm?

tarruda 4 hours ago | parent | prev | next [-]

Something similar to Deno's permission system, but operating at a package level instead of a process level.

When declaring dependencies, you'd also declare the permissions of those dependencies. So a package like `tinycolor` would never need network or disk access.

diggan 4 hours ago | parent | prev | next [-]

Probably signatures could alleviate most of these issues, as each publish would require the author to actually sign the artifact, and setup properly with hardware keys, this sort of malware couldn't spread. The NPM CI tokens that don't require 2fa kind of makes it less useful though.

Clojars (run by volunteers AFAIK) been doing signatures since forever, not sure why it's so difficult for Microsoft to follow their own yearly proclamation of "security is our top concern".

madeofpalk 4 hours ago | parent [-]

I would like to see more usage of NPM/Github Actions provenance statements https://www.npmjs.com/package/sigstore#provenance through the ecosystem

> The NPM CI tokens that don't require 2fa kind of makes it less useful though

Use OIDC to publish packages instead of having tokens around that can be stolen or leaked https://docs.npmjs.com/trusted-publishers

mzl 4 hours ago | parent | prev | next [-]

Manual verification of releases and chain-of-trust systems help a lot. See for example https://lucumr.pocoo.org/2019/7/29/dependency-scaling/

dist-epoch 4 hours ago | parent | prev [-]

There are, but they have huge performance or usability penalties.

Stuff like intents "this is a math library, it is not allowed to access the network or filesystem".

At a higher level, you have app sandboxing, like on phones or Apple/Windows store. Sandboxed desktop apps are quite hated by developers - my app should be allowed to do whatever the fuck it wants.

IshKebab 4 hours ago | parent | next [-]

Do they actually have huge performance penalties in Javascript?

I would have thought it wouldn't be too hard to design a capability system in JS. I bet someone has done it already.

Of course, it's not going to be compatible with any existing JS libraries. That's the problem.

3 hours ago | parent | prev | next [-]
[deleted]
killerstorm 4 hours ago | parent | prev [-]

You can do that by screening module imports with zero runtime penalty.