Skip to content

Commit 88d7884

Browse files
feat: enhance pipeFileToResponse with error handling (#7169)
* Enhance pipeFileToResponse with error handling Added error handling for file streaming in pipeFileToResponse function. * Security: Fix path traversal vulnerability in pipeFileToResponse with input validation and error handling Security: Enhance file streaming with comprehensive path validation - Add path traversal protection in pipeFileToResponse function - Implement input validation to prevent directory traversal attacks - Improve error handling for file read operations with proper status codes - Ensure resolved paths stay within intended directory boundaries - Add security checks using path.resolve() and startsWith() methods - Fix CodeQL "Uncontrolled data in path expression" vulnerability - Maintain backward compatibility while enhancing security --------- Co-authored-by: Jay <jasonsaayman@gmail.com>
1 parent 86b2423 commit 88d7884

File tree

1 file changed

+49
-5
lines changed

1 file changed

+49
-5
lines changed

‎examples/server.js‎

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'path';
33
import http from 'http';
44
import minimist from 'minimist';
55
import url from "url";
6+
67
const argv = minimist(process.argv.slice(2));
78
let server;
89
let dirs;
@@ -67,15 +68,53 @@ function send404(res, body) {
6768
}
6869

6970
function pipeFileToResponse(res, file, type) {
70-
if (type) {
71-
res.writeHead(200, {
72-
'Content-Type': type
71+
try {
72+
// Validate file path - prevent directory traversal
73+
const safeBasePath = path.join(__dirname, 'examples');
74+
const resolvedPath = path.resolve(path.join(safeBasePath, file));
75+
76+
// Ensure the resolved path is within intended directory
77+
if (!resolvedPath.startsWith(safeBasePath)) {
78+
res.writeHead(400);
79+
res.end('Invalid file path');
80+
return;
81+
}
82+
83+
// Check if file exists
84+
if (!fs.existsSync(resolvedPath)) {
85+
res.writeHead(404);
86+
res.end('File not found');
87+
return;
88+
}
89+
90+
if (type) {
91+
res.writeHead(200, {
92+
"Content-Type": type
93+
});
94+
} else {
95+
res.writeHead(200);
96+
}
97+
98+
const stream = fs.createReadStream(resolvedPath);
99+
100+
stream.on("error", (err) => {
101+
console.error("Error while reading file:", err.message);
102+
if (!res.headersSent) {
103+
res.writeHead(500, { "Content-Type": "text/plain" });
104+
}
105+
res.end("File read error");
73106
});
107+
108+
stream.pipe(res);
109+
} catch (err) {
110+
console.error("Unexpected error:", err.message);
111+
if (!res.headersSent) {
112+
res.writeHead(500, { "Content-Type": "text/plain" });
113+
}
114+
res.end("Internal server error");
74115
}
75-
fs.createReadStream(path.join(__dirname, file)).pipe(res);
76116
}
77117

78-
79118
dirs = listDirs(__dirname);
80119

81120
server = http.createServer(function (req, res) {
@@ -123,17 +162,22 @@ server = http.createServer(function (req, res) {
123162
} else {
124163
send404(res);
125164
}
165+
return;
126166
}
127167

128168
// Process server request
129169
else if (new RegExp('(' + dirs.join('|') + ')\/server').test(url)) {
130170
if (fs.existsSync(path.join(__dirname, url + '.js'))) {
131171
import('file://' + path.join(__dirname, url + '.js')).then((server) => {
132172
server.default(req, res);
173+
}).catch(err => {
174+
console.error('Error importing server:', err);
175+
send404(res);
133176
});
134177
} else {
135178
send404(res);
136179
}
180+
return;
137181
}
138182
else {
139183
send404(res);

0 commit comments

Comments
 (0)