jorangreef / sudo-prompt Goto Github PK
View Code? Open in Web Editor NEWRun a command using sudo, prompting the user with an OS dialog if necessary.
License: MIT License
Run a command using sudo, prompting the user with an OS dialog if necessary.
License: MIT License
Hey,
Thanks a lot for producing this package, super-helpful!
I've run into an issue when running a command on a Windows machine where the user folder contains an ampersand. Please see the logs below.
From what I can see in your code the path is already wrapped in double-quotes?!
Let me know if you need any more information or help.
Thanks!
Command failed: powershell.exe Start-Process "C:\Users\MARK&R~1\AppData\Local\Temp\fe6c94de20f19bcf3d07c504ca9012d1\execute.bat" -WindowStyle hidden -Verb runAs
At line:1 char:28 Start-Process C:\Users\MARK&R~1\AppData\Local\Temp\fe6c94de20f19bcf3d ...
The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks ("&") to pass it as part of a string.
I can't seem to get this to pull up a dialog box even in the simplest of cases. If I try the following:
sudo.exec('touch /etc/test.txt', function(err){if(err)console.log(err)})
It will silently fail with no prompt, and nothing on the errors object.
I did notice one thing that may be relevant.
If I attempt the command in the console window sudo touch /etc/test.txt
then I get a prompt to enter the password. After I have entered the password using the command window, the programmatic version begins to work with sudo commands (but will never properly prompt for a password). I would really like to figure out why this isn't working and was wondering if you had any debug suggestions.
I've also tried mixing sudo.touch
in various locations without success.
Thanks!
Module is really great but unfortunately on Windows it has problem with regional characters. It cannot find files in path. In Powershell on my computer I have encoding OEM 852. Javascript use utf-8 encoding and it is used to save .bat files in this module. I think it cause in differences in regional characters like Polish ąę or Danish å.
I tried saving command.bat encoded to OEM 852 (i provided encoded buffor instead of string with null encoding part) but it didn't helped. I also tried adding chcp 1252 or chcp 65001 commands to change encoding in Powershell instance to UTF-8 but it hasn't helped either.
I've commented out removing files to check them manually in temp localization. chcp works fine when i run just command.bat. Problems start only when it is run like in extension from another .bat file.
I've tried running only command.bat from powershell with -Verb runAs option but then I get error with info that user didn't provided access, but there wasn't any UAC prompt.
Do you have any ideas how to fix problem with regional characters?
User-Names with an "-" are possible on mac but not allowed by the validation check. Exchanging [a-z0-9 ] with [a-z0-9 -] solves it for mac. Although I do not know if it is causing problems on other systems.
function ValidName(string) { // We use 70 characters as a limit to side-step any issues with Unicode // normalization form causing a 255 character string to exceed the fs limit. if (!/^[a-z0-9 -]+$/i.test(string)) return false; if (string.trim().length === 0) return false; if (string.length > 70) return false; return true; }
was frustradet, asked google
found it, was so happy
tried it with so much hope
not supported, so sad...
I've seen some issues when running this module on GNU/Linux systems without a full featured desktop environment (e.g: Arch Linux + i3). In these kinds of systems, the user doesn't always have a graphical PolKit authentication agent, which causes pkexec
to default to asking for the password using stdin, which won't be seen from the context of a desktop application.
I'd be great if we could make this module check if there is an available PolKit authentication agent, and default to other graphical sudo implementation, or throw a warning otherwise.
ps aux
seems to output useful information about available authentication agents, but I bet there should be a more reliable way using PolKit tooling directly.
As an example, this is what I get on Ubuntu 16.04:
parallels@ubuntu:~$ ps aux | grep polkit
root 840 0.0 0.1 303876 6600 ? Sl 07:35 0:10 /usr/lib/policykit-1/polkitd --no-debug
paralle+ 3766 0.0 0.6 656268 27080 ? Sl 07:36 0:02 /usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
paralle+ 28096 0.0 0.0 15940 944 pts/10 S+ 21:37 0:00 grep --color=auto polkit
According to https://github.com/jorangreef/sudo-prompt/blob/master/index.js#L20, sudo-prompt uses regular expression to detect whether to show a prompt dialog. But under different language environments this does not always work. So here is my temporary solution:
const SUDO_OPTION = {
name: APP_NAME,
process: {
options: {
env: { 'LANG': 'en_US.UTF-8' }
}
}
};
As described in the issue #289, I have an issue with Etcher.app.
It seems etcher uses sudo-prompt, but I cannot make it work because etcher is not able to grant requested sudo privileges.
As requested in the etcher's issue, I tried the following test and the step 7 did prompt fo my password :
sudo -k
sudo mkdir -p /var/db/sudo/$USER
sudo touch /var/db/sudo/$USER
sudo touch /var/db/sudo/$USER
Maybe this issue is related to the OS X 10.10.5 kernel local privilege escalation issue I did fix by adding a Defaults tty_tickets
in my /etc/sudoers
?
node version: v5.10.1
npm version: 3.8.6
platform: Darwin Merlin 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64 (OS X 10.11.4)
Hi,
I am working on Windows, my batch file has some if-else statement for different commands, for example,
IF condition1 (c:\Windows\System32\schtasks.exe /Create ...)
Else (c:\Windows\System32\schtasks.exe /delete ...)
I hope with sudo-prompt, we can pass parameters like the following syntax, so that I can verify the if condition above by comparing with the passed parameter value.
var sudo = require('sudo-prompt');
var options = {
name: 'Electron',
icns: '/Applications/Electron.app/Contents/Resources/Electron.icns', // (optional)
};
sudo.exec('echo hello', [args] ,options, function(error, stdout, stderr) {});
If with current package, there is other ways to achieve my goal, please let me know.
Thanks,
i want to run like this.
but only first command is running and other have error
var sudoP = require('sudo-prompt');
var options = {
name: 'Productivity app',
icns: '/path/to/icns/file', // (optional)
};
sudoP.exec('apt-get install -y xdotool', options, function(error, stdout, stderr) {
console.log("stdout",stdout,"stderror",stderr);
});
sudoP.exec('xdotool', options, function(error, stdout, stderr) {
console.log("stdout",stdout,"stderror",stderr,"error",error);
});
sudoP.exec('apt-get install -y gawk', options, function(error, stdout, stderr) {
console.log("stdout",stdout,"stderror",stderr,"error",error);
});
Hi Joran. I have a small issue. You wrote in documentation that if tty_tickets is disabled than we'll ask password only once but also with disabled tty_tickets promt shows for each exec call but if I input some command in terminal after that I can use exec command much times without password promt.
Also maybe do you have some ideas how to resolve troubles with enabled tty_tickets? Because I want to ask root permissions only once and after use needed commands also after close/restart app (sudo-prompt + electron).
As title. I am wondering if you have any suggestion for windows?
I'm attempting to execute a script within my Electron app by using Electron's "run as node" functionality, controlled by the ELECTRON_RUN_AS_NODE=1
environment variable, however this variable doesn't seem to be considered by sudo-prompt
when executing the final command.
By some inspection, it looks like the applet executes sudo -n <command>
. Can we change this to include sudo
's -E
option, to preserve the environment?
Hi, the pkexec
dialog is correctly being shown, however no matter the password I pass, I get this error.
After some investigation, turns out that users can't run graphical applications with pkexec without explicitly configuring it to do so.
However, turns out I can workaround this by running pkexec
like this: pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY
. See http://askubuntu.com/a/332847.
This almost works, since relative arguments to the program passed through pkexec
get resolved from /root/
, and I have no idea how to solve this (tried everything I could think of).
I'm sending a PR to inherit the environment variables mentioned above, and will use absolute paths for my arguments unless you can think about anything else.
Hey,
Thanks for your work on this . I'm trying to use this sudo-promt to start a child process on a raspberry PI, tha needs sudo to execute.
I am trying this :
var sudo = require('sudo-prompt');
const execFile = require('child_process').execFile:
const child = sudo.execFile('/home/pi/Desktop/fm_transmitter/bin/Release/fm_transmitter' , ['high_dash.wav', '103.40'], (error,stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
}
But is returning TypeError: sudo.execFile is not a function
I'm also trying:
var sudo = require('sudo-prompt');
const child = sudo.exec('/home/pi/Desktop/fm_transmitter/bin/Release/fm_transmitter', ['high_dash.wav', '103.40'], (error,stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
}
But that is returning:
Usage: /home/pi/Desktop/fm_transmitter/bin/Release/fm_transmitter [FILE] [Frequency] which are the two arguments required. I'm trying to figure out where I should place these?
As you've probably noticed, I'm technically out of my debt here but any insights would be greatly appreciated!
I'm doing a sudo.exec('echo a name', function (err) {console.log(err)})
and keep getting the same error without any prompt being shown.
Error: Command failed: /bin/sh -c sudo -n echo 'en2'
sudo: a password is required
sudo: a password is required
at ChildProcess.exithandler (child_process.js:209:12)
at emitTwo (events.js:87:13)
at ChildProcess.emit (events.js:172:7)
at maybeClose (internal/child_process.js:764:16)
at Socket.<anonymous> (internal/child_process.js:319:11)
at emitOne (events.js:77:13)
at Socket.emit (events.js:169:7)
at Pipe._onclose (net.js:469:12)
Mac 10.10.5
process.env['USER'] is defined
os.tmpdir() is writable by the user
You can see the issue on https://github.com/ghostbar/shakeitoff
EDIT: Already tried setting the title name, as well.
Dear author and other developers,
I find sudo-prompt
a very useful and handy tool. Recently I encounter an issue while using it:
I have an node application that will launch a process A, and process A will fork a new process B. And then process A will terminates. (Process B is not sub-process of process A)
If I run process A in Terminal directly, I can see it quit normally as well. However when I use sudo-prompt on Mac, the Sudo App does not exit, and the node callback is not called unless I kill process B.
May I know how should I get Sudo App quit and node callback called while keep a separate process B running?
Hi,
I've been using sudo-prompt
for a couple of days in an Electron application, however it suddenly started failing with the following error:
$ npm start
> [email protected] start /Users/jviotti/Projects/resin/herostratus
> electron lib/herostratus.js
Command failed: /bin/sh -c sudo -n /Users/jviotti/Projects/resin/herostratus/node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron lib/herostratus.js
env: node\r: No such file or directory
Code:
sudoPrompt.setName('Herostratus');
sudoPrompt.exec(process.argv.join(' '), function(error) {
if (error) {
console.error(error.message);
process.exit(1);
}
// Don't keep the original parent process alive
process.exit(0);
});
The command that files is this one: https://github.com/jorangreef/sudo-prompt/blob/master/index.js#L30, however by running it manually myself I can see it gives the expected output:
$ sudo -n /Users/jviotti/Projects/resin/herostratus/node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron lib/herostratus.js
sudo: a password is required
Is there a way a carriage return is slipping in any env node
hash bang?
Currently we are using sudo prompt in parts of our application.
Is is there a way to return the pid of a process that is started with sudo prompt, so we can store it.
The value: We would like an easy way to also shutdown / verify all things started with sudo prompt are shutdown properly. If we have the pid it would be easier to kill it.
Open to other suggestions (as we currently using grep)
Even if you're within the set timeout, it will still prompt for a password. If you're using a sudo
keep alive via sudo -v
running on an interval, the program will continually create new prompts.
Any idea what would be causing this?
Hey guys,
Someone please help me know how to store password for next time run command?
(my app alway ask permission when run any command, it is not good for UI)
Thanks!
Hello there,
Thanks for your great work on the sudo-prompt module!
I’m building an Electron App that needs to send UDP packages and I’m using a module called Cap to access an interface, open it and send the package through it. Locally, it runs without any problems, but when running the App on other Macs (I sent the App.app to a couple of fellows to help me with the testing) an error message appears Uncaught Error: (cannot open BPF device) /dev/bpf0: Permission denied.
If they start the App via the Terminal running sudo Electron-app.app/Contents/MacOS/Electron-app
no error is thrown, so definitely it’s an issue related to User Permissions and that is why I searched for available sudo modules for Electron.
I don’t need to run a specific command as root, but I do need to grant the App with sudo privileges on this specific section (specifically on the c.open()
line -which is throwing the error-):
var Cap = require(‘cap’).Cap,
c = new Cap(),
device = Cap.findDevice(‘192.168.0.20’),
filter = ‘arp’,
bufSize = 10 1024 1024,
buffer = new Buffer(65535);
var linkType = c.open(device, filter, bufSize, buffer);
I’m trying to use your package this way:
sudo.exec(‘su’, options, function(error, stdout, stderr) {
linkType = c.open(device, filter, bufSize, buffer);
})
in order to get the required privileges but it seems not to be working (or I’m using it wrong). Have you seen or know a way to start the complete Electron App with sudo privileges (asking for the root password on the startup) or is there something I’m missing?
Thank you very much in advanced!
I’ll be waiting for your response.
Have been struggling with getting sudo-prompt to work, and finally figured out why. My environment's timestamp timeout was set to 0. This resulted in attempt()
's check of the if (/sudo: /i.test(stderr))
condition always matching, and throwing an error on the second command execution.
It would be nice if there was either a) a workaround, or b) a check for this condition within sudo-prompt and subsequent user notification.
For example, the following bash will give a permissions fail:
sudo-prompt.exec("echo 'some text' > /Library/some-file.txt")
It's easily fixed by doing:
sudo-prompt.exec("bash -c \"echo 'some text' > /Library/some-file.txt\"")
Perhaps sudo-prompt should do this (bash -c
) at the module level instead? String escaping may need a little bit of thought but should be ok.
Using elementary OS 0.4.1 (based on Ubuntu 16.04) over here.
I'm trying to run a bash script via sudo-prompt.exec
, and after entering my password the app throws an error saying User did not grant permission.
Script would be launched from an Electron environment, if that is at all important. The GUI application itself is NOT run with administrator privileges.
I know it's not much to go on, but I've no idea what could be wrong and was hoping to get some pointers (again 😄 )
Hey there,
thanks for this awesome package!
I have a homebrew script to switch between php versions on my macbook.
You can't execute the script with sudo, so the normal command would be phpswitch.sh 70
in order to switch to php 7.0.
But at the end of the script the apache config is updated and the apache will be restarted. So the script needs root rights.
I search for some workaround and I found the possibility to call sudo -v
first, so the root password is prompted and then executing the phpswitch script, because then the timestamp for sudo is already valid.
Now the problem with this workaround: with your package I cant call sudo.exec('sudo -v')
nor sudo.exec('-v')
.
Do you have any idea how I could achieve this?
Thanks in advance!
Instead of executing a line of code can I execute a file?
Hello,
Scenario: I have several commands to be executed along with my application and they all needs admin privilege.
Problem: I would like to use your module, but whenever I run a command through it, it is asking for the password while I just want to have the prompt once at the beginning.
Do you have any idea?
Is it possible to find somewhere the applet source code?
Is there a way to get the output of a long running command (output stream) on Windows before it exits?
Hi there,
Thanks for creating that package, it's really handy.
However, I have a small issue with it.
I need to run 2 commands with root rights.
If I do
sudo.exec('command1', options, function(error, stdout, stderr) {
if (!error){
sudo.exec('command 2', options, function(error, stdout, stderr) {
if (!error){
} else {
console.error(error);
console.log(stderr);
}
});
} else {
console.error(error);
console.log(stderr);
}
});
It works, but the app will ask twice for the root password, which is annoying for the users.
I tried doing
sudo.exec('command1; command2', options, function(error, stdout, stderr) {
if (!error){
} else {
console.error(error);
console.log(stderr);
}
});
So they run at the same time, but that fails. The command2 fails because it doesn't have root rights.
Happening on Ubuntu 16.04
Am I missing something ?
sudo-prompt
makes use of the cp
command to perform a copy operation on the applet.app
embedded in this module:
/// https://github.com/jorangreef/sudo-prompt/blob/master/index.js#L46
var command = '/bin/cp -R -p "' + source + '" "' + target + '"';
Node.child.exec(command, end);
When an electron application is packaged as an asar
, the cp
command will not be able to find the file and will throw the following error:
Is anything preventing us from implement this using Node's fs
module instead, which is automatically patched by electron to understand asar
archives by (extracting the file into a temporary location)?
It would be great if you could export a function that returns a permanent path to the bundled applet for MacOS, so that the SUDO_ASKPASS
environment variable can be set to use it. I have several third-party scripts that use sudo -A
if a tty isn't present, and right now they're timing out.
Hey there,
How hard would it be to allow the child process to be spawned instead of executed on this module? I didn't take a look myself, but I suspect it's just a matter of spawning the final command built by this module in Attempt()
.
The use case is that we've figured out how to call the process that needs the elevation in Etcher, instead of the full application, but we need to consume its stdout
and stderr
while it runs in order to get state information.
In my mind, the sudoPrompt.spawn()
function should just return the spawn
object for the client to handle.
What do you think about this addition? Happy to collaborate on it.
Is there a way to clear the sudo
cache to force the prompt to appear? Maybe it's worth to document in the README since it can be quite helpful when debugging.
simon.mbp: ~
🍉 sw_vers
ProductName: Mac OS X
ProductVersion: 10.11.6
BuildVersion: 15G1611
simon.mbp: ~
🍉 sudo cat /etc/sudoers
...
ALL ALL=(ALL) NOPASSWD: /usr/sbin/networksetup, /sbin/route
...
I can execute sudo /sbin/route
command in terminal without password. But "sudo-prompt" require password when execute the same command.
Any advice?
From balena-io/etcher#1579.
Not sure what's needed for this, but it'd indeed be very cool if sudo-prompt
can support Touch ID authentication on newest MacBooks.
Hello,
I am having a problem with asking permissions:
First time that app is opened, works correctly, but second time sudo-prompt don't ask for user and password, and obviously, fails. I have to restart, and then it is called again.
My command is:
sudo chown -R User '/Applications/Example/Plugins/'
var command = "chown -R User '/Applications/Example/Plugins/'";
sudo.exec(command,....
It is showing this message:
Command failed: /usr/bin/sudo -n -E -- chown -R User '/Applications/Example/Plugins/'
User is not in the sudoers file. This incident will be reported.
Command is working correctly in shell, that asks for password every time.
Thanks.
Is it possible to end the spawned process?
Node's exec
isn't suitable for long-running processes due to that max buffer size.
Will there be an issue launching a process that could stay alive 24/7 through sudo-prompt
, since there is no support for spawn
? As in, does sudo-prompt
's exec
work differently?
When i try to restart the app as root i get the error Error: User did not grant permission
, although I did enter the password and clicked the OK button.
// ... imports
var sudo = require('sudo-prompt');
const app = require('electron').remote.app;
console.log('app exe', app.getPath('exe'));
// ... check if started programm as root
var user = process.env['USER'];
if (user === 'root' || user === 'administrator') {
console.log('started as root');
} else {
// try restarting as root
sudo.exec(app.getPath('exe'), {name: 'Appname'}, function(error, stdout, stderr) {
stdout && console.log('output:', stdout);
stderr && console.log('error:', stderr);
error && console.log('error:', error);
if (!error) {
app.exit(0)
} else {
// Error: User did not grant permission
alert('Sorry we could not restart the app with administrator/root privileges, which is necessary for certain functions.');
}
});
}
Any ideas?
But no matter what, thank you so much for creating this!
I really do not know a lot of linux, but i thought with try and error it may works. But finally giving up, all failed:
t = 'script/to/start.sh';
startNew(t);
startNew(app.getPath('exe'));
startNew(t + ' &');
startNew(app.getPath('exe') + ' &');
startNew('nohup ' + t);
startNew('nohup ' + app.getPath('exe'));
startNew('nohup sudo ' + t + ' &');
startNew('nohup sudo ' + app.getPath('exe') + ' &');
startNew('fork || exec "' + app.getPath('exe') +'"'); // starts at least the app new, but not as root :(
startNew('echo "" | fork || exec sudo -S "' + app.getPath('exe') +'"');
startNew('sudo -S fork || exec "' + t +'"');
startNew('exec "' + app.getPath('exe') + '"');
startNew('exec "' + t + '"');
ok, got it i should learn to read the readme and look into the closed issues #15 ;) non-graphical terminal commands only
. But if somebody has an idea let me hear it.
Hello,
I had permission errors like this "Uncaught Error: EACCES: permission denied, open" or like this "Uncaught Error: EACCES: permission denied, mkdir".
And for this reason, I use this npm module (sudo-prompt)
My code is ..
var toExec = "chown -R $(whoami) "+ pathToCopy;
sudo.exec(toExec, options, function (error, stdout, stderr) {
startCopying();
});
But I receive "command failed"
What am I doing badly?
Thanks
Hey guys,
Someone please help me how to get ERROR CODE when run command error?
Thanks!
Hi @jorangreef:
Node.js has both synchronous and asynchronous functions to execute commands. In your package, is the synchronous function available?
Hi Joran,
Many thanks for creating the package. It's very handing with us.
However, on windows os, when running this lib, windows asks permission as "exe.cmd" name. Have we optioned for a set this name? Thanks
@craig-mulligan tried running the usage example:
sudo.exec('echo hello', {},
function(error, stdout, stderr) {
if (error) throw error;
console.log('stdout: ' + stdout);
}
);
But all he gets is:
/Users/gaudi/work/sudo-test/index.js:8
if (error) throw error;
^
Error: User did not grant permission.
at ReadFileContext.callback (/Users/gaudi/work/sudo-test/node_modules/sudo-prompt/index.js:316:49)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:367:13)
without any prompt at all.
I unzipped the applet to see if I could debug things myself, but got stuck a bit. The AppleScript file calls sudo-prompt-script
, which then calls /bin/bash sudo-prompt-command 1>stdout 2>stderr
, but I can't see the source of sudo-prompt-command
anywhere.
Maybe you have some suggestions to debug this further?
I am trying to get this to work with electron on a macOS Sierra machine, but I am not having any luck.
Here is my code
function handleSudo() {
return new Promise((resolve, reject) => {
var sudo = require('sudo-prompt');
var options = {
name: 'Electron',
icns: '/Applications/Electron.app/Contents/Resources/Electron.icns', // (optional)
};
sudo.exec('echo hello', options, (error, stdout, stderr) => {
winston.info(error);
winston.info(stdout);
winston.info(stderr);
});
});
}
and here is what I get from the output
info: errno=-2, code=ENOENT, syscall=open, path=/Applications/Electron.app/Contents/Resources/Electron.icns
info:
info:
I do not get a popup, and only the error variable has any data, and I am not sure how to understand it.
Hi!
Just curious as to how I would detect if the command terminates. I tried setting the exec to a variable and doing variable.on(....) as I would to a normal async child process.
Is there any way I can do that?
Does this run the command asynchronously?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.