Skip to content

Feature/validate conversations - #212

Merged
Premshaw23 merged 3 commits into
Premshaw23:masterfrom
omnipotentchaos:feature/validate-conversations
May 20, 2026
Merged

Feature/validate conversations#212
Premshaw23 merged 3 commits into
Premshaw23:masterfrom
omnipotentchaos:feature/validate-conversations

Conversation

@omnipotentchaos

Copy link
Copy Markdown
Contributor

What type of PR is this?

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation
  • 🎨 UI/UX improvement
  • ⚡ Performance improvement
  • 🔒 Security fix

Description

Secures the /api/conversations endpoint by enforcing strict schema/type checks via Zod, input sanitization, and request payload size limits. These enhancements prevent database bloat and XSS code injection.

Related Issues

Closes #162

Changes Made

  • Size Limits: Enforced an early 413 Payload Too Large rejection for request bodies exceeding 1MB.
  • Type Validation: Defined a strict zod schema to ensure userMessage and botMessage are required strings with a maximum limit of 10,000 characters (returns 400 Bad Request on type anomalies).
  • Sanitization: Stripped HTML <script> tags to prevent XSS script execution.
  • Documentation: Created docs/conversations-api.md outlining the API inputs, bounds, and responses.
  • Testing: Added tests in components/_tests_/conversationsRoute.test.js covering large payload size limits (> 1MB), type errors, missing inputs, and script stripping.

Testing

How did you test these changes?

  • Tested locally (all 41 tests pass, Next.js build passes)

Screenshots (if applicable)

N/A

Checklist

  • No hardcoded secrets or credentials
  • .env.local is not committed
  • Code follows project style
  • Changes are documented (docs/conversations-api.md)
  • Build passes locally (npm run build)
  • No console errors/warnings

…y Firebase ID Token in the authorization header- Early reject unauthenticated requests with 401 Unauthorized- Enriched conversations log with userId and userEmail metadata- Added comprehensive Jest unit tests covering all auth outcomes
…ne Zod schema to enforce types and 10k character limits- Enforce maximum raw payload size of 1MB, returning 413- Sanitize string inputs server-side by stripping script tags- Create api documentation file docs/conversations-api.md- Add new Jest tests covering all validation criteria
…into feature/authenticate-conversations

Necesssary
Copilot AI review requested due to automatic review settings May 20, 2026 19:01
@vercel

vercel Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

@omnipotentchaos is attempting to deploy a commit to the Prem Shaw's projects Team on Vercel.

A member of the Team first needs to authorize it.

@Premshaw23
Premshaw23 merged commit 206ca30 into Premshaw23:master May 20, 2026
9 of 10 checks passed
@Premshaw23

Copy link
Copy Markdown
Owner

Done 👍

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the /api/conversations POST route by adding request validation (schema + bounds), basic sanitization, and payload size limiting, along with accompanying documentation and tests, addressing Issue #162.

Changes:

  • Added Zod-based schema validation for userMessage/botMessage and added <script> tag stripping.
  • Enforced a 1MB payload size cap (header-based and post-read checks) and improved error responses for invalid payloads.
  • Added endpoint documentation and a new Jest test suite for auth/validation/size-limit behavior.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
package.json Adds zod dependency for runtime schema validation.
package-lock.json Locks zod dependency resolution.
app/api/conversations/route.js Implements auth enforcement, size checks, Zod validation, and sanitization before DB insert.
components/tests/conversationsRoute.test.js Adds tests for auth failures, oversize payloads, invalid JSON, type/required errors, and sanitization.
docs/conversations-api.md Documents the endpoint contract, limits, and response codes.
Comments suppressed due to low confidence (1)

docs/conversations-api.md:30

  • The payload fields table rows start with ||, which creates an unintended empty first column in GitHub-flavored markdown. Switch to a single leading | per row so the table renders as intended.
| Field | Type | Required | Limits | Description |
|---|---|---|---|---|
| `userMessage` | `string` | **Yes** | Min 1 char, Max 10,000 chars | The message sent by the user. Stripped of `<script>` tags. |
| `botMessage` | `string` | **Yes** | Min 1 char, Max 10,000 chars | The message returned by the bot. Stripped of `<script>` tags. |


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +39
const authorization = req.headers.get("authorization");
const token = authorization?.split(" ")[1];

const decodedToken = await verifyFirebaseToken(token);

if (!decodedToken) {
return jsonError("Unauthorized", 401);
}
Comment on lines +13 to +27
userMessage: z.string({
required_error: "userMessage is required",
invalid_type_error: "userMessage must be a string",
})
.min(1, "userMessage cannot be empty")
.max(10000, "userMessage must not exceed 10,000 characters")
.transform(sanitizeText),

botMessage: z.string({
required_error: "botMessage is required",
invalid_type_error: "botMessage must be a string",
})
.min(1, "botMessage cannot be empty")
.max(10000, "botMessage must not exceed 10,000 characters")
.transform(sanitizeText),
const body = await response.json();

expect(response.status).toBe(400);
expect(body.error).toContain("expected string, received number");
const body = await response.json();

expect(response.status).toBe(400);
expect(body.error).toContain("expected string, received undefined");
Comment thread docs/conversations-api.md
Comment on lines +15 to +18
| Header | Value | Description |
|---|---|---|
| `Authorization` | `Bearer <Firebase_ID_Token>` | **Required.** Firebase authentication token to verify user identity. |
| `Content-Type` | `application/json` | **Required.** Must be JSON payload. |
Comment on lines +35 to +45
const decodedToken = await verifyFirebaseToken(token);

if (!decodedToken) {
return jsonError("Unauthorized", 401);
}

// Enforce maximum document size (1MB = 1048576 bytes)
const contentLength = req.headers.get("content-length");
if (contentLength && parseInt(contentLength, 10) > 1024 * 1024) {
return jsonError("Payload too large", 413);
}
Comment on lines +32 to +38
const authorization = req.headers.get("authorization");
const token = authorization?.split(" ")[1];

const decodedToken = await verifyFirebaseToken(token);

if (!decodedToken) {
return jsonError("Unauthorized", 401);
@github-actions github-actions Bot added GSSoC'26 Part of GirlScript Summer of Code 2026 mentor:Ayushh-Sharmaa GSSoC: Mentor — @Ayushh-Sharmaa and removed mentor:Premshaw23 labels Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gssoc:approved GSSoC'26 Part of GirlScript Summer of Code 2026 level:intermediate mentor:Ayushh-Sharmaa GSSoC: Mentor — @Ayushh-Sharmaa type:feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SECURITY: No input validation/size limits for conversations

3 participants