Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/God/ForkMode.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,15 @@ module.exports = function ForkMode(God) {
};

try {
// Sanitize environment variables before passing to spawn().
// Node.js spawn() calls .toString() on all env values, which converts
// nested objects (e.g. axm_monitor, axm_options) to "[object Object]".
// Filter to only include primitive values (string, number, boolean).
// See: https://github.com/Unitech/pm2/issues/6073
var spawnEnv = Utility.sanitizeEnv(pm2_env);

var options = {
env : pm2_env,
env : spawnEnv,
detached : true,
cwd : pm2_env.pm_cwd || process.cwd(),
stdio : ['pipe', 'pipe', 'pipe', 'ipc'] //Same as fork() in node core
Expand Down
59 changes: 59 additions & 0 deletions lib/Utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,65 @@ var Utility = module.exports = {
return canonic_module_name;
},

/**
* Sanitize environment variables object for use with child_process.spawn().
*
* Node.js spawn() calls .toString() on all env values, which converts
* objects and arrays to "[object Object]" or comma-separated strings.
* This function filters out non-primitive values to prevent pollution
* of subprocess environment variables.
*
* @method sanitizeEnv
* @param {Object} env The environment object (typically pm2_env)
* @return {Object} A new object containing only string-safe entries
* @see https://github.com/Unitech/pm2/issues/6073
*/
sanitizeEnv: function(env) {
if (!env || typeof env !== 'object') {
return {};
}

var sanitized = {};

Object.keys(env).forEach(function(key) {
var val = env[key];

if (val === null || val === undefined) {
return;
}

var type = typeof val;

if (type === 'string') {
sanitized[key] = val;
}
else if (type === 'number' || type === 'boolean') {
sanitized[key] = String(val);
}
// Skip objects, arrays, functions, and symbols to prevent
// "[object Object]" from appearing in environment variables
});

return sanitized;
},

/**
* Check if a value is a primitive type safe for use as an env variable.
* Primitive types (string, number, boolean) can be safely converted to
* strings for environment variables. Objects, arrays, functions cannot.
*
* @method isEnvSafeValue
* @param {*} val The value to check
* @return {Boolean} True if the value is a primitive type
*/
isEnvSafeValue: function(val) {
if (val === null || val === undefined) {
return false;
}
var type = typeof val;
return type === 'string' || type === 'number' || type === 'boolean';
},

checkPathIsNull: function(path) {
return path === 'NULL' || path === '/dev/null' || path === '\\\\.\\NUL';
},
Expand Down
18 changes: 18 additions & 0 deletions test/fixtures/env-check.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Test fixture that outputs its environment variables as JSON.
* Used to verify that object properties are not passed as
* "[object Object]" to subprocess environment variables.
*
* @see https://github.com/Unitech/pm2/issues/6073
*/

// Output env vars so tests can verify them
process.send && process.send({
type: 'env:report',
env: process.env
});

// Keep the process alive
setInterval(function keepAlive() {
// intentionally empty
}, 100);
Loading