Skip to content

fix: reject malformed API inputs - #41

Merged
lewiswigmore merged 2 commits into
mainfrom
fix/validate-api-inputs
Aug 30, 2026
Merged

lewiswigmore merged 2 commits into
mainfrom
fix/validate-api-inputs

Conversation

@lewiswigmore

Copy link
Copy Markdown
Owner

Summary

  • reject malformed messages, tool calls, content parts, and response formats instead of silently normalising them
  • validate image MIME types, canonical base64, signatures, and decoded size
  • return reliable JSON 413 responses while closing unbounded chunked uploads safely
  • bound integer configuration values and document the enforced limits

Verification

  • npm run test — 238 passed
  • npm run lint
  • npm run build
  • npm run package
  • npm audit --omit=dev — 0 vulnerabilities
  • independent fail-closed review passed with no security or logic findings

Copilot AI lite review requested due to automatic review settings August 30, 2026 15:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The current Content-Length oversize path delays the 413 until request end, enabling slow/huge uploads to tie up capacity and conflicting with the intended behavior of promptly returning a 413.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR tightens OpenWire’s HTTP API validation to fail closed on malformed inputs (messages/content parts/tool calls/response_format), adds stricter image input validation, and improves request-body limit handling so oversized uploads return consistent JSON errors.

Changes:

  • Enforce stricter request-shape validation for chat messages, content parts, tool calls, and response_format.
  • Add image data URI validation (MIME required, canonical base64, signature match, decoded size cap).
  • Add tests for malformed inputs and oversized request bodies; clamp numeric config values and document bounds.
File summaries
File Description
src/test/gateway.test.ts Adds coverage for JSON 413 responses and slow chunked oversized uploads, plus malformed message cases.
src/server/gateway.ts Adjusts 413 error handling and request-body reading logic to support safer oversized upload handling.
src/server/config.ts Introduces bounded integer normalization for numeric config values.
src/server/config.test.ts Adds tests verifying numeric config clamping behavior.
src/routes/json-mode.ts Tightens response_format parsing by requiring an explicit type when provided.
src/routes/json-mode.test.ts Adds test ensuring missing response_format.type is rejected.
src/routes/content.ts Strengthens content/message validation and enforces strict image data URI validation (type/base64/signature/size).
src/routes/content.test.ts Updates/extends tests for stricter content/message/tool-call and image validation behavior.
README.md Updates documentation to reflect stricter validation rules, limits, and image validation guarantees.
package.json Updates VS Code settings schema to bounded integer types and min/max constraints.
Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread package.json Outdated
Comment thread src/server/gateway.ts Outdated
@lewiswigmore

Copy link
Copy Markdown
Owner Author

Addressed both review findings in e4bda29:

  • maxRequestBodyMb now consistently says mebibytes (MiB).
  • Declared oversized bodies are rejected immediately. The server pauses the upload, flushes JSON 413, then allows only a 250 ms bounded drain grace so normal clients receive the response without EPIPE; incomplete uploads are destroyed before releasing the concurrency slot. Unknown chunked overflows still close immediately after the 413 is flushed.

Added regressions for normal oversized bodies, incomplete declared 100 MiB uploads, and unterminated chunked uploads. All 239 tests pass.

@lewiswigmore
lewiswigmore merged commit c7bb557 into main Aug 30, 2026
5 checks passed
@lewiswigmore
lewiswigmore deleted the fix/validate-api-inputs branch August 30, 2026 15:13
@andesyte-code-security

Copy link
Copy Markdown
Pre-merge checks · ✅ 2 · ⚠ 0 · ❌ 0 · ⏭ 1
Check Status Reason
PR title ✅ The title clearly describes rejecting malformed API inputs.
Description ✅ The body explains what changes were made and why with verification steps.
Linked issue ⏭ No linked issues were provided.

@andesyte-code-security

Copy link
Copy Markdown
Pre-merge checks · ✅ 2 · ⚠ 0 · ❌ 0 · ⏭ 1
Check Status Reason
PR title ✅ The title clearly describes the primary change of rejecting malformed API inputs.
Description ✅ The body explains what is being validated and why with verification steps included.
Linked issue ⏭ No linked issues were provided.

@andesyte-code-security

andesyte-code-security Bot commented Aug 30, 2026 •

Copy link
Copy Markdown

Walkthrough

