Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security & Package Authorship #1

Open
lsjroberts opened this issue Nov 26, 2018 · 7 comments
Open

Security & Package Authorship #1

lsjroberts opened this issue Nov 26, 2018 · 7 comments
Labels
discussion Ideas open for discussion

Comments

@lsjroberts
Copy link
Contributor

lsjroberts commented Nov 26, 2018

In light of the recent event-stream security issue, and the previous left-pad debacle, it seems sensible to open discussion on approaches to more secure methods of guaranteeing authorship and safe publishing & installation of packages.

What exists already?

note: "exists" refers to in the design, not code, wool is still very early pre-alpha

Indirect packages

In its current design, wool helps surface indirect / transient packages. This helps developers be fully aware of the quantity of dependencies in their project and whose code is running.

wool add hello/world
To add hello/world I would like to install the following packages:

    hello/world  1.2.0  1.0.0 <= v < 2.0.0
    hello/other  2.0.0  2.0.0 <= v < 3.0.0

Should I install these packages? [Y/n]
{
  "dependencies": {
    "direct": {
      "hello/world": "1.0.0 <= v < 2.0.0"
    },
    "indirect": {
      "hello/other": "2.0.0 <= v < 3.0.0"
    }
  }
}

Automatic semver

It also only allows a single entry point into packages with an automatically semantically versioned interface.

Registries

When creating a project, the developer must choose which package registries to point at (defaulting to just registry.wool.org).

{
  "registries": ["registry.wool.org"]
}

All registries must be accessible over https.

When adding a package, its registry is stored in the wool.lock, e.g.

{
  "hello/world": {
    "version": "1.2.0",
    "constraint": "1.0.0 <= v < 2.0.0",
    "registry": "registry.wool.org"
  }
}

Further ideas

Package permissions and sandboxing

Restricted default file access

Most packages do not need direct access to the filesystem, so by default they should not be allowed to read or write anywhere.

Restricted default network access

Most packages also do not need network access, so by default they should also not be allowed to send network requests.

Granting permissions

Packages should be provided opt-in permissions to let them perform certain, risky actions.

When running wool make ., wool would warn them that a package does not have the permissions it requires:

❖ PERMISSIONS REQUIRED --------------------------------------------- hello/world

The package hello/world requires the following permissions:

    "read": true
    "write: ["./path/to/folder"]

Do you wish to grant these permissions to hello/world? [y/N]

This would then update their wool.json and re-attempt the compilation.

{
  "dependencies": {
    "direct": {
-     "hello/world": "1.0.0 <= v < 2.0.0"
+     "hello/world": {
+       "constraint": "1.0.0 <= v < 2.0.0",
+       "permissions": {
+         "read": true,
+         "write": ["./path/to/folder"]
+       }
+     }
    }
  }
}

For example, to restrict file access this can be acheived through the wool loader by preventing installed packages from using the fs package directly.

Instead import via wool/fs (with the loader explicitly only allowing the wool namespace direct access to node in-built packages).

-import * as fs from 'fs';
+import * as fs from 'wool/fs';

Publish verification

2-factor authentication should be mandatory for all publishing, even to private registries.

Package archival

It should be possible for maintainers to archive packages and put them in a read-only mode.

wool archive .

Both archiving and unarchiving a package would require 2-factor authentication.

Developers adding archived projects will be warned:

❖ PACKAGE ARCHIVED ----------------------------------------------- hello/world

The package hello/world has been archived and is no longer being maintained.
It may present a security risk for your project if there are un-patched
vulnerabilities.

Do you wish to continue using hello/world? [y/N]
{
  "dependencies": {
    "direct": {
-     "hello/world": "1.0.0 <= v < 2.0.0"
+     "hello/world": {
+       "constraint": "1.0.0 <= v < 2.0.0",
+       "allowArchived": true
+     }
    }
  }
}

Transferal of ownership

It should be feasible to transfer ownership of a project that the maintainer no longer wishes to support.

This would involve the owner pushing a "transference key" to the registry, this would immediately lock the package and prevent any new publications. They would then share the key with the intended new owner, who would then use it to unlock and take control of the package.

Only one account should be able to publish a package at any given time.

Transferal of ownership would enforce the next publication to be a major version update bump.

If a developer updates their constraint to the next major version they will be warned about the ownership change.

❖ PACKAGE OWNER CHANGED --------------------------------------- hello/world

