🔱 chore: Harden API Routes Against IDOR and DoS Attacks (#11760)

* 🔧 feat: Update user key handling in keys route and add comprehensive tests

- Enhanced the PUT /api/keys route to destructure request body for better clarity and maintainability.
- Introduced a new test suite for keys route, covering key update, deletion, and retrieval functionalities, ensuring robust validation and IDOR prevention.
- Added tests to verify handling of extraneous fields and missing optional parameters in requests.

* 🔧 fix: Enhance conversation deletion route with parameter validation

- Updated the DELETE /api/convos route to handle cases where the request body is empty or the 'arg' parameter is null/undefined, returning a 400 status with an appropriate error message for DoS prevention.
- Added corresponding tests to ensure proper validation and error handling for these scenarios, enhancing the robustness of the API.

* 🔧 fix: Improve request body validation in keys and convos routes

- Updated the DELETE /api/convos and PUT /api/keys routes to validate the request body, returning a 400 status for null or invalid bodies to enhance security and prevent potential DoS attacks.
- Added corresponding tests to ensure proper error handling for these scenarios, improving the robustness of the API.
This commit is contained in:
Danny Avila 2026-02-12 18:08:24 -05:00 committed by GitHub
parent 793ddbce9f
commit b8c31e7314
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 216 additions and 4 deletions

View file

@ -98,7 +98,7 @@ router.get('/gen_title/:conversationId', async (req, res) => {
router.delete('/', async (req, res) => {
let filter = {};
const { conversationId, source, thread_id, endpoint } = req.body.arg;
const { conversationId, source, thread_id, endpoint } = req.body?.arg ?? {};
// Prevent deletion of all conversations
if (!conversationId && !source && !thread_id && !endpoint) {
@ -160,7 +160,7 @@ router.delete('/all', async (req, res) => {
* @returns {object} 200 - The updated conversation object.
*/
router.post('/archive', validateConvoAccess, async (req, res) => {
const { conversationId, isArchived } = req.body.arg ?? {};
const { conversationId, isArchived } = req.body?.arg ?? {};
if (!conversationId) {
return res.status(400).json({ error: 'conversationId is required' });
@ -194,7 +194,7 @@ const MAX_CONVO_TITLE_LENGTH = 1024;
* @returns {object} 201 - The updated conversation object.
*/
router.post('/update', validateConvoAccess, async (req, res) => {
const { conversationId, title } = req.body.arg ?? {};
const { conversationId, title } = req.body?.arg ?? {};
if (!conversationId) {
return res.status(400).json({ error: 'conversationId is required' });