{"record":{"id":"046c2b5098b0b3f3","repo":"louislam/uptime-kuma","slug":"invalid-language","errorCode":null,"errorMessage":"Invalid language","messagePattern":"Invalid language","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"server/socket-handlers/general-socket-handler.js","lineNumber":120,"sourceCode":"                .catch((e) => {\n                    callback({\n                        ok: false,\n                        msg: e.message,\n                    });\n                });\n        } catch (e) {\n            callback({\n                ok: false,\n                msg: e.message,\n            });\n        }\n    });\n\n    socket.on(\"getPushExample\", async (language, callback) => {\n        try {\n            checkLogin(socket);\n            if (!/^[a-z-]+$/.test(language)) {\n                throw new Error(\"Invalid language\");\n            }\n        } catch (e) {\n            callback({\n                ok: false,\n                msg: e.message,\n            });\n            return;\n        }\n\n        try {\n            let dir = path.join(\"./extra/push-examples\", language);\n            let files = await fsAsync.readdir(dir);\n\n            for (let file of files) {\n                if (file.startsWith(\"index.\")) {\n                    callback({\n                        ok: true,\n                        code: await fsAsync.readFile(path.join(dir, file), \"utf8\"),","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/socket-handlers/general-socket-handler.js#L102-L138","documentation":"Thrown by the getPushExample handler when the language argument fails the regex ^[a-z-]+$. The handler uses language to build a directory path ./extra/push-examples/<language>, so the whitelist prevents path traversal and rejects anything outside the available example languages.","triggerScenarios":"Client emits 'getPushExample' with a language containing digits, uppercase letters, slashes, dots, or any non [a-z-] character; an attacker probes the endpoint to escape the push-examples directory.","commonSituations":"Frontend sends a language code with a region suffix in the wrong format (e.g. 'en_US', 'EN', 'c++'); attempted directory traversal ('../etc'); user-typed language code from a URL parameter.","solutions":["Pass one of the language directory names that exist under extra/push-examples (e.g. 'nodejs', 'bash', 'python') using lowercase ASCII letters and hyphens only.","Sanitize any user-supplied language input on the client against the allowed list before emitting.","Reject language values containing digits, dots, slashes, or uppercase before sending."],"exampleFix":"// before\nsocket.emit(\"getPushExample\", \"en_US\", cb);\n// after\nsocket.emit(\"getPushExample\", \"nodejs\", cb);","handlingStrategy":"validation","validationCode":"const ALLOWED = fs.readdirSync(\"./extra/push-examples\"); // or hard-coded list\nif (!/^[a-z-]+$/.test(language) || !ALLOWED.includes(language)) {\n  throw new Error(\"Invalid language\");\n}\nsocket.emit(\"getPushExample\", language, cb);","typeGuard":"function isSafeLanguage(l) {\n  return typeof l === \"string\" && /^[a-z-]+$/.test(l);\n}","tryCatchPattern":"try { await emitAsync(\"getPushExample\", lang, cb); }\ncatch (e) { if (e.message === \"Invalid language\") showLanguageError(); else throw e; }","preventionTips":["Filter user-supplied language input through an allow-list.","Use lowercase ASCII-only language codes.","Never pass raw URL params straight to the event."],"tags":["validation","security","path-traversal","socket-io","push-examples"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}