This PR tightens input validation across the API gateway. Malformed messages, content parts, image payloads and response formats now return 400 errors instead of being silently normalised. Image data URIs are validated for MIME type, canonical base64, magic-byte signatures and decoded size. Oversized request bodies produce reliable JSON 413 responses with safe connection teardown, and integer configuration values are bounded and clamped.

Changes

File Summary
Input validation src/routes/content.ts, src/routes/json-mode.ts Reject malformed content scalars, unknown part types, missing response_format type, non-canonical base64, mismatched image signatures and oversized images with explicit 400 errors.
Request body size enforcement src/server/gateway.ts Add early rejection of declared-oversized bodies and safe drain/close handling to return reliable JSON 413 responses for both chunked and content-length uploads.
Configuration bounds src/server/config.ts, package.json Clamp numeric settings to bounded integer ranges and update the schema to declare minimum/maximum constraints.
Tests src/routes/content.test.ts, src/routes/json-mode.test.ts, src/server/config.test.ts, src/test/gateway.test.ts Add and update tests covering malformed input rejection, base64 validation, config clamping and 413 response behaviour.
Docs README.md Update documentation to reflect stricter validation behaviour and rejection semantics.

🎯 Effort: 3 (Moderate) · ⏱ ~30 minutes

Generated by Sebastion Code Security · docs

@andesyte-code-security andesyte-code-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Sebastion Code Security review

1 finding on this PR. ⚠️ 1 high

Sources: 1 LLM

Inline comments are posted on changed lines below.

Other findings (in scanned files but outside this diff)

  • HIGH hardcoded-secret · CWE-798 — package.json:95 — The default API key is a well-known static string "change-me-openwire-key". Users who do not change it are exposed to unauthenticated access from any local process. An attacker on the same machine can use this predictable token to invoke any language model the user has access to.
      Fix: Remove the default value or generate a random key on first activation and store it in VS Code's SecretStorage. At minimum, refuse to start the server when the key is still the default placeholder.

Findings also visible in Security tab.

Audited by Sebastion Code Security · docs · install on more repos

Prompt for all review comments with AI agents

In package.json:

  • Line 95: In package.json at line 95, the default API key is a well-known static string "change-me-openwire-key". Users who do not change it are exposed to unauthenticated access from any local process. An attacker on the same machine can use this predictable token to invoke any language model the user has access to. Fix: Remove the default value or generate a random key on first activation and store it in VS Code's SecretStorage. At minimum, refuse to start the server when the key is still the default placeholder. Context: rule hardcoded-secret and CWE CWE-798.

🔧 Autofix (action required)

Sebastion Code Security couldn't open a draft autofix PR because the installed GitHub App is missing Contents: Read and write. A repository owner must approve the pending permission at https://github.com/settings/installations, then push another commit to retry. This permission only lets Sebastion create fix branches and draft PRs; Sebastion cannot approve or merge them.

@andesyte-code-security andesyte-code-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Sebastion Code Security review

1 finding on this PR. ⚠️ 1 high

Sources: 1 LLM

Inline comments are posted on changed lines below.

Other findings (in scanned files but outside this diff)

  • HIGH hardcoded-secret · CWE-798 — package.json:95 — The default API key is a well-known static string "change-me-openwire-key". Users who do not change this value are exposed to unauthorized access from any local process. An attacker on the same machine can call the API with this predictable token.
      Fix: Remove the default value or generate a random key on first activation and store it in VS Code's SecretStorage. At minimum, refuse to start with the default key and force the user to set one.

Findings also visible in Security tab.

Audited by Sebastion Code Security · docs · install on more repos

Prompt for all review comments with AI agents

In package.json:

  • Line 95: In package.json at line 95, the default API key is a well-known static string "change-me-openwire-key". Users who do not change this value are exposed to unauthorized access from any local process. An attacker on the same machine can call the API with this predictable token. Fix: Remove the default value or generate a random key on first activation and store it in VS Code's SecretStorage. At minimum, refuse to start with the default key and force the user to set one. Context: rule hardcoded-secret and CWE CWE-798.

🔧 Autofix (action required)

Sebastion Code Security couldn't open a draft autofix PR because the installed GitHub App is missing Contents: Read and write. A repository owner must approve the pending permission at https://github.com/settings/installations, then push another commit to retry. This permission only lets Sebastion create fix branches and draft PRs; Sebastion cannot approve or merge them.

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