Skip to content

Commit 3c88aec

Browse files
prevent exports path traversal (#233)
1 parent 0fd46e1 commit 3c88aec

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

Diff for: frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,9 @@ export default function DocumentSettings({ workspace }) {
177177
</div>
178178
</div>
179179
<div
180-
className={`flex items-center ${canDelete ? "justify-between" : "justify-end"
181-
} p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600`}
180+
className={`flex items-center ${
181+
canDelete ? "justify-between" : "justify-end"
182+
} p-4 md:p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600`}
182183
>
183184
<button
184185
hidden={!canDelete}

Diff for: server/endpoints/system.js

+21-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const { User } = require("../models/user");
2424
const { validatedRequest } = require("../utils/middleware/validatedRequest");
2525
const { handleImports } = setupDataImports();
2626
const { handleLogoUploads } = setupLogoUploads();
27+
const fs = require("fs");
2728
const path = require("path");
2829
const {
2930
getDefaultFilename,
@@ -315,9 +316,21 @@ function systemEndpoints(app) {
315316
"/system/data-exports/:filename",
316317
[validatedRequest],
317318
(request, response) => {
318-
const filePath =
319-
__dirname + "/../storage/exports/" + request.params.filename;
320-
response.download(filePath, request.params.filename, (err) => {
319+
const exportLocation = __dirname + "/../storage/exports/";
320+
const sanitized = path
321+
.normalize(request.params.filename)
322+
.replace(/^(\.\.(\/|\\|$))+/, "");
323+
const finalDestination = path.join(exportLocation, sanitized);
324+
325+
if (!fs.existsSync(finalDestination)) {
326+
response.status(404).json({
327+
error: 404,
328+
msg: `File ${request.params.filename} does not exist in exports.`,
329+
});
330+
return;
331+
}
332+
333+
response.download(finalDestination, request.params.filename, (err) => {
321334
if (err) {
322335
response.send({
323336
error: err,
@@ -448,13 +461,11 @@ function systemEndpoints(app) {
448461
response.status(200).json({ canDelete });
449462
} catch (error) {
450463
console.error("Error fetching can delete workspaces:", error);
451-
response
452-
.status(500)
453-
.json({
454-
success: false,
455-
message: "Internal server error",
456-
canDelete: false,
457-
});
464+
response.status(500).json({
465+
success: false,
466+
message: "Internal server error",
467+
canDelete: false,
468+
});
458469
}
459470
}
460471
);

0 commit comments

Comments
 (0)