Skip to content

Conversation

@amikofalvy
Copy link
Collaborator

Summary

Implements API-level request size validation independent of model constraints. Both Run API and Manage API now enforce a configurable 1GB default limit through Content-Length header validation before body parsing.

Changes

Core Infrastructure

  • Added payload_too_large error code (413) to the core error system
  • Created request-size-limit middleware with configurable maxRequestSizeBytes
  • Updated ServerOptions to support maxRequestSizeBytes configuration (default: 1GB)
  • Applied middleware to both agents-run-api and agents-manage-api
  • Updated OpenAPI schemas to document 413 error responses in common error response schemas

Implementation Details

  • Middleware validates Content-Length headers before expensive body parsing
  • Skips safe methods (GET/HEAD/OPTIONS) that don't typically have request bodies
  • Returns proper Problem+JSON error responses when limits are exceeded
  • Error response includes both received size and maximum allowed size for debugging

Testing

  • 18 unit tests for middleware logic (method skipping, size validation, error responses)
  • 9 integration tests for Run API (default/custom limits, HTTP methods, response format)
  • 9 integration tests for Manage API (matching Run API test coverage)
  • All tests passing (36 new tests)

Documentation

  • Comprehensive API reference docs at /docs/api-reference/request-limits
  • Includes: Overview, configuration examples, best practices, troubleshooting, client-side validation examples
  • Added to navigation for discoverability

Why 1GB?

The 1GB default is intentionally set high to be well above any model's context window requirements while still providing protection against abuse. This is purely an API-level limit independent of model constraints.

Configuration Example

import { createExecutionHono } from '@inkeep/agents-run-api';

const serverConfig = {
  serverOptions: {
    maxRequestSizeBytes: 536870912, // 512MB custom limit
  },
};

const app = createExecutionHono(serverConfig, credentialStores);

Error Response Example

{
  "title": "Payload Too Large",
  "status": 413,
  "detail": "Request payload size (1073741825 bytes) exceeds maximum allowed size of 1073741824 bytes",
  "code": "payload_too_large",
  "error": {
    "code": "payload_too_large",
    "message": "Request payload exceeds maximum allowed size"
  }
}

Related Files

  • packages/agents-core/src/middleware/request-size-limit.ts (new middleware)
  • packages/agents-core/src/utils/error.ts (413 error code support)
  • packages/agents-core/src/types/server.ts (ServerOptions configuration)
  • agents-run-api/src/app.ts (middleware application)
  • agents-manage-api/src/app.ts (middleware application)
  • agents-docs/content/docs/api-reference/request-limits.mdx (documentation)

🤖 Generated with Claude Code

Implements API-level request size validation independent of model constraints.
Both Run API and Manage API now enforce a configurable 1GB default limit through
Content-Length header validation before body parsing.

Core Changes:
- Added payload_too_large error code (413) to error system
- Created request-size-limit middleware with configurable maxRequestSizeBytes
- Updated ServerOptions to support maxRequestSizeBytes configuration
- Applied middleware to both agents-run-api and agents-manage-api
- Updated OpenAPI schemas to document 413 error responses

Testing:
- Unit tests for middleware (18 tests)
- Integration tests for Run API (9 tests)
- Integration tests for Manage API (9 tests)
- All tests passing

Documentation:
- Added comprehensive API reference docs at /docs/api-reference/request-limits
- Includes configuration examples, best practices, and troubleshooting

The middleware validates Content-Length headers before expensive body parsing,
skips safe methods (GET/HEAD/OPTIONS), and returns proper Problem+JSON error
responses when limits are exceeded.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@changeset-bot
Copy link

changeset-bot bot commented Oct 15, 2025

⚠️ No Changeset found

Latest commit: f98c10a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Oct 15, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
agents-docs Ready Ready Preview Comment Oct 15, 2025 8:55pm
agents-manage-api Ready Ready Preview Comment Oct 15, 2025 8:55pm
agents-manage-ui Ready Ready Preview Comment Oct 15, 2025 8:55pm
agents-run-api Ready Ready Preview Comment Oct 15, 2025 8:55pm

@claude
Copy link

claude bot commented Oct 15, 2025

Claude finished @amikofalvy's task —— View job


PR Review: Request Size Limit Implementation

Review Tasks

  • Read repository guidelines and setup
  • Analyze core middleware implementation
  • Review API integration patterns
  • Examine error handling and types
  • Evaluate test coverage and quality
  • Review documentation completeness
  • Check consistency with existing patterns
  • Assess system design and architecture
  • Provide comprehensive feedback

System Design & Architecture Review

✅ Strong Points

Excellent Implementation Architecture:

  • Early validation via Content-Length header before expensive body parsing - this is a smart performance optimization
  • Proper separation of concerns with dedicated middleware in agents-core package
  • Consistent integration across both APIs using shared ServerConfig.serverOptions.maxRequestSizeBytes
  • Comprehensive test coverage (36 tests total: 18 unit + 9 integration per API)
  • Well-structured documentation with clear examples

