Skip to content
This repository has been archived by the owner on Aug 11, 2022. It is now read-only.

package.json should be required to be JSON, and never eval()'ed. #408

Closed
inimino opened this issue Nov 28, 2010 · 6 comments
Closed

package.json should be required to be JSON, and never eval()'ed. #408

inimino opened this issue Nov 28, 2010 · 6 comments

Comments

@inimino
Copy link

inimino commented Nov 28, 2010

  1. It's likely to be a security risk if you can't even query or list the contents of a package without evaluating arbitrary code (e.g. npm view should always be safe).
  2. It's going to create incompatibilities with any other package managers for other environments or for node, and encourages people to create package.json files that aren't JSON, which is a bad thing.
@isaacs
Copy link
Contributor

isaacs commented Nov 28, 2010

If JSON.parse fails, then the package.json is evaluated using Script.runInNewContext, so that it has no access to any of node's capabilities.

The security implication is nil. It's just pure JS (in parens), not a node program. But allowing JavaScript constructs does allow for strings that span multiple lines, comments, and unquoted keys, all of which are pretty nice-to-have features.

I'm not worried about compatibility with other packagers. What ends up on the registry and in the cache is sanitary JSON, so it's not an issue. If package authors want ot be compatible with systems that don't allow these features, then it's up to them to be more strict with themselves.

@inimino
Copy link
Author

inimino commented Nov 29, 2010

Even if there is no security issue, (I guess that depends how package.json is used; I wasn't aware the original package.json isn't served from the registry) I still think fake JSON should be discouraged, and npm is the only place to do that when people are writing package.json files only for npm. If someone mirrors the npm package database, won't the uploaded npm packages still contain the original package.json?

Putting non-JSON in package.json is exactly the sort of thing I think tools need to prevent as early as possible, because it is increasingly harder to change once people rely on it. Comments are convenient but not necessary, and unquoted property names certainly aren't worth giving up JSON-compatibility for. If package.json is going to become a standard location for package metadata, other tools are going to want to read it. It would be disappointing if we end up with a de-facto standard of arbitrary code in package.json just to support a little more author laziness in early days.

@isaacs
Copy link
Contributor

isaacs commented Nov 29, 2010

I guess that depends how package.json is used; I wasn't aware the original package.json isn't served from the registry

The registry is a couch app. It's pretty finicky about the JSON you put in. In fact, it can't even have property names that start with _ (except the blessed _rev and _id), and has to pass through a pretty strict validate_doc_update function.

If someone mirrors the npm package database, won't the uploaded npm packages still contain the original package.json?

The tarballs do contain the original unmolested package.json.

But again, the security issue isn't because package authors can't execute arbitrary JavaScript. It's because the arbitrary JavaScript they can execute is powerless. No "process", no "require", etc. No IO of any kind. Nothing except what's in the ES5 spec.

They could conceivably do while(true);, and that'd suck. But all it would do is spin the CPU until you hit ^C.

On the other hand, you're totally right, of course.

The very aspects that make the system secure also make it crappy. If you wanted some clever build system that generates the package.json file based on some git state or gemspec or something (as some people currently do), it'd be nice to have a way to do that easily.

Furthermore, ".json" should be a JSON file, and ".js" should be a JS file.

So, here's an idea, lemme know how it strikes you:

When publishing or installing/linking a local folder, if there's no package.json file, but there is a package.js file, then do fs.write("./package.json", JSON.stringify(require("./package.js"))).

When installing a published name/version combination, if there is no package.json, then fail.

This way, you'll be able to do your fancy build step stuff on your own kit, but stuff sent to the registry will have to be "frozen" at some spot.

@inimino
Copy link
Author

inimino commented Nov 29, 2010

That sounds good to me. I use a regular build system (make, shell scripts, node scripts, miscellaneous other stuff) to generate a package, then I tar it up and npm publish the tarball. I wouldn't have thought to move parts of the build process into npm, but if people want to do that, your package.js idea sounds like a great way to support it and keep package.json clean at the same time.

@isaacs
Copy link
Contributor

isaacs commented Nov 29, 2010

Yeah, also, "hey, if you want comments (and for that matter, all of node) just use a package.js and set module.exports = { package.json stuff }". That's neat.

@ghost
Copy link

ghost commented Dec 30, 2010

Is there any concern that "package.js" would make it impossible to have a "package" module in the root directory of the project? An edge case, to be sure...

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants