VYPR
Critical severityNVD Advisory· Published Jun 4, 2018· Updated Sep 16, 2024

CVE-2017-16042

CVE-2017-16042

Description

Growl before 1.10.2 passes unsanitized user input to exec(), allowing arbitrary command execution.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Growl before 1.10.2 passes unsanitized user input to `exec()`, allowing arbitrary command execution.

Vulnerability

Growl, a Node.js package for sending Growl notifications, before version 1.10.2 does not properly sanitize input before passing it to the exec() function from child_process. This allows an attacker to inject arbitrary shell commands through specially crafted notification messages, titles, or image paths [1]. The vulnerability is present in versions prior to the fix merged in commits such as d71177d, which replaced exec with spawn and removed unsafe quoting functions [2].

Exploitation

An attacker who can control the msg, title, or image parameters passed to the growl() function can inject shell metacharacters. For example, a message containing backticks or command substitution characters (e.g., ` malicious_command ) would be executed by the shell when exec is called. The fix eliminated the use of quote() and passed arguments via spawn`'s array interface, preventing shell injection [2]. No authentication is required beyond the ability to invoke the library with attacker-controlled input.

Impact

Successful exploitation leads to arbitrary command execution on the system running the vulnerable Node.js application. The attacker can execute shell commands with the privileges of the process that calls growl(), potentially leading to full system compromise depending on the application's permissions [1].

Mitigation

The vulnerability is fixed in version 1.10.2 (and subsequent releases) by replacing exec with spawn and removing unsafe string quoting [2]. Users should upgrade to version 1.10.2 or later. If upgrading is not immediately possible, avoid passing untrusted input to the growl() function [3].

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
growlnpm
< 1.10.01.10.0

Affected products

2
  • ghsa-coords
    Range: < 1.10.0
  • HackerOne/growl node modulev5
    Range: <1.10.2

Patches

1
d71177d5331c

Fix to resolve the command injection vulnerability. (#62)

https://github.com/tj/node-growlZsolt ImreJul 13, 2017via ghsa
3 files changed · +31 27
  • History.md+5 0 modified
    @@ -1,4 +1,9 @@
     
    +1.9.3 / 2016-09-05
    +==================
    +
    +  * fixed command injection vulnerability
    +
     1.7.0 / 2012-12-30 
     ==================
     
    
  • lib/growl.js+25 26 modified
    @@ -4,12 +4,11 @@
      * Module dependencies.
      */
     
    -var exec = require('child_process').exec
    +var spawn = require('child_process').spawn
       , fs = require('fs')
       , path = require('path')
       , exists = fs.existsSync || path.existsSync
       , os = require('os')
    -  , quote = JSON.stringify
       , cmd;
     
     function which(name) {
    @@ -127,7 +126,7 @@ exports = module.exports = growl;
      * Node-growl version.
      */
     
    -exports.version = '1.4.1'
    +exports.version = '1.9.3'
     
     /**
      * Send growl notification _msg_ with _options_.
    @@ -189,18 +188,18 @@ function growl(msg, options, fn) {
             flag = flag || /^png|gif|jpe?g$/.test(ext) && 'image'
             flag = flag || ext && (image = ext) && 'icon'
             flag = flag || 'icon'
    -        args.push('--' + flag, quote(image))
    +        args.push('--' + flag, image)
             break;
           case 'Darwin-NotificationCenter':
    -        args.push(cmd.icon, quote(image));
    +        args.push(cmd.icon, image);
             break;
           case 'Linux':
    -        args.push(cmd.icon, quote(image));
    +        args.push(cmd.icon, image);
             // libnotify defaults to sticky, set a hint for transient notifications
             if (!options.sticky) args.push('--hint=int:transient:1');
             break;
           case 'Windows':
    -        args.push(cmd.icon + quote(image));
    +        args.push(cmd.icon + image);
             break;
         }
       }
    @@ -230,61 +229,61 @@ function growl(msg, options, fn) {
       switch(cmd.type) {
         case 'Darwin-Growl':
           args.push(cmd.msg);
    -      args.push(quote(msg).replace(/\\n/g, '\n'));
    -      if (options.title) args.push(quote(options.title));
    +      args.push(msg.replace(/\\n/g, '\n'));
    +      if (options.title) args.push(options.title);
           break;
         case 'Darwin-NotificationCenter':
           args.push(cmd.msg);
    -      var stringifiedMsg = quote(msg);
    +      var stringifiedMsg = msg;
           var escapedMsg = stringifiedMsg.replace(/\\n/g, '\n');
           args.push(escapedMsg);
           if (options.title) {
             args.push(cmd.title);
    -        args.push(quote(options.title));
    +        args.push(options.title);
           }
           if (options.subtitle) {
             args.push(cmd.subtitle);
    -        args.push(quote(options.subtitle));
    +        args.push(options.subtitle);
           }
           if (options.url) {
             args.push(cmd.url);
    -        args.push(quote(options.url));
    +        args.push(options.url);
           }
           break;
         case 'Linux-Growl':
           args.push(cmd.msg);
    -      args.push(quote(msg).replace(/\\n/g, '\n'));
    -      if (options.title) args.push(quote(options.title));
    +      args.push(msg.replace(/\\n/g, '\n'));
    +      if (options.title) args.push(options.title);
           if (cmd.host) {
             args.push(cmd.host.cmd, cmd.host.hostname)
           }
           break;
         case 'Linux':
           if (options.title) {
    -        args.push(quote(options.title));
    +        args.push(options.title);
             args.push(cmd.msg);
    -        args.push(quote(msg).replace(/\\n/g, '\n'));
    +        args.push(msg.replace(/\\n/g, '\n'));
           } else {
    -        args.push(quote(msg).replace(/\\n/g, '\n'));
    +        args.push(msg.replace(/\\n/g, '\n'));
           }
           break;
         case 'Windows':
    -      args.push(quote(msg).replace(/\\n/g, '\n'));
    -      if (options.title) args.push(cmd.title + quote(options.title));
    -      if (options.url) args.push(cmd.url + quote(options.url));
    +      args.push(msg.replace(/\\n/g, '\n'));
    +      if (options.title) args.push(cmd.title + options.title);
    +      if (options.url) args.push(cmd.url + options.url);
           break;
         case 'Custom':
           args[0] = (function(origCommand) {
             var message = options.title
               ? options.title + ': ' + msg
               : msg;
    -        var command = origCommand.replace(/(^|[^%])%s/g, '$1' + quote(message));
    -        if (command === origCommand) args.push(quote(message));
    +        var command = origCommand.replace(/(^|[^%])%s/g, '$1' + message);
    +        if (command === origCommand) args.push(message);
             return command;
           })(args[0]);
           break;
       }
    -
    -  // execute
    -  exec(args.join(' '), fn);
    +  var cmd_to_exec = args[0];
    +  args.shift();
    +  spawn(cmd_to_exec, args);
     };
    
  • package.json+1 1 modified
    @@ -1,6 +1,6 @@
     {
       "name": "growl",
    -  "version": "1.9.2",
    +  "version": "1.9.3",
       "description": "Growl unobtrusive notifications",
       "author": "TJ Holowaychuk <tj@vision-media.ca>",
       "maintainers": [
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.