Skip to content

Commit 5950865

Browse files
authored
Merge pull request github#13755 from github/max-schaefer/js-server-crash-help
JavaScript: Improve qhelp for js/server-crash.
2 parents c38cbe8 + 5124310 commit 5950865

File tree

4 files changed

+24
-25
lines changed

4 files changed

+24
-25
lines changed

javascript/ql/src/Security/CWE-730/ServerCrash.qhelp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,13 @@
4242

4343
<p>
4444

45-
The following server implementation checks if a client-provided
46-
file path is valid and throws an exception if the check fails. It can
47-
be seen that the exception is uncaught, and it is therefore reasonable to
48-
expect the server to respond with an error response to client requests
49-
that cause the check to fail.
50-
51-
But since the exception is uncaught in the context of an
52-
asynchronous callback invocation (<code>fs.access(...)</code>), the
53-
entire server will terminate instead.
45+
The following server code checks if a client-provided file path is valid
46+
before saving data to that path. It would be reasonable to expect that the
47+
server responds with an error in case the request contains an invalid
48+
file path. However, the server instead throws an exception, which is
49+
uncaught in the context of the asynchronous callback invocation
50+
(<code>fs.access(...)</code>). This causes the entire server to
51+
terminate abruptly.
5452

5553
</p>
5654

@@ -67,11 +65,9 @@
6765

6866
<p>
6967

70-
An alternative is to use an <code>async</code> and
71-
<code>await</code> for the asynchronous behavior, since the server
72-
will then print warning messages about uncaught exceptions instead of
73-
terminating, unless the server was started with the commandline option
74-
<code>--unhandled-rejections=strict</code>:
68+
To simplify exception handling, it may be advisable to switch to
69+
async/await syntax instead of using callbacks, which allows wrapping the
70+
entire request handler in a <code>try/catch</code> block:
7571

7672
</p>
7773

javascript/ql/src/Security/CWE-730/examples/server-crash.BAD.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ function save(rootDir, path, content) {
77
}
88
// write content to disk
99
}
10+
1011
express().post("/save", (req, res) => {
11-
fs.exists(rootDir, (exists) => {
12-
if (!exists) {
13-
console.error(`Server setup is corrupted, ${rootDir} does not exist!`);
12+
fs.access(rootDir, (err) => {
13+
if (err) {
14+
console.error(
15+
`Server setup is corrupted, ${rootDir} cannot be accessed!`
16+
);
1417
res.status(500);
1518
res.end();
1619
return;

javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-A.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// ...
22
express().post("/save", (req, res) => {
3-
fs.exists(rootDir, (exists) => {
3+
fs.access(rootDir, (err) => {
44
// ...
55
try {
6-
save(rootDir, req.query.path, req.body); // GOOD no uncaught exception
6+
save(rootDir, req.query.path, req.body); // GOOD exception is caught below
77
res.status(200);
88
res.end();
99
} catch (e) {
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// ...
22
express().post("/save", async (req, res) => {
3-
if (!(await fs.promises.exists(rootDir))) {
4-
console.error(`Server setup is corrupted, ${rootDir} does not exist!`);
3+
try {
4+
await fs.promises.access(rootDir);
5+
save(rootDir, req.query.path, req.body); // GOOD exception is caught below
6+
res.status(200);
7+
res.end();
8+
} catch (e) {
59
res.status(500);
610
res.end();
7-
return;
811
}
9-
save(rootDir, req.query.path, req.body); // MAYBE BAD, depends on the commandline options
10-
res.status(200);
11-
res.end();
1212
});

0 commit comments

Comments
 (0)