Skip to content

Commit 5877e3a

Browse files
committed
Remove node-static dependency from testkit-backend
This library has security vulnerabilities and it's not actively mantained. Their usage was replaced by a very basic implementation of static file server. See: https://github.com/neo4j/neo4j-javascript-driver/security/dependabot/134
1 parent b1fd33c commit 5877e3a

File tree

5 files changed

+73
-100
lines changed

5 files changed

+73
-100
lines changed

packages/testkit-backend/package-lock.json

Lines changed: 0 additions & 97 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/testkit-backend/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
"dependencies": {
3535
"neo4j-driver": "5.0.0-dev",
3636
"neo4j-driver-lite": "5.0.0-dev",
37-
"node-static": "^0.7.11",
3837
"ws": "^8.11.0"
3938
},
4039
"devDependencies": {

packages/testkit-backend/src/controller/remote.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Controller from './interface'
22
import { WebSocketServer } from 'ws'
33
import { createServer } from 'http'
4-
import { Server } from 'node-static'
4+
import { HttpStaticServer } from '../infrastructure'
55

66
/**
77
* RemoteController handles the requests by sending them a remote client.
@@ -14,7 +14,9 @@ import { Server } from 'node-static'
1414
export default class RemoteController extends Controller {
1515
constructor (port) {
1616
super()
17-
this._staticServer = new Server('./public')
17+
this._staticServer = new HttpStaticServer({
18+
basePath: './public'
19+
})
1820
this._port = port
1921
this._wss = null
2022
this._ws = null
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import fs from 'fs'
2+
3+
const DEFAULT_MIME_TYPES = {
4+
html: 'text/html',
5+
js: 'text/javascript',
6+
default: 'text/plain'
7+
}
8+
9+
const DEFAULT_INDEX_FILE = '/index.html'
10+
11+
/**
12+
* This a very minimal implementation of a static files http server.
13+
*
14+
* This is intend to be used only in the ${@link RemoteController} scenario and
15+
* this is not feature complete.
16+
*
17+
* Some security measures to avoid external elements to sniff to files out of the base
18+
* path are in place. Like Directory Transversal.
19+
*/
20+
export class HttpStaticServer {
21+
constructor ({
22+
basePath,
23+
mimeTypes,
24+
defaultMimeType,
25+
indexFile
26+
} = {}) {
27+
this._basePath = basePath
28+
this._mimeTypes = mimeTypes || DEFAULT_MIME_TYPES
29+
this._indexFile = indexFile || DEFAULT_INDEX_FILE
30+
31+
if (this._mimeTypes.default === undefined) {
32+
this._mimeTypes.default = defaultMimeType || DEFAULT_MIME_TYPES.default
33+
}
34+
}
35+
36+
serve (request, response) {
37+
if (request.method === 'GET') {
38+
const file = request.url !== '/' ? request.url : this._indexFile
39+
const filePath = `${this._basePath}${file}`
40+
const [, extension, ...rest] = file.split('.')
41+
if (rest.length > 0) {
42+
writeError(response, 403, '403 Forbidden!')
43+
return
44+
}
45+
46+
if (!fs.existsSync(filePath)) {
47+
writeError(response, 404, '404 Not Found!')
48+
return
49+
}
50+
51+
fs.readFile(filePath, 'utf-8', (err, message) => {
52+
if (err) {
53+
writeError(response, 500, '500 Internal Server Error!')
54+
return
55+
}
56+
response.writeHead(200, { 'Content-Type': this._mimeTypes[extension] || this._mimeTypes.default })
57+
response.write(message)
58+
response.end()
59+
})
60+
}
61+
}
62+
}
63+
64+
function writeError (response, code, errorMessage) {
65+
response.writeHead(code, { 'Content-Type': 'text/plain' })
66+
response.write(errorMessage)
67+
response.end()
68+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { HttpStaticServer } from './http-static.server'

0 commit comments

Comments
 (0)