mirror of
https://github.com/C4illin/ConvertX.git
synced 2026-11-13 01:30:53 +01:00
fix symlink in downloads
This commit is contained in:
1 parent
bc5a163fb5
commit
d112ef9a1b
7 files changed
+166
-26
No files matched your search
@@ -25,3 +25,6 @@ export const UNAUTHENTICATED_USER_SHARING =
|
||||
process.env.UNAUTHENTICATED_USER_SHARING?.toLowerCase() === "true" || false;
|
||||
|
||||
export const TIMEZONE = process.env.TZ || undefined;
|
||||
|
||||
export const uploadsDir = "./data/uploads/";
|
||||
export const outputDir = "./data/output/";
|
||||
+1
-3
@@ -4,7 +4,7 @@ import { Elysia } from "elysia";
|
||||
import { rmSync } from "node:fs";
|
||||
import db from "./db/db";
|
||||
import { Jobs } from "./db/types";
|
||||
import { AUTO_DELETE_EVERY_N_HOURS, WEBROOT } from "./helpers/env";
|
||||
import { AUTO_DELETE_EVERY_N_HOURS, outputDir, uploadsDir, WEBROOT } from "./helpers/env";
|
||||
import "./helpers/printVersions";
|
||||
import { getLandlockRunnerPath, isSandboxAvailable } from "./helpers/sandbox";
|
||||
import { chooseConverter } from "./pages/chooseConverter";
|
||||
@@ -20,8 +20,6 @@ import { root } from "./pages/root";
|
||||
import { upload } from "./pages/upload";
|
||||
import { user } from "./pages/user";
|
||||
|
||||
export const uploadsDir = "./data/uploads/";
|
||||
export const outputDir = "./data/output/";
|
||||
|
||||
// Fix for Elysia issue with Bun, (see https://github.com/oven-sh/bun/issues/12161)
|
||||
process.getBuiltinModule = require;
|
||||
|
||||
@@ -226,28 +226,45 @@ int main(int argc, char *argv[]) {
|
||||
return 127;
|
||||
}
|
||||
|
||||
// Build supported filesystem access rights
|
||||
// Handled filesystem access rights in ruleset
|
||||
__u64 handled_fs_access = LANDLOCK_ACCESS_FS_EXECUTE |
|
||||
LANDLOCK_ACCESS_FS_READ_FILE |
|
||||
LANDLOCK_ACCESS_FS_READ_DIR |
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE |
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_REG |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_FIFO |
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM;
|
||||
if (abi >= 2) handled_fs_access |= LANDLOCK_ACCESS_FS_REFER;
|
||||
if (abi >= 3) handled_fs_access |= LANDLOCK_ACCESS_FS_TRUNCATE;
|
||||
if (abi >= 5) handled_fs_access |= LANDLOCK_ACCESS_FS_IOCTL_DEV;
|
||||
|
||||
// Build supported filesystem access rights for read-only paths
|
||||
__u64 fs_ro_access = LANDLOCK_ACCESS_FS_EXECUTE |
|
||||
LANDLOCK_ACCESS_FS_READ_FILE |
|
||||
LANDLOCK_ACCESS_FS_READ_DIR;
|
||||
if (abi >= 2) fs_ro_access |= LANDLOCK_ACCESS_FS_REFER;
|
||||
|
||||
// Build supported filesystem access rights for read-write paths
|
||||
// NOTE: Intentionally exclude LANDLOCK_ACCESS_FS_MAKE_SYM, MAKE_CHAR, MAKE_BLOCK, MAKE_FIFO
|
||||
// to prevent creation of symlinks (CWE-59 sandbox escape) and device nodes.
|
||||
__u64 fs_rw_access = fs_ro_access |
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE |
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_REG |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_FIFO |
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM;
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK;
|
||||
if (abi >= 3) fs_rw_access |= LANDLOCK_ACCESS_FS_TRUNCATE;
|
||||
if (abi >= 5) fs_rw_access |= LANDLOCK_ACCESS_FS_IOCTL_DEV;
|
||||
|
||||
struct landlock_ruleset_attr attr = {
|
||||
.handled_access_fs = fs_rw_access,
|
||||
.handled_access_fs = handled_fs_access,
|
||||
};
|
||||
|
||||
if (no_net && abi >= 4) {
|
||||
|
||||
+32
-9
@@ -1,10 +1,10 @@
|
||||
import path from "node:path";
|
||||
import { Elysia } from "elysia";
|
||||
import { lstat, realpath } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import sanitize from "sanitize-filename";
|
||||
import * as tar from "tar";
|
||||
import { outputDir } from "..";
|
||||
import db from "../db/db";
|
||||
import { WEBROOT } from "../helpers/env";
|
||||
import { outputDir, WEBROOT } from "../helpers/env";
|
||||
import { userService } from "./user";
|
||||
|
||||
export const download = new Elysia()
|
||||
@@ -24,13 +24,28 @@ export const download = new Elysia()
|
||||
const jobId = decodeURIComponent(params.jobId);
|
||||
const fileName = sanitize(decodeURIComponent(params.fileName));
|
||||
|
||||
const filePath = `${outputDir}${userId}/${jobId}/${fileName}`;
|
||||
const file = Bun.file(filePath);
|
||||
if (!(await file.exists())) {
|
||||
const jobOutputDir = path.join(outputDir, userId, jobId);
|
||||
const filePath = path.join(jobOutputDir, fileName);
|
||||
|
||||
try {
|
||||
const stat = await lstat(filePath);
|
||||
if (stat.isSymbolicLink()) {
|
||||
set.status = 403;
|
||||
return { message: "Access denied." };
|
||||
}
|
||||
|
||||
const resolvedBase = await realpath(jobOutputDir);
|
||||
const resolvedFile = await realpath(filePath);
|
||||
if (!resolvedFile.startsWith(resolvedBase + path.sep)) {
|
||||
set.status = 403;
|
||||
return { message: "Access denied." };
|
||||
}
|
||||
} catch {
|
||||
set.status = 404;
|
||||
return { message: "Converted file not found." };
|
||||
}
|
||||
|
||||
const file = Bun.file(filePath);
|
||||
return file;
|
||||
},
|
||||
{
|
||||
@@ -50,15 +65,23 @@ export const download = new Elysia()
|
||||
}
|
||||
|
||||
const jobId = decodeURIComponent(params.jobId);
|
||||
const outputPath = `${outputDir}${userId}/${jobId}`;
|
||||
const outputPath = path.join(outputDir, userId, jobId);
|
||||
const outputTar = path.join(outputPath, `converted_files_${jobId}.tar`);
|
||||
|
||||
await tar.create(
|
||||
{
|
||||
file: outputTar,
|
||||
cwd: outputPath,
|
||||
filter: (path) => {
|
||||
return !path.match(".*\\.tar");
|
||||
filter: (entryPath, stat) => {
|
||||
const isSymlink =
|
||||
("isSymbolicLink" in stat &&
|
||||
typeof stat.isSymbolicLink === "function" &&
|
||||
stat.isSymbolicLink()) ||
|
||||
("type" in stat && (stat as { type?: string }).type === "SymbolicLink");
|
||||
if (entryPath.endsWith(".tar") || isSymlink) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
},
|
||||
["."],
|
||||
|
||||
Reference in new issue
Block a user