commit 84735034ed87be9473fe2fadbe6ad11a6b4e13bc from: Markus Uhlin via: GitHub date: Sat Aug 16 21:56:35 2025 UTC Potential fix for code scanning alert no. 8: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> commit - a75af80d23b0ad23fbf368d8961a237c2e27f3aa commit + 84735034ed87be9473fe2fadbe6ad11a6b4e13bc blob - 2353c6065cee6dcca1a3aafa7660e0b71acd5204 blob + 73c1ae0884f309341d57fca1d362a5326ffcae30 --- FICS/obsproc.c +++ FICS/obsproc.c @@ -39,6 +39,8 @@ #include "common.h" #include +#include +#include #include "command.h" #include "comproc.h" @@ -1045,8 +1047,31 @@ FindHistory2(int p, int p1, int p_game, char *End, con fclose(fpHist); + /* Validate 'when' before using it in a path */ + if (when <= 0 || when > LONG_MAX) { + pprintf(p, "Invalid history timestamp for %s.\n", parray[p1].name); + return NULL; + } + msnprintf(fileName, sizeof fileName, "%s/%ld/%ld", hist_dir, (when % 100), when); + + /* Validate that the resolved path is within hist_dir */ + char *resolvedPath = realpath(fileName, NULL); + if (resolvedPath == NULL) { + warnx("%s: %s: realpath failed", __func__, fileName); + return NULL; + } + if (strncmp(resolvedPath, hist_dir, strlen(hist_dir)) != 0) { + warnx("%s: %s: path traversal detected", __func__, resolvedPath); + free(resolvedPath); + return NULL; + } + /* Copy resolvedPath back to fileName for return */ + strncpy(fileName, resolvedPath, sizeof(fileName) - 1); + fileName[sizeof(fileName) - 1] = '\0'; + free(resolvedPath); + return (&fileName[0]); }