Package-maintenance: Introduce field to configure expected permissions of a package.

Created on 2 Dec 2020  路  10Comments  路  Source: nodejs/package-maintenance

Node has the ability to limit access to modules and enforce integrity at runtime these days with policies.

There should be a way to have a package list what permissions it wants to be granted at install time. Permissions for policies currently are limited to integrity checks on the files (preventing the file write described in the event-stream breakdown), or limiting what modules can be accessed via import/require preventing things like a text parser spawning child processes directly.

This means that there should be:

  1. some way to persist these permissions across installs / updates

    1. ideally diff the changes

  2. some way to list the current permissions

I propose we look into adding a field to package.json to specify what a package is expecting to be granted. This is likely much different from the policy file itself since it doesn't need to do things like list the integrity of each file and would not contain the resolution of its dependencies to prevent redirecting to other modules. So while a policy would have these specifics, a package likely only wants to list the extern modules it can access pre-resolution and list if files are not expecting to be integrity checked.

Unlike lock files which guard install time, this is meant generate the guards for run time. Node core can enforce the guards and be expanded for more guards as needed.

I am open to any designs to suit package managers.

package-maintenance-agenda

All 10 comments

Based on the discussion related to adding support info, I'm guessing the preference might be to add as a separate file, possibly with an entry in the package.json that indicates if the info is provided or not.

@mhdawson I am fairly neutral to any location since this is not runtime information. I would state that any runtime based configuration should be in package.json since we already grab that file for various things at runtime. I would be opposed to any runtime mechanism using a new file.

@bmeck the use cases that we considered for support info that resulted in a package.json field that either a) contained inline info or b) pointed to a repo with the config or c) pointed to a file in the repo with the config were to serve the ability to have shared config.

In this case, if the info must be contained directly in package.json, that adds a lot of friction to the ability for a company, for example, to easily ensure that every app within the company shares the same policies, because it would require N changes to update N apps.

In this case, if the info must be contained directly in package.json, that adds a lot of friction to the ability for a company, for example, to easily ensure that every app within the company shares the same policies, because it would require N changes to update N apps.

I'm not sure what you mean by friction. Policies, much like lock files are specific per application. Lock files are done at install time to guard install time replication. Policies are a means to guard runtime.

Policies are not enforced and should not be enforced by package.json since they require things like knowing the entire codebase of the application to properly secure some attacks; this request is to add a field so that tooling can generate the policy file at install time.

The purpose of the field is listing what permissions are expected/requested by a package, not what is granted. A company can/should be concerned with what is granted but I cannot think of a reason to have the requested permissions to be uniform across all packages. Some packages require different access levels; things like a text parser shouldn't request child_process but a SSH wrapper should.

The field I am requesting should not point to another file as that is a vulnerability if it could be altered in a way that escalates privileges.

a) contained inline info

It does, similar to how dependencies/devDependencies are listed. I'm not sure I understand what you mean by "inline info" since all information in JSON is inline.

b) pointed to a repo with the config

This would be a bug in designing the field since they are listing the permissions the package in question uses and deferring that wouldn't make sense / be a vector of abuse.

c) pointed to a file in the repo with the config were to serve the ability to have shared config.

I'm unclear why it would be a separate file since it isn't going to be used by the policy enforcement mechanism itself.

Thanks for clarifying; so it's more of a declaration of capabilities - in that case, inline in the package.json makes sense, since it's primarily about published packages.

Missed this as it doesn't have any modules group pings and I'm no longer subscribed to the firehose.

I really like the concept of this kind of a permissions system. But the details are very hard to get right on this.

Two main points:

  1. Given the wide design space, it would be worth having a mandatory version for the field, and explicitly start out with an experimental version.
  2. I think it would be beneficial to start with a global application manifest, that defines the package boundary paths:
{
  "core-imports": "off-by-default",
  "module-imports": "explicit-pjson-dependencies",
  "permissions": {
    "./node_modules/x": {
      "fs": { "permission": "read", "scope": "./node_modules/x" }
    }
  }
}

(syntax a complete bikeshed!)

Re 2, I agree; i like the idea of an app-level field (a different field) in package.json that was like resolutions/overrides on top of the per-package field.

Re 1, can you elaborate on what you mean by mandatory?

@ljharb using the same example as above which refers to some type of global permissions manifest, the per package manifest equivalent would then require the version something like:

// node_modules/x/package.json
{
  "permissions": {
    "version": "0.1.0-experimental",
    "packages": {
      "fs": { "permission": "read", "scope": "./node_modules/x" }
    }
  }
}

(again a complete bikeshed)

where if there were no explicit and matching version field, it would ignore the field.

What would be the point of a version field inside the permissions object, when the resulting package.json likely has a version field itself?

per our call today it seems like this is likely better suited in a different space since the feature isn't tailoring itself towards package authors. I'm closing it here and will find a different place to discuss.

Was this page helpful?
0 / 5 - 0 ratings