Skip to content

Conversation

@Saeraphinx
Copy link
Owner

closes #88
closes #4
closes #83
closes #23

Saeraphinx and others added 30 commits April 29, 2025 16:00
…y? localized entirely within your kitchen?

(begin validation against swagger file)
Rename Mod/ModVersion to Project/Version
…ame, disable beatmods importer, update api responses to not send generic messages
@Saeraphinx Saeraphinx self-assigned this Jun 9, 2025
}).then(async (project) => {
DatabaseHelper.refreshCache(`projects`);
if (iconIsValid) {
(icon as UploadedFile).mv(filePath);

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.

Copilot Autofix

AI 6 months ago

To fix the issue, we need to ensure that the constructed filePath is both normalized and validated to prevent directory traversal or other attacks. This can be achieved by:

  1. Using path.resolve to normalize the path and remove any .. segments.
  2. Using fs.realpathSync to resolve symbolic links and ensure the path points to a real location.
  3. Validating that the resolved path starts with the expected root directory (Config.storage.iconsDir).

Additionally, we should sanitize the icon.name using a library like sanitize-filename to remove any special characters that could be used maliciously.

Changes required:

  • Add the sanitize-filename package to sanitize icon.name.
  • Update the construction and validation of filePath to include normalization, symbolic link resolution, and sanitization.

Suggested changeset 2
src/api/routes/v3/createMod.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/src/api/routes/v3/createMod.ts b/src/api/routes/v3/createMod.ts
--- a/src/api/routes/v3/createMod.ts
+++ b/src/api/routes/v3/createMod.ts
@@ -2,2 +2,4 @@
 import path from 'node:path';
+import fs from 'node:fs';
+import sanitize from 'sanitize-filename';
 import { DatabaseHelper, ContentHash, Status, UserRoles } from '../../../shared/Database.ts';
@@ -88,4 +90,6 @@
                     // move the icon to the correct location
-                    filePath = `${path.resolve(Config.storage.iconsDir)}/${icon.md5}${path.extname(icon.name)}`;
-                    if (filePath.startsWith(`${path.resolve(Config.storage.iconsDir)}`) == false) {
+                    const sanitizedFileName = sanitize(icon.name);
+                    filePath = path.resolve(Config.storage.iconsDir, `${icon.md5}${path.extname(sanitizedFileName)}`);
+                    const resolvedFilePath = fs.realpathSync(filePath);
+                    if (!resolvedFilePath.startsWith(fs.realpathSync(Config.storage.iconsDir))) {
                         iconIsValid = false;
EOF
@@ -2,2 +2,4 @@
import path from 'node:path';
import fs from 'node:fs';
import sanitize from 'sanitize-filename';
import { DatabaseHelper, ContentHash, Status, UserRoles } from '../../../shared/Database.ts';
@@ -88,4 +90,6 @@
// move the icon to the correct location
filePath = `${path.resolve(Config.storage.iconsDir)}/${icon.md5}${path.extname(icon.name)}`;
if (filePath.startsWith(`${path.resolve(Config.storage.iconsDir)}`) == false) {
const sanitizedFileName = sanitize(icon.name);
filePath = path.resolve(Config.storage.iconsDir, `${icon.md5}${path.extname(sanitizedFileName)}`);
const resolvedFilePath = fs.realpathSync(filePath);
if (!resolvedFilePath.startsWith(fs.realpathSync(Config.storage.iconsDir))) {
iconIsValid = false;
package.json
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -39,3 +39,4 @@
     "zod": "^3.24.1",
-    "zod-validation-error": "^3.4.1"
+    "zod-validation-error": "^3.4.1",
+    "sanitize-filename": "^1.6.3"
   },
EOF
@@ -39,3 +39,4 @@
"zod": "^3.24.1",
"zod-validation-error": "^3.4.1"
"zod-validation-error": "^3.4.1",
"sanitize-filename": "^1.6.3"
},
This fix introduces these dependencies
Package Version Security advisories
sanitize-filename (npm) 1.6.3 None
Copilot is powered by AI and may make mistakes. Always verify output.
if (filePath.startsWith(`${path.resolve(Config.storage.modsDir)}`) == false) {
return res.status(400).send({ message: `Invalid zip file.` });
} else {
file.mv(filePath);

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.
let oldFileName = project.iconFileName;
project.iconFileName = `${icon.md5}${path.extname(icon.name)}`;
project.save().then((project) => {
icon.mv(filePath, (error) => {

Check failure

Code scanning / CodeQL

Uncontrolled data used in path expression High

This path depends on a
user-provided value
.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants