diff --git a/server/index.js b/server/index.js
index 51437f7..c4d4dfa 100644
--- a/server/index.js
+++ b/server/index.js
@@ -331,7 +331,7 @@ class Cap extends EventEmitter {
}),
);
- const isValid = hashes.every((pair) => pair?.[0].startsWith(pair[1]));
+ const isValid = hashes.every((pair) => pair?.[0]?.startsWith?.(pair[1]));
if (!isValid) return { success: false, message: "Invalid solution" };
diff --git a/standalone/public/js/dashboard.js b/standalone/public/js/dashboard.js
index 54e96cd..30cbd44 100644
--- a/standalone/public/js/dashboard.js
+++ b/standalone/public/js/dashboard.js
@@ -8,7 +8,12 @@ const welcomeScreen = document.getElementById("welcomeScreen");
const keyDetail = document.getElementById("keyDetail");
const escapeHtml = (s) => {
- return s.replaceAll("<", "<").replaceAll(">", ">");
+ return String(s)
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
};
const api = async (method, path, body) => {
@@ -508,7 +513,7 @@ async function saveConfig() {
if (!name || difficulty < 2 || challengeCount < 1 || saltSize < 7) {
showModal(
- "Validation Error",
+ "Validation error",
`
Please check your input values. Difficulty must be ≥2, challenge count ≥1, and salt size ≥7.
`,
);
btn.disabled = false;
diff --git a/standalone/src/ratelimit.js b/standalone/src/ratelimit.js
index 514734c..cf9fd83 100644
--- a/standalone/src/ratelimit.js
+++ b/standalone/src/ratelimit.js
@@ -4,7 +4,8 @@ export const ratelimitGenerator = (req, server) => {
const ip = req.headers.get(header) || req.headers.get(header.toLowerCase());
if (ip) {
- return ip.split(",")[0].trim();
+ const parts = ip.split(",").filter((e) => !!e.trim());
+ return (parts[parts.length - 1] || parts[0]).trim();
}
console.error(
diff --git a/standalone/src/server.js b/standalone/src/server.js
index ae408f1..271c4dc 100644
--- a/standalone/src/server.js
+++ b/standalone/src/server.js
@@ -295,6 +295,7 @@ export const server = new Elysia({
instrumentation,
blockAutomatedBrowsers,
} = body;
+
const config = {
...keyDefaults,
...existingConfig,
@@ -313,10 +314,10 @@ export const server = new Elysia({
},
{
body: t.Object({
- name: t.Optional(t.String()),
- difficulty: t.Optional(t.Number()),
- challengeCount: t.Optional(t.Number()),
- saltSize: t.Optional(t.Number()),
+ name: t.Optional(t.String({ maxLength: 600 })),
+ difficulty: t.Optional(t.Number({ minimum: 1, maximum: 8 })),
+ challengeCount: t.Optional(t.Number({ minimum: 1, maximum: 500 })),
+ saltSize: t.Optional(t.Number({ minimum: 7, maximum: 1_001 })),
instrumentation: t.Optional(t.Boolean()),
blockAutomatedBrowsers: t.Optional(t.Boolean()),
}),