Security & Performance:

  • Protects against DoS attacks without parsing large payloads
  • Graceful handling of missing/invalid Content-Length headers
  • Appropriate default of 1GB balances protection with usability
  • Proper HTTP method filtering (skips GET/HEAD/OPTIONS)

🔍 Areas for Consideration

1. CRITICAL: Transfer-Encoding Bypass Vulnerability

Issue: The middleware only validates Content-Length but ignores Transfer-Encoding: chunked requests, which can bypass size limits entirely.

// Current implementation vulnerability:
// POST /api/endpoint HTTP/1.1
// Transfer-Encoding: chunked
// (no Content-Length header)
// [unlimited chunked data can be sent]

Recommendation: Add chunked transfer validation:

// In request-size-limit.ts around line 62
const transferEncoding = c.req.header('transfer-encoding');
if (transferEncoding?.toLowerCase().includes('chunked')) {
  // For chunked requests, we need to either:
  // 1. Reject them outright for simplicity, or  
  // 2. Implement chunked request size tracking
  logger.warn(
    { method, path: c.req.path },
    'Chunked transfer encoding not supported - rejecting for size limit compliance'
  );
  throw createApiError({
    code: 'bad_request',
    message: 'Chunked transfer encoding not supported. Please use Content-Length header.',
  });
}

2. Configuration & Extensibility Issues

Issue: Hard-coded HTTP method skipping reduces flexibility:

// Current: hard-coded method check
if (method === 'GET' || method === 'HEAD' || method === 'OPTIONS') {
  return next();
}

Recommendation: Make methods configurable:

export interface RequestSizeLimitOptions {
  maxRequestSizeBytes?: number;
  skipMethods?: string[]; // Allow customization
}

const skipMethods = options.skipMethods ?? ['GET', 'HEAD', 'OPTIONS'];
if (skipMethods.includes(method)) {
  return next();
}

Issue: No per-route size limits capability.

Recommendation: Consider future extensibility for per-endpoint limits:

// Future: per-route configuration
export interface RequestSizeLimitOptions {
  maxRequestSizeBytes?: number;
  routeSpecificLimits?: Record<string, number>;
}

3. Error Handling & Monitoring

Issue: Limited observability for security monitoring.

Recommendation: Enhanced logging for security analysis:

// Around line 87, enhance logging:
logger.warn(
  {
    requestSize,
    maxSize,
    method,
    path: c.req.path,
    userAgent: c.req.header('user-agent'),
    clientIp: c.req.header('x-forwarded-for') || c.req.header('x-real-ip'), // Add IP tracking
    timestamp: new Date().toISOString(),
  },
  'Request payload size limit exceeded - potential abuse'
);

4. Type Safety & Integration Patterns

Issue: Minor type safety gap in ServerOptions integration.

Current in packages/agents-core/src/types/server.ts:94:
The comment states "This is an API-level limit independent of model constraints" but doesn't enforce this architecturally.

Recommendation: Consider separating API-level vs model-level size constraints in the type system for clarity:

export interface ServerOptions {
  /** API-level request size limit (independent of model constraints) */
  maxRequestSizeBytes?: number;
  /** Future: model-specific constraints could go here */
  // modelConstraints?: ModelSizeConstraints;
}

5. Testing & Edge Cases

Minor Testing Gap: Integration tests use /health endpoint which doesn't process request bodies, making the tests somewhat artificial.

Recommendation: Add tests against actual endpoints that consume request bodies:

// Test against actual chat/agent endpoints that would process bodies
const res = await app.request('/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Length': contentLength,
    'Content-Type': 'application/json',
    'Authorization': 'Bearer test-key'
  },
  body: JSON.stringify({ /* actual request body */ })
});

6. Documentation & API Design

Missing: Client-side implementation guidance for handling 413 responses.

Recommendation: Add to documentation:

## Client-Side Handling

```javascript
try {
  const response = await fetch('/api/endpoint', { 
    method: 'POST', 
    body: largePayload 
  });
} catch (error) {
  if (error.response?.status === 413) {
    // Implement chunking, compression, or request splitting
    console.log('Request too large, consider splitting into smaller requests');
  }
}

### **Overall Assessment**

**Excellent foundation** with thoughtful design decisions. The Transfer-Encoding vulnerability is the primary concern requiring immediate attention. The implementation follows repository patterns well and provides good extensibility.

**Priority Actions:**
1. **HIGH**: Address Transfer-Encoding bypass vulnerability
2. **MEDIUM**: Consider configurability enhancements
3. **LOW**: Improve monitoring and documentation

This is a well-engineered feature that enhances API security significantly once the chunked transfer issue is addressed.

---

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants