diff --git a/.env.example b/.env.example index a58a37efb..274588199 100644 --- a/.env.example +++ b/.env.example @@ -349,6 +349,11 @@ REGISTRATION_VIOLATION_SCORE=1 CONCURRENT_VIOLATION_SCORE=1 MESSAGE_VIOLATION_SCORE=1 NON_BROWSER_VIOLATION_SCORE=20 +TTS_VIOLATION_SCORE=0 +STT_VIOLATION_SCORE=0 +FORK_VIOLATION_SCORE=0 +IMPORT_VIOLATION_SCORE=0 +FILE_UPLOAD_VIOLATION_SCORE=0 LOGIN_MAX=7 LOGIN_WINDOW=5 diff --git a/api/cache/logViolation.js b/api/cache/logViolation.js index a3162bbfa..5d785480b 100644 --- a/api/cache/logViolation.js +++ b/api/cache/logViolation.js @@ -9,7 +9,7 @@ const banViolation = require('./banViolation'); * @param {Object} res - Express response object. * @param {string} type - The type of violation. * @param {Object} errorMessage - The error message to log. - * @param {number} [score=1] - The severity of the violation. Defaults to 1 + * @param {number | string} [score=1] - The severity of the violation. Defaults to 1 */ const logViolation = async (req, res, type, errorMessage, score = 1) => { const userId = req.user?.id ?? req.user?._id; diff --git a/api/server/middleware/limiters/forkLimiters.js b/api/server/middleware/limiters/forkLimiters.js index c486c46fb..8a07cefab 100644 --- a/api/server/middleware/limiters/forkLimiters.js +++ b/api/server/middleware/limiters/forkLimiters.js @@ -11,6 +11,7 @@ const getEnvironmentVariables = () => { const FORK_IP_WINDOW = parseInt(process.env.FORK_IP_WINDOW) || 1; const FORK_USER_MAX = parseInt(process.env.FORK_USER_MAX) || 7; const FORK_USER_WINDOW = parseInt(process.env.FORK_USER_WINDOW) || 1; + const FORK_VIOLATION_SCORE = process.env.FORK_VIOLATION_SCORE; const forkIpWindowMs = FORK_IP_WINDOW * 60 * 1000; const forkIpMax = FORK_IP_MAX; @@ -27,12 +28,18 @@ const getEnvironmentVariables = () => { forkUserWindowMs, forkUserMax, forkUserWindowInMinutes, + forkViolationScore: FORK_VIOLATION_SCORE, }; }; const createForkHandler = (ip = true) => { - const { forkIpMax, forkIpWindowInMinutes, forkUserMax, forkUserWindowInMinutes } = - getEnvironmentVariables(); + const { + forkIpMax, + forkUserMax, + forkViolationScore, + forkIpWindowInMinutes, + forkUserWindowInMinutes, + } = getEnvironmentVariables(); return async (req, res) => { const type = ViolationTypes.FILE_UPLOAD_LIMIT; @@ -43,7 +50,7 @@ const createForkHandler = (ip = true) => { windowInMinutes: ip ? forkIpWindowInMinutes : forkUserWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, forkViolationScore); res.status(429).json({ message: 'Too many conversation fork requests. Try again later' }); }; }; diff --git a/api/server/middleware/limiters/importLimiters.js b/api/server/middleware/limiters/importLimiters.js index 88c4e9814..7ff48af5e 100644 --- a/api/server/middleware/limiters/importLimiters.js +++ b/api/server/middleware/limiters/importLimiters.js @@ -11,6 +11,7 @@ const getEnvironmentVariables = () => { const IMPORT_IP_WINDOW = parseInt(process.env.IMPORT_IP_WINDOW) || 15; const IMPORT_USER_MAX = parseInt(process.env.IMPORT_USER_MAX) || 50; const IMPORT_USER_WINDOW = parseInt(process.env.IMPORT_USER_WINDOW) || 15; + const IMPORT_VIOLATION_SCORE = process.env.IMPORT_VIOLATION_SCORE; const importIpWindowMs = IMPORT_IP_WINDOW * 60 * 1000; const importIpMax = IMPORT_IP_MAX; @@ -27,12 +28,18 @@ const getEnvironmentVariables = () => { importUserWindowMs, importUserMax, importUserWindowInMinutes, + importViolationScore: IMPORT_VIOLATION_SCORE, }; }; const createImportHandler = (ip = true) => { - const { importIpMax, importIpWindowInMinutes, importUserMax, importUserWindowInMinutes } = - getEnvironmentVariables(); + const { + importIpMax, + importUserMax, + importViolationScore, + importIpWindowInMinutes, + importUserWindowInMinutes, + } = getEnvironmentVariables(); return async (req, res) => { const type = ViolationTypes.FILE_UPLOAD_LIMIT; @@ -43,7 +50,7 @@ const createImportHandler = (ip = true) => { windowInMinutes: ip ? importIpWindowInMinutes : importUserWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, importViolationScore); res.status(429).json({ message: 'Too many conversation import requests. Try again later' }); }; }; diff --git a/api/server/middleware/limiters/messageLimiters.js b/api/server/middleware/limiters/messageLimiters.js index 4191c9fe7..cd409fa52 100644 --- a/api/server/middleware/limiters/messageLimiters.js +++ b/api/server/middleware/limiters/messageLimiters.js @@ -11,6 +11,7 @@ const { MESSAGE_IP_WINDOW = 1, MESSAGE_USER_MAX = 40, MESSAGE_USER_WINDOW = 1, + MESSAGE_VIOLATION_SCORE: score, } = process.env; const ipWindowMs = MESSAGE_IP_WINDOW * 60 * 1000; @@ -39,7 +40,7 @@ const createHandler = (ip = true) => { windowInMinutes: ip ? ipWindowInMinutes : userWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, score); return await denyRequest(req, res, errorMessage); }; }; diff --git a/api/server/middleware/limiters/sttLimiters.js b/api/server/middleware/limiters/sttLimiters.js index 72ed3af6a..79305bf5d 100644 --- a/api/server/middleware/limiters/sttLimiters.js +++ b/api/server/middleware/limiters/sttLimiters.js @@ -11,6 +11,7 @@ const getEnvironmentVariables = () => { const STT_IP_WINDOW = parseInt(process.env.STT_IP_WINDOW) || 1; const STT_USER_MAX = parseInt(process.env.STT_USER_MAX) || 50; const STT_USER_WINDOW = parseInt(process.env.STT_USER_WINDOW) || 1; + const STT_VIOLATION_SCORE = process.env.STT_VIOLATION_SCORE; const sttIpWindowMs = STT_IP_WINDOW * 60 * 1000; const sttIpMax = STT_IP_MAX; @@ -27,11 +28,12 @@ const getEnvironmentVariables = () => { sttUserWindowMs, sttUserMax, sttUserWindowInMinutes, + sttViolationScore: STT_VIOLATION_SCORE, }; }; const createSTTHandler = (ip = true) => { - const { sttIpMax, sttIpWindowInMinutes, sttUserMax, sttUserWindowInMinutes } = + const { sttIpMax, sttIpWindowInMinutes, sttUserMax, sttUserWindowInMinutes, sttViolationScore } = getEnvironmentVariables(); return async (req, res) => { @@ -43,7 +45,7 @@ const createSTTHandler = (ip = true) => { windowInMinutes: ip ? sttIpWindowInMinutes : sttUserWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, sttViolationScore); res.status(429).json({ message: 'Too many STT requests. Try again later' }); }; }; diff --git a/api/server/middleware/limiters/toolCallLimiter.js b/api/server/middleware/limiters/toolCallLimiter.js index 482744a3e..b14ca55d8 100644 --- a/api/server/middleware/limiters/toolCallLimiter.js +++ b/api/server/middleware/limiters/toolCallLimiter.js @@ -6,6 +6,8 @@ const logViolation = require('~/cache/logViolation'); const { isEnabled } = require('~/server/utils'); const { logger } = require('~/config'); +const { TOOL_CALL_VIOLATION_SCORE: score } = process.env; + const handler = async (req, res) => { const type = ViolationTypes.TOOL_CALL_LIMIT; const errorMessage = { @@ -15,7 +17,7 @@ const handler = async (req, res) => { windowInMinutes: 1, }; - await logViolation(req, res, type, errorMessage, 0); + await logViolation(req, res, type, errorMessage, score); res.status(429).json({ message: 'Too many tool call requests. Try again later' }); }; diff --git a/api/server/middleware/limiters/ttsLimiters.js b/api/server/middleware/limiters/ttsLimiters.js index 9054a6beb..93dd6eb99 100644 --- a/api/server/middleware/limiters/ttsLimiters.js +++ b/api/server/middleware/limiters/ttsLimiters.js @@ -11,6 +11,7 @@ const getEnvironmentVariables = () => { const TTS_IP_WINDOW = parseInt(process.env.TTS_IP_WINDOW) || 1; const TTS_USER_MAX = parseInt(process.env.TTS_USER_MAX) || 50; const TTS_USER_WINDOW = parseInt(process.env.TTS_USER_WINDOW) || 1; + const TTS_VIOLATION_SCORE = process.env.TTS_VIOLATION_SCORE; const ttsIpWindowMs = TTS_IP_WINDOW * 60 * 1000; const ttsIpMax = TTS_IP_MAX; @@ -27,11 +28,12 @@ const getEnvironmentVariables = () => { ttsUserWindowMs, ttsUserMax, ttsUserWindowInMinutes, + ttsViolationScore: TTS_VIOLATION_SCORE, }; }; const createTTSHandler = (ip = true) => { - const { ttsIpMax, ttsIpWindowInMinutes, ttsUserMax, ttsUserWindowInMinutes } = + const { ttsIpMax, ttsIpWindowInMinutes, ttsUserMax, ttsUserWindowInMinutes, ttsViolationScore } = getEnvironmentVariables(); return async (req, res) => { @@ -43,7 +45,7 @@ const createTTSHandler = (ip = true) => { windowInMinutes: ip ? ttsIpWindowInMinutes : ttsUserWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, ttsViolationScore); res.status(429).json({ message: 'Too many TTS requests. Try again later' }); }; }; diff --git a/api/server/middleware/limiters/uploadLimiters.js b/api/server/middleware/limiters/uploadLimiters.js index d9049f898..84eb6c071 100644 --- a/api/server/middleware/limiters/uploadLimiters.js +++ b/api/server/middleware/limiters/uploadLimiters.js @@ -11,6 +11,7 @@ const getEnvironmentVariables = () => { const FILE_UPLOAD_IP_WINDOW = parseInt(process.env.FILE_UPLOAD_IP_WINDOW) || 15; const FILE_UPLOAD_USER_MAX = parseInt(process.env.FILE_UPLOAD_USER_MAX) || 50; const FILE_UPLOAD_USER_WINDOW = parseInt(process.env.FILE_UPLOAD_USER_WINDOW) || 15; + const FILE_UPLOAD_VIOLATION_SCORE = process.env.FILE_UPLOAD_VIOLATION_SCORE; const fileUploadIpWindowMs = FILE_UPLOAD_IP_WINDOW * 60 * 1000; const fileUploadIpMax = FILE_UPLOAD_IP_MAX; @@ -27,6 +28,7 @@ const getEnvironmentVariables = () => { fileUploadUserWindowMs, fileUploadUserMax, fileUploadUserWindowInMinutes, + fileUploadViolationScore: FILE_UPLOAD_VIOLATION_SCORE, }; }; @@ -36,6 +38,7 @@ const createFileUploadHandler = (ip = true) => { fileUploadIpWindowInMinutes, fileUploadUserMax, fileUploadUserWindowInMinutes, + fileUploadViolationScore, } = getEnvironmentVariables(); return async (req, res) => { @@ -47,7 +50,7 @@ const createFileUploadHandler = (ip = true) => { windowInMinutes: ip ? fileUploadIpWindowInMinutes : fileUploadUserWindowInMinutes, }; - await logViolation(req, res, type, errorMessage); + await logViolation(req, res, type, errorMessage, fileUploadViolationScore); res.status(429).json({ message: 'Too many file upload requests. Try again later' }); }; }; diff --git a/e2e/playwright.config.a11y.ts b/e2e/playwright.config.a11y.ts index 7cf5eed90..064a15900 100644 --- a/e2e/playwright.config.a11y.ts +++ b/e2e/playwright.config.a11y.ts @@ -26,6 +26,15 @@ const config: PlaywrightTestConfig = { CONCURRENT_VIOLATION_SCORE: '0', MESSAGE_VIOLATION_SCORE: '0', NON_BROWSER_VIOLATION_SCORE: '0', + FORK_VIOLATION_SCORE: '0', + IMPORT_VIOLATION_SCORE: '0', + TTS_VIOLATION_SCORE: '0', + STT_VIOLATION_SCORE: '0', + FILE_UPLOAD_VIOLATION_SCORE: '0', + RESET_PASSWORD_VIOLATION_SCORE: '0', + VERIFY_EMAIL_VIOLATION_SCORE: '0', + TOOL_CALL_VIOLATION_SCORE: '0', + CONVO_ACCESS_VIOLATION_SCORE: '0', ILLEGAL_MODEL_REQ_SCORE: '0', LOGIN_MAX: '20', LOGIN_WINDOW: '1', diff --git a/e2e/playwright.config.local.ts b/e2e/playwright.config.local.ts index b69cbd851..5281836ac 100644 --- a/e2e/playwright.config.local.ts +++ b/e2e/playwright.config.local.ts @@ -26,6 +26,15 @@ const config: PlaywrightTestConfig = { CONCURRENT_VIOLATION_SCORE: '0', MESSAGE_VIOLATION_SCORE: '0', NON_BROWSER_VIOLATION_SCORE: '0', + FORK_VIOLATION_SCORE: '0', + IMPORT_VIOLATION_SCORE: '0', + TTS_VIOLATION_SCORE: '0', + STT_VIOLATION_SCORE: '0', + FILE_UPLOAD_VIOLATION_SCORE: '0', + RESET_PASSWORD_VIOLATION_SCORE: '0', + VERIFY_EMAIL_VIOLATION_SCORE: '0', + TOOL_CALL_VIOLATION_SCORE: '0', + CONVO_ACCESS_VIOLATION_SCORE: '0', ILLEGAL_MODEL_REQ_SCORE: '0', LOGIN_MAX: '20', LOGIN_WINDOW: '1',