Conversation
|
|
|
A few questions:
|
|
|
Just to back up a little bit and frame the discussion, let me talk about the Node core vs the N|Solid runtime which is essentially core++. One of the driving ideas being N|Solid, particularly at the runtime component, is that it's a place where we can put functionality that either doesn't belong in the OSS core or doesn't fit well within the small-core philosophy that has served Node.js so well. NodeSource wants to be able to upstream things that may prove useful in general but I do think we (in core) want to be very careful about bloat just because there is a section of the user community that finds functionality useful. It does make sense for us to say that some things just don't belong in core because they negatively impact on the average user either in terms of complexity, performance or the additional divided attention of core developers (the standard library problem). N|Solid's user-base is very enterprise-heavy, focused on the types of users that don't want to have to piece things together themselves or come up with solutions more complicated than point-and-click. This gives NodeSource the ability to do a bit of kitchen sinking of core, putting additional modules in there that you'd normally have to install in userland. One of the more extreme examples of something that may be considered at some point in the future is an XML parser and serialiser. This is something that hits enterprise pretty hard with Node because heavy string parsing and manipulation isn't exactly Node's forte yet most of the kinds of companies NodeSource deals with have legacy SOAP and other crappy XML APIs they have to live with. Onto policies specifically. This is a feature that some of the very large companies like (even if they don't actually use it), it makes operations departments happy, but pretty much nobody else. It comes from similar features that Java has and appeals to the ops mentality of having complete control over stuff (cause they never trust developers) and they tend to miss all of the Java knob-turning when they move to Node. But, it adds significant complexity to core and it also introduces an expectation burden on developers because it has such deep impact on application runtime, it's a big fat hammer that stops any code in your application (dependencies included obviously) from using a module. It widens the potential gap between development and deployment by modifying the execution environment. Adding yet another major runtime behaviour modifier introduces cognitive overhead for developers. Another problem with this feature that NodeSource experiences in practice is the expectation of security and sandbox. You'll notice that there is no mention of "sandbox" in the doc you linked to and the only mention of "security" there is a "Further Thoughts" disclaimer telling you that you shouldn't use this as a replacement or proper security practices. This isn't AppArmor and without severe lock-down you can't stop breakouts (particularly via addons which can replace any functionality you want to blacklist). It's much more of a lint-like tool than a security tool, framing it as a sandbox or a security feature puts us (Node core and NodeSource) into a very problematic space and makes us much more liable for user security (not in a strictly legal sense obviously, that's what OSS licenses are for) which we absolutely don't want to be. I don't particularly want to go through the zero-fill IF sandboxing really is an interesting piece of functionality to explore then perhaps we should tackle that in a holistic manner by stepping back and asking what it would mean to sandbox Node? Perhaps there's a place for providing a server-side Browser-like environment? I don't like the idea, denying that you're writing server-side applications is absurd and simply encourages poor programming behaviour because you think the runtime takes care of all of the tricky things. It's true that we have a lot of users coming to Node and bringing their expectations based on the fact that it's JavaScript. I don't particularly want us to be in the same kind of space as Docker where preventing break-out is one of the cores of what they do. I don't want it to be logical for Node to participate in browser pwn2own competitions. We'd be better off pointing people to good AppArmour and SELinux style documentation if they really want to do lock-down. |
|
/cc @nodejs/security, perhaps |
|
FWIW, at StrongLoop we've had similar requests from customers - i.e., module whitelisting - and, like Rod says, the main use case seems to be locking down enterprise developers. I somewhat understand where these companies come from but as to whether it's a feature that belongs in core, I'd say I'm -0.5 - "preferably not." |
Agree with your comment, except wanted to clarify this point. The buffer issue showed us how many users expected buffer to be zero-filled -- an incorrect belief, probably based on comparisons to the browser's typed array implementation. But the actual issue, once it was all hashed out, was really about improving the API so it's not a potential foot-gun. |
|
Right @feross, it's hard to talk about the Buffer changes without conflating the two items. The API problem was a real problem, the zero-fill user expectations were something else. |
|
So bit more about the motivation behind opening this discussion: to be absolutely certain, I'm not taking the position that policies are something we absolutely need to have in core. However, as @bnoordhuis and @rvagg point out, this idea of whitelisting/blacklisting/sandboxing modules comes up often in enterprise use cases -- so often that at least having the discussion about whether it's something we'd want in core makes a lot of sense. However, the policy route that n|solid and this EP discuss can be quite problematic in that the policies to be either grossly underspecified or extremely complicated to enforce. If we did start down this road I'm afraid that we'd end up with something very similar to Java's policy framework and I don't think anyone of us actually want that. It's quite likely (and quite probable) that policies simply aren't a thing we want in core in any way but I'd like us to be deliberate about that decision. That said, given how prevalent the use case is in the enterprise, some generalized solution may be worthwhile here that can work for users of all Node.js distributions. We (IBM) could certainly come up with a policy mechanism that works for us and is baked into our particular builds of Node.js but having multiple policy formats and approaches that only work depending on which third party Node.js distribution you happen to be using kind of sucks (we've been down that road before and we don't like it). So while baking a policy thing into core might not be the right approach, working within the foundation on a common approach to building a policy thing that can work with all Node.js distributions may be a very worthwhile activity. The question then becomes, what would we need to do in core to enable it without having to actually bake it in. |
|
Mechanism, not policy: if we add hooks to the module loader (e.g. a way to override the |
|
@jasnell Want to take a stab at writing a proposal that exposes the necessary hooks to allow this proposal to work? |
|
Closing as this is over two years dormant. By all means, comment or re-open if this is still an ongoing concern, although I suspect it should be moved to a more active repository (probably the main node repo) if that's the case. |
NodeSource's n|solid Node.js build introduces the notion of policies that can be applied to Node to essentially sandbox applications.
Example n|solid policy document:
{ "// severity levels": "0 - ignore; 1 - warning; 2 - throw error; 3 - exit", "blacklist": { "modules": { "dns": 2 }, "bindings": { "cares_wrap": 2 } } }The
blacklistproperty identifies specific core modules and bindings that can or cannot be required. n|solid will either print a warning to the console, throw an error or abort the process of a blacklisted module is required.This EP proposes a modified form of this policy mechanism with a slightly refactored policy syntax built into Node.js core for v7 or v8.
Syntax
0: Grant1: Warn2: Deny (throw)3: Abort (Exit){ "*": { "default": 0, "modules": { "dns": 2 }, "bindings": { "cares_wrap": 2 } }, "module_a": { "modules": { "dns": 0, "fs": 2 }, "bindings": { "cares_wrap": 0, "fs": 2 } } }/cc @rvagg @trevnorris