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

feat: new alternative to exec #524

Closed
wants to merge 6 commits into from
Closed

feat: new alternative to exec #524

wants to merge 6 commits into from

Conversation

nfischer
Copy link
Member

@nfischer nfischer commented Oct 9, 2016

Update July 2019

Notice: this is not a security vulnerability, this is a prototype implementation for a feature request. Please see #945 for more context regarding security advisories.

Original message

Add a new command to launch external shell commands, providing a less vulnerable
alternative to exec(), with cross-platform globbing.

I'd love community input on the design of the new API, if this is an agreeable name, etc. This implementation would work well with shelljs-exec-proxy (see nfischer/shelljs-exec-proxy#2), which might be a better API alternative for Node v6+ users.

I believe this, in conjunction with set('-f'), should solve all the relevant security flaws surrounding command injection and unexpected globbing. Globbing is enabled by default in this implementation, for the sake of providing a consistent API across all commands.

This relies on a JS-based implementation of globbing, which is an improvement on exec(), which inconsistently provides globbing on unix but not on windows.

Fixes #143
Fixes #495
Fixes #103

I believe this should also help with #175, #5, shelljs/shx#68, and probably some others.

@nfischer nfischer added feature exec Issues specific to the shell.exec() API security labels Oct 9, 2016
@nfischer nfischer added this to the v0.8.0 milestone Oct 9, 2016
@nfischer
Copy link
Member Author

@ariporad Please go ahead and start reviewing. The fixes for the test failures should be pretty trivial (some of them are with the tests themselves). This way I can knock out all the fixes at once.

@ariporad
Copy link
Contributor

LGTM!

This is really great, I think that we should consider building a new exec on top of it.

@nfischer
Copy link
Member Author

I'll see if I can figure out why this is failing on unix. This will never pass on v0.10, so I think it's time to remove that from Travis (the version already wasn't supported by us).

This is currently blocked by #525 #523 #522 and shelljs/shx#81, so help with those issues would be appreciated.

@detailyang
Copy link

Hi, @nfischer.

what's time your PR will be merged into master?

@nfischer
Copy link
Member Author

nfischer commented Dec 8, 2016

@detailyang thanks for the follow up. I'll try to put in some work on this PR this week. I believe most of the blocking issues are now resolved.

This just needs to be rebased on top of master and the tests need to be rewritten to use ava.

@nfischer
Copy link
Member Author

This is now rebased and tests are refactored.

This is currently blocked on #633, and I need to check that I've properly taken advantage of the PRs that this was previously blocked by.

@nfischer
Copy link
Member Author

TODO list (in no particular order):

  • possibly rename realtimeOutput to interactive (taken from this comment)
  • fix TODOs in the code
  • get rid of nodeBinPath (this was taken care of in Move execPath into common #633)
  • make sure it handles interactive input nicely
  • clean up commented code
  • deprecate exec
  • rebase off dev
  • merge into dev
  • fix skipped tests
  • write tests for interactive output (maybe check that ls --color=auto prints colored output)
  • decide whether or not to return control characters in the return properties (like colors inside result.stdout)

@zhiqunq
Copy link

zhiqunq commented Mar 22, 2017

Hi, @nfischer.

what's time your PR will be merged into master?

@nfischer
Copy link
Member Author

@zhiqunq this is still slated for v0.8. I haven't had time to pick it back up. I'm waiting to wrap this up so that I can be confident it fixes all of the major issues with exec. If you'd like to help, feel free to test this out and see if it meets your needs or if it has any issues.

@wclr
Copy link

wclr commented Mar 25, 2017

Hope to see this soon!

@nfischer
Copy link
Member Author

Unfortunately, I don't have a whole lot of time for OSS right now, so this will probably take a month or two.

src/child.js Outdated
// Wait to exit until all other work has been finished, like closing IO streams
function delayedExit(code) {
setTimeout(function () {
process.exit(code); // let streams close before ending
Copy link

@bruce-one bruce-one Jun 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this use process.exitCode = code instead?

Based on the warning from https://nodejs.org/api/process.html#process_process_exit_code

It is important to note that calling process.exit() will force the process to exit as quickly as possible even if there are still asynchronous operations pending that have not yet completed fully, including I/O operations to process.stdout and process.stderr.

(Which seems to imply it might not actually let the streams close/flush correctly?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is better, thanks!

On second thought, I'm not completely sure if delayedExit would've worked. It posts a timeout to work around this, but that might not actually work if streams are buffered after the process finishes.

@shaunbaruth
Copy link

@nfischer Thanks for your work on this. It's a very useful feature. Looking forward to it.

@brennoo
Copy link

brennoo commented Aug 16, 2017

@nfischer thanks for good work here, we still good to have it in v0.8 ?

@nfischer
Copy link
Member Author

Update:

I'm trying to harden shell.exec() a bit for the v0.8 release (#782). It'll have some (not all) of the improvements from this PR (source code script instead of writing to a file, reducing file IO), but the goal is a backwards-compatible API.

I almost have that working, and it's cleaning up quite a bit of code. After we land that, there should be a little bit of clean-up work, and then it should be easy to revisit this PR (and build a secure-by-default API!).

Thanks for your patience!

@nfischer nfischer modified the milestones: v0.8.0, v0.9.0 Oct 20, 2017
@nfischer
Copy link
Member Author

Bumping this back to v0.9. I want to release the hardened exec changes under v0.8 (still a minor security improvement). This will give us a chance to fix any bugs, and move forward with the new API.

@evenstensberg
Copy link

Any update for this?

@nfischer
Copy link
Member Author

Updates:

@nfischer
Copy link
Member Author

Ok, so v0.8 is released! If you can, please try out the release, let us know if there are any new issues with exec. I'm going to dedicate time over the next couple weeks on this PR.

@igrayson
Copy link

igrayson commented Jun 6, 2018

We're looking forward to switching over to this more secure execution method! Any update?

@nfischer
Copy link
Member Author

nfischer commented Jun 7, 2018

@igrayson I'm currently finishing up a local prototype. I will post a design doc in the next 2-ish weeks and upload a PR around the same time. Sorry this has dragged on so long, but this is indeed still on my radar (and thanks for asking about progress).

@nfischer
Copy link
Member Author

nfischer commented Jul 2, 2018

Thank you all for your patience. I'm currently polishing up my prototype (it is going to take a slightly different approach from this PR). I've written a design doc, and I invite you all to comment on the design (in particular, please check the proposed design will work for your use case).

Next steps:

  • upload my prototype in a new PR, close this one
  • land the initial prototype, and implement the extra "modes" mentioned in the design doc in further PRs
  • the first shelljs release with shell.cmd() will be the first release we deprecate shell.exec()

@nfischer
Copy link
Member Author

nfischer commented Jul 3, 2018

New PR is up at #866! Closing this PR (and the other PR should be in a much more landable state than this one).

@nfischer
Copy link
Member Author

nfischer commented Jul 1, 2019

If you've found this PR, please do not consider this a security fix. ShellJS does not have a security "vulnerability" to resolve, we have a poorly-designed API (shell.exec()) that must be used with care to be considered secure. We've updated documentation to warn against improper usage and have provided security guidelines to help dependent modules use this safely. Please consult #945 for more information.


This PR is an obsolete attempt to provide a better API, but such a better API is not required for your modules to be secure.

@shelljs shelljs locked and limited conversation to collaborators Jul 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
exec Issues specific to the shell.exec() API feature security
Projects
None yet