Skip to content

Commit adf0094

Browse files
authored
Remove node-static dependency from testkit-backend (#1125)
This library has security vulnerabilities and it's not actively maintained. 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 5721c73 commit adf0094

File tree

5 files changed

+72
-100
lines changed

5 files changed

+72
-100
lines changed

packages/testkit-backend/package-lock.json

-97
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/testkit-backend/package.json

-1
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

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

0 commit comments

Comments
 (0)