fix(wom+wob): reject path traversal in WOM texture paths + WOB material/group texPaths

Same defensive check as the WoB doodad path guard. Texture paths from
hostile WOM/WoB are passed to the asset manager; '..' or absolute paths
could probe outside the assets/ tree. Now cleared on detection — slot
survives but loads no texture (renderer falls back to white).

Single shared rejectTraversal lambda in WoB to avoid copy-paste.
This commit is contained in:
Kelsi 2026-05-06 06:16:54 -07:00
parent c4463ba96e
commit 719951976d
2 changed files with 19 additions and 0 deletions

View file

@ -96,12 +96,22 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) {
if (idx > vMax) idx = 0;
}
// Helper: clear path on traversal/absolute attempt.
auto rejectTraversal = [](std::string& s, const char* what) {
if (s.find("..") != std::string::npos ||
(!s.empty() && (s[0] == '/' || s[0] == '\\')) ||
(s.size() >= 2 && s[1] == ':')) {
LOG_WARNING("WOB ", what, " path rejected (traversal): ", s);
s.clear();
}
};
for (uint32_t ti = 0; ti < tc; ti++) {
uint16_t tl;
f.read(reinterpret_cast<char*>(&tl), 2);
if (tl > 1024) tl = 0;
std::string tp(tl, '\0');
f.read(tp.data(), tl);
rejectTraversal(tp, "group texture");
grp.texturePaths.push_back(tp);
}
@ -115,6 +125,7 @@ WoweeBuilding WoweeBuildingLoader::load(const std::string& basePath) {
if (pl > 1024) pl = 0;
mat.texturePath.resize(pl);
f.read(mat.texturePath.data(), pl);
rejectTraversal(mat.texturePath, "material texture");
f.read(reinterpret_cast<char*>(&mat.flags), 4);
f.read(reinterpret_cast<char*>(&mat.shader), 4);
f.read(reinterpret_cast<char*>(&mat.blendMode), 4);

View file

@ -113,6 +113,14 @@ WoweeModel WoweeModelLoader::load(const std::string& basePath) {
if (pathLen > 1024) { pathLen = 0; }
std::string path(pathLen, '\0');
f.read(path.data(), pathLen);
// Reject path-traversal — texture paths from a hostile WOM are fed
// to the asset manager and could probe files outside assets/.
if (path.find("..") != std::string::npos ||
(!path.empty() && (path[0] == '/' || path[0] == '\\')) ||
(path.size() >= 2 && path[1] == ':')) {
LOG_WARNING("WOM texture path rejected (traversal): ", path);
path.clear();
}
model.texturePaths.push_back(path);
}