Skip to content

fix: add .max(500) path length validation to all AI tool schemas - #532

Open
Somil450 wants to merge 1 commit into
piyushdotcomm:mainfrom
Somil450:fix/522-validate-path-length-in-tool-schemas
Open

fix: add .max(500) path length validation to all AI tool schemas#532
Somil450 wants to merge 1 commit into
piyushdotcomm:mainfrom
Somil450:fix/522-validate-path-length-in-tool-schemas

Conversation

@Somil450

Copy link
Copy Markdown

Closes #522

The path field in all four tool schemas (read_file, edit_file, edit_multiple_files, delete_file) was an unbounded z.string(). While the content field already had a 100k char cap, an adversarial or runaway AI could craft an extremely long path string with no validation.

Adds .max(500) to every path field - plenty for any real file path, blocks unbounded payload attacks.

Summary

  • what changed
  • why it changed

Summary

Closes #522

Adds .max(500) length validation to every path field across all four AI tool schemas in app/api/chat/tools.ts.

Problem

The content field already had a 100,000-character cap, but all path fields were unbounded z.string() with no length limit. An adversarial or runaway AI could generate an extremely long path string, bypassing input validation and wasting server resources.

Change

// Before
path: z.string().describe("The file path relative to the project root")

// After
path: z.string().max(500).describe("The file path relative to the project root")

Applied to all 4 tool schemas:

  • read_file
    • edit_file
    • edit_multiple_files (inner path field)
    • delete_file
      500 characters is well beyond any realistic file path, while blocking unbounded payload attacks.

Files Changed

  • app/api/chat/tools.ts - 4 lines changed (one per tool schema)

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • Test or CI improvement
  • Starter template change

Related issue

Closes #

Validation

  • npm run lint
  • npm test
  • npm run build

List any additional manual verification you performed:

Screenshots or recordings

Add screenshots or short recordings for UI changes when relevant.

Checklist

  • I kept this PR focused on one primary change
  • I updated documentation if behavior changed
  • I did not commit secrets, local logs, or scratch files
  • I am requesting review on the correct scope

Closes piyushdotcomm#522

The path field in all four tool schemas (read_file, edit_file,
edit_multiple_files, delete_file) was an unbounded z.string(). While the
content field already had a 100k char cap, an adversarial or runaway AI
could craft an extremely long path string with no validation.

Adds .max(500) to every path field - plenty for any real file path,
blocks unbounded payload attacks.
@Somil450
Somil450 requested a review from piyushdotcomm as a code owner July 31, 2026 08:48
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Somil450, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 54 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c5b63d69-6a98-45d3-8171-fd184845083d

📥 Commits

Reviewing files that changed from the base of the PR and between 4ffe26f and c6971c8.

📒 Files selected for processing (1)
  • app/api/chat/tools.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

👋 Thanks for opening a PR, @Somil450!

Your PR has entered the 🚦 PR Review Pipeline.

Standard PR detected — your PR will follow the standard review pipeline.


What happens next

Stage Reviewer Checks
Stage 1 — Automated Validation 🤖 Bot DCO · Format · AI/Slop · Duplicate
Stage 2 — Human Review 👥 Maintainer Code + Quality Review
Stage 3 — PA / Maintainer Review 🔑 Project Admin Final Merge Decision

A pipeline status comment will appear below and update automatically as your PR progresses.


