Let's be care-file out there

Re-visiting the file node ahead of 0.20 I'm thinking that we ought to add a blocklist capability to allow the owner to stop the file node from reading and writing where maybe it shouldn't. Right now the file node can potentially read any file that it has operating system permission to access.

I'm thinking that the filename should be checked to see if it's path or filename is blocked before reading or writing is allowed. By using a glob engine like micromatch (https://github.com/micromatch/micromatch) we could allow matching to both directories (like /etc) or files (like the settings.js file) in an easy to use way.

I think that there are two things to consider... some should be hard-coded into the node (ie can't be undone) and some should be specifiable in settings.js so users can remove the initial default list and allow more potentially dangerous actions. I'm thinking the Node-RED user directory should be hard-coded, and things like /etc/ ~/.ssh/ soft-coded.

So - thoughts please - and what/where should be hardcoded and what/where user settable but default.

Really liking the idea of being able to control where the file node can reach into.

It would be great, though, to have an option that is very straight-forwards so that beginners and non-techie folk don't have to get their heads around "glob" :slight_smile:.

So a setting that lets you easily and simply specify a single root folder and restricts it to just that (and sub-folders of course). This could simply be presented as a commented example as with many of the other settings. This would be best in settings.js I think so that it is hidden from the admin ui - giving 2 levels of control.

Of course, you would also then want to allow a more complex setting in the way that you've mentioned so that more advanced uses would be easy enough using multiple "globs" for inclusion and exclusion.

In order for this not to break existing deployments. I think that the default will probably have to be null so that everything is allowed. Though actually, thinking about it, since existing deployments would already have a settings.js file, you could in fact change the template settings file to include something if you wanted to. Would a sensible default be to include the userDir folder but exclude the Node-RED system files and folders (flows, credentials, projects, etc)?

I'm in two minds about about excluding /etc and so on. I can see the benefit of excluding them by default but I worry about the complexity and system overheads. Especially when having to think about multiple platforms. Would need additional, multi-platform testing and some performance testing too.

Really, we should be improving the security documentation and installation scripts so that installations are not using global modules and, at least on Linux systems, are using dedicated user ID's more in keeping with web server and database deployments. That way, the system itself wouldn't have access to files that it shouldn't do.

Anyway, a few thoughts to mull over or ignore at leisure. Really good idea though and well worth getting right.

You raise an interesting point.

I had been thinking of this as a deny list - but the risk is always there that we miss something.

Flipping it on its head and making it an allow-list would be worth considering. It makes the node completely locked down by default and has to be consciously opened. Is that too onerous? Not sure.

You are right this is just one aspect of security. There is certainly an exercise to be done around reviewing our default security story across the whole of Node-RED - but I don't want to derail this topic on the File node.

I suspect the right answer will need both, in order to make the logic simple enough to understand - think Apache allow/deny lists (which are still horrible but hey).

eg - allow this overall subdirectory - but block sub-subdirectory/a and file b within it.

1 Like

@dceejay "Let's be care-file out there"...
Hill Street Blues???
I didn't think you were that old :wink:

1 Like

Haha, many of us are easily "that old"! :older_adult:

Best Show Ever !!

Anyway - my 2cents - i think upon install of the node it should create a subdirectory in the home directory of NR and that is the only directory by default it is able to write into.

Any changes to that default behaviour would be best done in the settings.js file.

This would then be OK across OS's

I would think in the settings.js file you might have a switch to turn on an Intermediate and then advanced control - to enable globbing etc - but MOST users will get into trouble with this, so an intermediate setting would be to allow specific directories and/or subdirectories (but not root as most newbies would end up doing) - each of the parent directories would need to be specified from the root down (or windows drive letter down)

Craig

I agree - for new installations. Obviously, for updates this cannot be the case as it may break things. A warning would be helpful in this instance.

Again, I agree, this seems to be the safest place to do this.

It has to be!

Or simple and advanced :slight_smile: or maybe all 3?

So - starter for 10

  • Always has access to {user-dir}/files directory (not matter what other settings are)
  • if not in that directory then test
    • Allowlist - array - if filename matches anything in the array it is allowed to access that dir/file
  • then test
    • Blocklist - array - if filename matches anything in the array it is not allowed to access

That way you could allow access to my-home-dir/* but block my-home-dir/.node-red/* - while still allowing access to the default my-home-dir/.node-red/files/*.

As this is a major change to default behaviour...

1 - if the .../files dir is now default - should someone entering foo.txt into the out node expect it now to just be in .../files/foo.txt - i.e. no longer need to fully path the name in the config?

2 - for existing users - we can detect lack of a setting in settings.js - and do what ? just set allow all ?

All 3

default behaviour is to enable only to the newly created subdirectory (for new Installs),
Intermediate is to enable an include list (full paths) which would include subdirectories - but not allow root access
advanced would enable everything - includes/allows/block with globbing.

  1. I think you need to set the default as just that - no path needed etc - straight within the Node-red directory
  2. Yep if no settings in settings.js - place a big warning in the node in the pallette help and allow all

i guess some sort of timeframe when that legacy behaviour will be turned off.

:thinking: what is the actual default relative path ? I think it's currently where flows.json file is located ? So wouldn't this break existing NR-apps ?

Yes if you want to avoid breaking existing NR-apps but you could issue a (red) security warning in the console when starting NR ...

Generally, it is considered the job of the OS to restrict/allow access to files - not a programming language.

No programming language that I know of, does any blocking

(Well - Scratch has an .ini file that can restrict access to drive letters but that was put in place before Windows got serious about file/folder permissions :slight_smile: )

PHP does, depending on the configuration.

But then Node-RED isn't just a programming language is it?

So there are plenty of tools that do restrict access to parts of the filing system. Notably web servers for example. It is a very simple and effective way of adding security.

The OS can indeed prevent access and I've already mentioned that there are other things we need to do to help improve the security of Node-RED. But if you want Node-RED to have access to parts of the OS - perhaps read-only - as many of us do, then obviously another way to limit that is very helpful.