diff --git a/package.json b/package.json index e4bd4e5..4d05972 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "formidable": "^3.5.2", "fs-extra": "^8.1.0", "http-proxy-middleware": "^3.0.3", + "is-path-inside": "^4.0.0", "lodash": "^4.17.15", "morgan": "^1.9.1", "p-map": "^4.0.0", diff --git a/src/app.ts b/src/app.ts index 82d6d6e..49eeeff 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,7 +1,7 @@ import express, { Response } from 'express'; import Formidable from 'formidable'; import { createReadStream } from 'node:fs'; -import { join, basename } from 'node:path'; +import { join, basename, relative } from 'node:path'; import assert from 'node:assert'; import * as fs from 'node:fs/promises'; import morgan from 'morgan'; @@ -17,6 +17,8 @@ import bodyParser from 'body-parser'; import filenamify from 'filenamify'; import stream from 'node:stream/promises'; import parseRange from 'range-parser'; +// @ts-expect-error dunno +import isPathInside from 'is-path-inside'; const maxFields = 1000; @@ -34,11 +36,15 @@ export default ({ sharedPath: sharedPathIn, port, maxUploadSize, zipCompressionL // console.log({ sharedPath: sharedPathIn, port, maxUploadSize, zipCompressionLevel }); const sharedPath = sharedPathIn || process.cwd(); + function arePathsEqual(path1: string, path2: string) { + return relative(path1, path2) === ''; + } + async function getFileAbsPath(relPath: string | undefined) { if (relPath == null) return sharedPath; const absPath = join(sharedPath, join('/', relPath)); const realPath = await fs.realpath(absPath); - assert(realPath.startsWith(sharedPath), 'Path must be within shared path'); + assert(isPathInside(realPath, sharedPath) || arePathsEqual(realPath, sharedPath), `Path must be within shared path ${realPath} ${sharedPath}`); return realPath; } diff --git a/yarn.lock b/yarn.lock index 8730ab8..3757135 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2444,6 +2444,7 @@ __metadata: formidable: "npm:^3.5.2" fs-extra: "npm:^8.1.0" http-proxy-middleware: "npm:^3.0.3" + is-path-inside: "npm:^4.0.0" lodash: "npm:^4.17.15" morgan: "npm:^1.9.1" p-map: "npm:^4.0.0" @@ -3280,6 +3281,13 @@ __metadata: languageName: node linkType: hard +"is-path-inside@npm:^4.0.0": + version: 4.0.0 + resolution: "is-path-inside@npm:4.0.0" + checksum: 10c0/51188d7e2b1d907a9a5f7c18d99a90b60870b951ed87cf97595d9aaa429d4c010652c3350bcbf31182e7f4b0eab9a1860b43e16729b13cb1a44baaa6cdb64c46 + languageName: node + linkType: hard + "is-plain-object@npm:^5.0.0": version: 5.0.0 resolution: "is-plain-object@npm:5.0.0"