While you wait

  • Sign all commits (git commit -s)
  • Link your issue (Closes #123)
  • Use a feature branch (not main)
  • Avoid unrelated changes

This comment is posted only once.

@github-actions github-actions Bot added the bug Something isn't working label Jul 31, 2026
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Fix: cap AI tool path inputs to 500 chars in Zod schemas

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Add 500-character max length validation to all AI tool path inputs.
• Prevent unbounded payload/DoS risk from runaway or adversarial tool calls.
• Keep existing content and batch-size limits unchanged.
Diagram

graph TD
  A{{"AI model"}} --> B(["Chat tool runtime"]) --> C["app/api/chat/tools.ts"] --> D(["Zod: validate tool input"]) --> E[("Project files")]
  subgraph Legend
    direction LR
    _actor{{"Actor"}} ~~~ _svc(["Service/Runtime"]) ~~~ _file["Code module"] ~~~ _db[("Filesystem")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Centralize `MAX_PATH_CHARS` and reuse across schemas
  • ➕ Ensures consistent policy and easier future adjustments
  • ➕ Makes security limits more discoverable alongside other caps (content/batch)
  • ➖ Slightly more refactor than necessary for the immediate fix
2. Add `path` semantic validation (e.g., traversal/null bytes) via `refine()`
  • ➕ Mitigates broader path-based attacks beyond oversized payloads
  • ➕ Can enforce repo-relative constraints more explicitly
  • ➖ More complex; higher risk of blocking legitimate edge-case paths
  • ➖ May need platform-specific nuance (Windows separators, etc.)

Recommendation: The PR’s approach (simple .max(500)) is the right minimal, low-risk mitigation for unbounded payloads. Consider a follow-up to introduce a shared MAX_PATH_CHARS constant (and optionally traversal-focused refine() checks) if threat modeling indicates broader path validation is needed.

Files changed (1) +4 / -4

Bug fix (1) +4 / -4
tools.tsAdd '.max(500)' validation to all AI tool 'path' fields +4/-4

Add '.max(500)' validation to all AI tool 'path' fields

• Bounds 'path' strings to 500 characters for 'read_file', 'edit_file', 'edit_multiple_files.changes[].path', and 'delete_file'. This complements existing content-size and batch-size DoS protections by preventing oversized path payloads.

app/api/chat/tools.ts

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 22 rules

Grey Divider


Remediation recommended

1. path schema allows traversal 📘 Rule violation ⛨ Security
Description
The updated path fields only cap string length and still accept traversal/absolute-path patterns
(e.g., ../, leading /, backslashes). If these tool inputs are used for filesystem operations,
this can enable directory traversal outside the intended project root.
Code

app/api/chat/tools.ts[R18-35]

+        path: z.string().max(500).describe("The file path relative to the project root, e.g. src/App.tsx or package.json"),
    }),
    edit_file: z.object({
-        path: z.string().describe("The file path relative to the project root"),
+        path: z.string().max(500).describe("The file path relative to the project root"),
        // Prevent overly large content (character limit)
        content: z.string()
            .max(MAX_FILE_CONTENT_CHARS, { message: `content exceeds max characters (${MAX_FILE_CONTENT_CHARS})` }),
    }),
    edit_multiple_files: z.object({
        changes: z.array(z.object({
-            path: z.string().describe("The file path relative to the project root"),
+            path: z.string().max(500).describe("The file path relative to the project root"),
            // Same protections for batch changes
            content: z.string()
                .max(MAX_FILE_CONTENT_CHARS, { message: `content exceeds max characters (${MAX_FILE_CONTENT_CHARS})` }),
        })).max(MAX_BATCH_CHANGES, { message: `changes array exceeds max batch size (${MAX_BATCH_CHANGES})` }).describe("An array of file modifications to execute as a batch"),
    }),
    delete_file: z.object({
-        path: z.string().describe("The file path relative to the project root"),
+        path: z.string().max(500).describe("The file path relative to the project root"),
Relevance

●●● Strong

Team previously accepted path sanitization to prevent traversal; adding traversal/absolute-path
checks aligns with existing input-hardening work.

PR-#211
PR-#96

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance requires guarding file-path handling against directory traversal at system boundaries.
The modified schema lines show path is validated only as a bounded string (z.string().max(500))
with no constraints preventing traversal sequences or absolute paths.

Rule 599986: Protect file path handling against directory traversal
Rule 599980: Validate all inputs at system boundaries
app/api/chat/tools.ts[18-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`path` inputs for `read_file`, `edit_file`, `edit_multiple_files.changes[].path`, and `delete_file` are only constrained by length (`.max(500)`) and do not explicitly reject directory traversal or absolute paths.

## Issue Context
These schemas represent a system-boundary input validation layer for tool calls and should enforce safe relative paths (e.g., reject `..`, leading `/`, and `\\`).

## Fix Focus Areas
- app/api/chat/tools.ts[18-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread app/api/chat/tools.ts
Comment on lines +18 to +35
path: z.string().max(500).describe("The file path relative to the project root, e.g. src/App.tsx or package.json"),
}),
edit_file: z.object({
path: z.string().describe("The file path relative to the project root"),
path: z.string().max(500).describe("The file path relative to the project root"),
// Prevent overly large content (character limit)
content: z.string()
.max(MAX_FILE_CONTENT_CHARS, { message: `content exceeds max characters (${MAX_FILE_CONTENT_CHARS})` }),
}),
edit_multiple_files: z.object({
changes: z.array(z.object({
path: z.string().describe("The file path relative to the project root"),
path: z.string().max(500).describe("The file path relative to the project root"),
// Same protections for batch changes
content: z.string()
.max(MAX_FILE_CONTENT_CHARS, { message: `content exceeds max characters (${MAX_FILE_CONTENT_CHARS})` }),
})).max(MAX_BATCH_CHANGES, { message: `changes array exceeds max batch size (${MAX_BATCH_CHANGES})` }).describe("An array of file modifications to execute as a batch"),
}),
delete_file: z.object({
path: z.string().describe("The file path relative to the project root"),
path: z.string().max(500).describe("The file path relative to the project root"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. path schema allows traversal 📘 Rule violation ⛨ Security

The updated path fields only cap string length and still accept traversal/absolute-path patterns
(e.g., ../, leading /, backslashes). If these tool inputs are used for filesystem operations,
this can enable directory traversal outside the intended project root.
Agent Prompt
## Issue description
`path` inputs for `read_file`, `edit_file`, `edit_multiple_files.changes[].path`, and `delete_file` are only constrained by length (`.max(500)`) and do not explicitly reject directory traversal or absolute paths.

## Issue Context
These schemas represent a system-boundary input validation layer for tool calls and should enforce safe relative paths (e.g., reject `..`, leading `/`, and `\\`).

## Fix Focus Areas
- app/api/chat/tools.ts[18-35]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] Validate input length on content field in AI tool calls

2 participants