Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9e3cc3b

Browse files
committed
JS: add qhelp and changenotes for js/server-crash
1 parent 3015dcd commit 9e3cc3b

5 files changed

Lines changed: 124 additions & 10 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* The `js/server-crash` query has been added. It highlights servers may be terminated by a malicious user.
Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,86 @@
11
<!DOCTYPE qhelp PUBLIC
2-
"-//Semmle//qhelp//EN"
3-
"qhelp.dtd">
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
44
<qhelp>
55

6-
<overview>
6+
<overview>
77

8-
</overview>
8+
<p>
99

10-
<recommendation>
10+
Servers handle requests from clients until terminated
11+
deliberately by a server administrator. A client request that results
12+
in an uncaught server-side exception causes the current server
13+
response generation to fail, and should not have an effect on
14+
subsequent client requests.
1115

12-
</recommendation>
16+
</p>
1317

14-
<example>
18+
<p>
1519

16-
</example>
20+
Under some circumstances, uncaught exceptions can however
21+
cause the entire server to terminate abruptly. Such a behavior is
22+
highly undesirable, especially if it gives malicious users the ability
23+
to turn off the server at will, which is an efficient
24+
denial-of-service attack.
1725

18-
<references>
26+
</p>
1927

20-
</references>
28+
</overview>
29+
30+
<recommendation>
31+
32+
<p>
33+
34+
Ensure that the processing of client requests can not cause
35+
uncaught exceptions to terminate the entire server abruptly.
36+
37+
</p>
38+
39+
</recommendation>
40+
41+
<example>
42+
43+
<p>
44+
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.
54+
55+
</p>
56+
57+
<sample src="examples/server-crash.BAD.js"/>
58+
59+
<p>
60+
To remedy this, the server can catch the exception explicitly with
61+
a <code>try/catch</code> block, and generate an appropriate error
62+
response instead:
63+
64+
</p>
65+
66+
<sample src="examples/server-crash.GOOD-A.js"/>
67+
68+
<p>
69+
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>:
75+
76+
</p>
77+
78+
<sample src="examples/server-crash.GOOD-B.js"/>
79+
80+
</example>
81+
82+
<references>
83+
84+
</references>
2185

2286
</qhelp>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const express = require("express"),
2+
fs = require("fs");
3+
4+
function save(rootDir, path, content){
5+
if (!isValidPath(rootDir, req.query.filePath)) {
6+
throw new Error(`Invalid filePath: ${req.query.filePath}`); // BAD crashes the server
7+
}
8+
// write content to disk
9+
}
10+
express().post("/save", (req, res) => {
11+
fs.access(rootDir, (err) => {
12+
if (err) {
13+
console.error(`Server setup is corrupted, ${rootDir} does not exist!`);
14+
res.status(500);
15+
res.end();
16+
}
17+
save(rootDir, req.query.path, req.body);
18+
res.status(200);
19+
res.end();
20+
});
21+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// ...
2+
express().post("/save", (req, res) => {
3+
fs.access(rootDir, (err) => {
4+
// ...
5+
try {
6+
save(rootDir, req.query.path, req.body); // GOOD no uncaught exception
7+
res.status(200);
8+
res.end();
9+
} catch (e) {
10+
res.status(500);
11+
res.end();
12+
}
13+
});
14+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// ...
2+
express().post("/save", async (req, res) => {
3+
try {
4+
await fs.access(rootDir);
5+
} catch (e) {
6+
console.error(`Server setup is corrupted, ${rootDir} does not exist!`);
7+
res.status(500);
8+
res.end();
9+
}
10+
save(rootDir, req.query.path, req.body); // MAYBE BAD, depends on the commandline options
11+
res.status(200);
12+
res.end();
13+
});

0 commit comments

Comments
 (0)