The package `hello/world` has transferred ownership from:

    [email protected]

to:

    [email protected]

Before updating from 1.2.0 to 2.0.0 you should check the new package owner
is trustworthy.

Do you wish to continue? [y/N]

Checksum imports

When compiling, check the imported package code against their checksums stored in the wool.lock.

{
  "hello/world": {
    "version": "1.2.0",
    "constraint": "1.0.0 <= v < 2.0.0",
    "registry": "registry.wool.org",
    "checksum": "123456"
  }
}

This could be generated by running a concatenated toString() on the exported functions & values. If another package mutates the function it will return a different toString() value and fail the checksum validation.

e.g.

import hello from 'hello/world'

let originalGreet = hello.greet;
hello.greet = async (message) => {
  await mineSomeBitcoin();
  return hello.greet(message);
};

Questions

Decentralisation and package name clashes

One of the main issues around a decentralised approach to package registries is namespace squatting and package name clashes.

Even from non-malicious actors this would be confusing and annoying.

If a package name exists on multiple registries, the user will be asked to confirm which registry they wish to install from:

❖ PACKAGE NAME CLASH --------------------------------------- hello/world

The package `hello/world` exists on more than one registry:

    registry.wool.org
    registry.wool-community.net

Which registry should I download this package from?    # multiple choice input
{
  "registries": ["registry.wool.org"]
  "dependencies": {
    "direct": {
-     "hello/world": "1.0.0 <= v < 2.0.0"
+     "hello/world": {
+       "constraint": "1.0.0 <= v < 2.0.0",
+       "registry": "registry.wool.org"
+     }
    }
  }
}

Is this enough? Is there any sensible way to prevent name clashing between decentralised registries?

What about namespace squatting?

Say the company hello registers their namespace on registry.wool.org, and publishes hello/world.

Then on another registry, for example registry.wool-community.net, an unaffiliated user registers hello. What recourse can the company hello take? Can the user mimic the company and freely cause confusion?

Should there be a single central authority for public namespace registration? Ideally not.

Perhaps allow whole namespaces to be tied to registries, instead of on a per-package basis.

{
  "registries": [
    "registry.wool.org",
+   {
+     "namespace": "hello",
+     "registry": "registry.hello.com"
+   }
  ],
  ...
}

And importantly, how can wool assuage non-developer stakeholders of the risks?

Commit verification

Should publishing be tied to the git repository? The primary downside is it would force package authors to use git, however this is by far the most dominant vcs used. And security is more important than convenience.

This would allow commit verification as a requirement.

It could be an opt-in for registries, i.e. a registry could chose to force all users to verify their commits.

Anything else?

There are probably numerous other issues and attack vectors possible.

@lsjroberts lsjroberts added the discussion Ideas open for discussion label Nov 26, 2018
@lsjroberts
Copy link
Contributor Author

This would involve the owner pushing a "transference key" to the registry, this would immediately lock the package and prevent any new publications. They would then share the key with the intended new owner, who would then use it to unlock and take control of the package.

This might be too convoluted, perhaps just wool change-owner [email protected] or something?

@lsjroberts
Copy link
Contributor Author

Worth investigating how maven does code signing - https://news.ycombinator.com/item?id=18534867

@lsjroberts
Copy link
Contributor Author

It will also need to provide a level of protection against typo-squatting, probably through user confirmation and warnings about similarly named packages

@lsjroberts
Copy link
Contributor Author

Archival should be a patch release

@lsjroberts
Copy link
Contributor Author

Packages should be published as their uncompiled typescript (though with the d.ts for various conveniences). And then built on the local machine. See https://twitter.com/jordwalke/status/1067340327407644672

@lsjroberts
Copy link
Contributor Author

There should be a way to see how stale a package is, i.e. when it was last updated.

wool summary
// ... other info ...

Outdated Packages

    Name         Installed  Latest
    hello/world  1.2.0      1.8.0


Stale Packages

    Name         Installed  Latest  Published
    hello/other  2.4.1      2.4.1   183 days ago

@lsjroberts
Copy link
Contributor Author

The permissions required warning should be more human friendly, e.g.

❖ PERMISSIONS REQUIRED --------------------------------------------- hello/world

The package hello/world requires the following permissions:

    Read all your files and data
    Write to "./path/to/folder"

Do you wish to grant these permissions to hello/world? [y/N]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Ideas open for discussion
Projects
None yet
Development

No branches or pull requests

1 participant