62 lines
1.7 KiB
Plaintext
Raw Normal View History

== How to fix it in Node.js
=== Code examples
include::../../common/fix/code-rationale.adoc[]
==== Noncompliant code example
[source,javascript,diff-id=1,diff-type=noncompliant]
----
const { execSync } = require('child_process')
cmd = req.query.cmd
execSync(cmd) // Noncompliant
----
==== Compliant solution
[source,javascript,diff-id=1,diff-type=compliant]
----
const { spawnSync } = require('child_process')
const cmdId = parseInt(req.query.cmdId)
let host = req.query.host
host = typeof host === "string"? host : "example.org"
const allowedCommands = [
{exe:"/bin/ping", args:["-c","1","--"]},
{exe:"/bin/host", args:["--"]}
]
const cmd = allowedCommands[cmdId]
spawnSync(cmd.exe, cmd.args.concat(host))
----
=== How does this work?
include::../../common/fix/introduction.adoc[]
include::../../common/fix/pre-approved-list.adoc[]
In the example compliant code, a static list of trusted commands is used. Users are only allowed to
submit an index in this array in place of a full command name.
:sanitizationLib: child_process.spawn
include::../../common/fix/sanitize-meta-characters.adoc[]
In the example compliant code, the `spawn` function from `child_process` is used in place of its less
secure `exec` counterpart. It accepts command arguments as an array and
performs a proper escaping of its element before building the command line to
run.
include::../../common/fix/shell_integration.adoc[]
The `spawn` function that is used in the example compliant code disables shell integration by default.
=== Pitfalls
include::../common/pitfalls/loose-typing.adoc[]
In the above compliant code example, the ambiguous `concat` function is used.
However, a type check has been introduced to prevent any unexpected issue.