FlawOpen

flawopen.com/Command Injection/exec() vs execFile()

exec() ou execFile() dans Node.js : quelle différence ?

Guide de référence
Réponse courte

exec() reçoit une chaîne et l’exécute dans un shell : les pipes et jokers fonctionnent, mais les métacaractères d’une entrée non fiable peuvent aussi modifier la commande. execFile() lance directement le programme indiqué avec un tableau d’arguments et sans shell par défaut. Cela évite l’analyse par le shell, mais pas tous les risques : le programme cible peut interpréter un argument comme une option ou agir sur une valeur inattendue.

Comparaison

exec() — utilise un shell
exec(`ls ${dir} | grep .txt`,
  (err, out) => {...})
// le pipe fonctionne, mais les métacaractères aussi.
execFile() — sans shell par défaut
execFile('ls', [dir],
  (err, out) => {...})
// sans shell ; validez comment ls interprète l’argument dir.
// break out of its own argument

Quand vous avez réellement besoin des fonctions du shell

Si une commande exige des pipes, une expansion de jokers ou une redirection, execFile() ne propose pas directement ces fonctions. Préférez composer le pipeline dans Node.js en lançant chaque étape séparément et en reliant les streams. Si exec() est inévitable, gardez les entrées non fiables hors de la chaîne de commande. Un tableau d’arguments sans shell n’empêche pas non plus l’injection d’arguments : validez chaque valeur selon le programme cible, utilisez -- si ce programme le prend en charge et n’autorisez que les commandes et options prévues. L’option shell: true active un shell pour les API qui n’en lancent normalement pas ; dans ce mode, ne transmettez jamais d’entrée non assainie.

Questions fréquentes

Les fichiers batch Windows changent la frontière de sécurité

Sous Windows, les fichiers .bat et .cmd ne peuvent pas être lancés directement avec execFile(). Node documente leur invocation via exec(), cmd.exe ou spawn() avec un shell activé ; ces chemins réintroduisent l’analyse par l’interpréteur de commandes. Préférez un exécutable natif ou une API directe. Si l’appel d’un fichier batch est inévitable, gardez le chemin du script et ses arguments fixes, ou validez-les selon le contrat exact du script. Node déprécie également le passage d’un tableau d’arguments avec shell: true (depuis v22.15.0 et v23.11.0).

spawn() est-il équivalent à execFile() ?

spawn() fonctionne également sans shell par défaut et accepte un tableau d’arguments. La principale différence pratique concerne la sortie : spawn() transmet des streams, tandis que execFile() met la sortie en mémoire tampon. Aucun des deux n’empêche le programme d’interpréter un argument comme une option ; validez-le pour ce programme. Définir shell: true réactive l’analyse par le shell.

Références

À voir aussi Injection de commandes système (CWE-78) : fonctionnement et prévention dans tous les langages — flawopen.com Java Runtime.exec() et Command Injection : que change-t-il ? Risque de command injection avec Node.js exec()