Validate untrusted IDs before using them as directory names

Texture pack installs took the destination directory from the archive's
textures.ini, and PKG update installs from the PBOOT's DISC_ID, both
unchecked, so a crafted archive or package could write outside
PSP/TEXTURES or PSP/GAME. Add IsSafePathComponent() to PathUtil and check
both, replacing the WebServer's own upload filename check with it too.

DISC_ID from any PARAM.SFO also names configs, cheats, textures, exdata
and savestates, so ReadSFO now drops one that isn't a safe name and the
game gets a fake ID like homebrew. The same goes for a frame dump's ID.

Combines #22419 and #22420 by Acts1631.

Co-Authored-By: Acts1631 <acts1631kjv@proton.me>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed 2026-10-05 13:39:06 -06:00
1 parent 647819fb6f
commit 499cdd55ad
8 files changed
+65 -12

No files matched your search

+1 -6
View File
@@ -580,11 +580,6 @@ enum class MultiPartResult {
Done,
};
static bool IsSafeUploadFilename(std::string_view filename) {
return !filename.empty() && filename != "." && filename != ".." &&
filename.find_first_of("/\\") == std::string_view::npos;
}
static MultiPartResult HandleMultipartPart(const http::ServerRequest &request, std::string boundary, const Path &uploadPath, ProgressTracker &progress) {
std::string firstBoundary = request.In()->ReadLine();
if (firstBoundary != "--" + boundary) {
@@ -625,7 +620,7 @@ static MultiPartResult HandleMultipartPart(const http::ServerRequest &request, s
}
}
if (!IsSafeUploadFilename(filename)) {
if (!IsSafePathComponent(filename)) {
ERROR_LOG(Log::HTTP, "Invalid upload filename");
return MultiPartResult::RequestError;
}