Skip to content

[codex] Bound MCP integer arguments#323

Merged
ramimbo merged 1 commit into
ramimbo:mainfrom
rounaksalim95:codex/bounty-292-mcp-integer-bounds
May 25, 2026
Merged

[codex] Bound MCP integer arguments#323
ramimbo merged 1 commit into
ramimbo:mainfrom
rounaksalim95:codex/bounty-292-mcp-integer-bounds

Conversation

@rounaksalim95
Copy link
Copy Markdown
Contributor

@rounaksalim95 rounaksalim95 commented May 25, 2026

Summary

  • Bound shared MCP integer arguments to SQLite's integer range before database lookups
  • Return JSON-RPC invalid argument errors instead of 500s for oversized get_bounty, get_ledger_entry, and submit_work_proof integer inputs
  • Add regression coverage for oversized string and JSON integer inputs

Bounty #292

Repro Before Fix

  • MCP get_bounty with id = "9" * 40 returned 500 Internal Server Error
  • MCP get_ledger_entry with sequence = "9" * 40 returned 500 Internal Server Error

Validation

  • uv run pytest tests/test_api_mcp.py::test_mcp_rejects_oversized_integer_arguments_without_500 tests/test_api_mcp.py::test_mcp_get_bounty_rejects_fractional_id tests/test_api_mcp.py::test_mcp_get_bounty_rejects_non_positive_id -q -> 8 passed
  • uv run ruff check app/main.py tests/test_api_mcp.py -> passed
  • uv run mypy app -> passed
  • uv run ruff check . -> passed
  • uv run pytest -> 279 passed, 2 warnings
  • git diff --check -> passed

No secrets, wallet material, deployment credentials, private vulnerability details, payout details, or MRWK price claims are included.

Summary by CodeRabbit

  • Bug Fixes

    • Improved integer argument validation with stricter bounds checking to prevent invalid values.
    • Enhanced error handling for oversized integer inputs, returning appropriate error messages instead of server errors.
  • Tests

    • Added regression test for oversized integer argument rejection.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

📝 Walkthrough

Walkthrough

This PR adds bounds validation to integer arguments in MCP tool calls, preventing oversized values from causing uncontrolled failures. The implementation tightens _call_mcp_tool's int_arg helper with SQLite range checks, and a new regression test verifies the validation rejects oversized integers with proper MCP error responses.

Changes

MCP Integer Argument Bounds Validation

Layer / File(s) Summary
Integer argument bounds validation
app/main.py
The int_arg helper function in _call_mcp_tool now validates integer inputs against SQLite integer bounds, rejecting values outside [-SQLITE_INTEGER_MAX - 1, SQLITE_INTEGER_MAX] with explicit error handling for both raw int and numeric string inputs.
Oversized integer argument rejection test
tests/test_api_mcp.py
A parametrized regression test covers oversized integer arguments for multiple MCP tools using TestClient with raise_server_exceptions=False, asserting HTTP 200 with MCP JSON-RPC error code -32602 (invalid tool arguments) instead of server errors.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • ramimbo/mergework#300: Both PRs update app/main.py to add/extend validation that rejects oversized user-supplied integers against SQLite bounds (main PR in the MCP _call_mcp_tool argument parsing; related PR in _positive_bounty_id/_positive_ledger_sequence), preventing uncontrolled failures from large integer inputs.

Suggested reviewers

  • MolhamHamwi
  • weilixiong
  • TateLyman
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Bound MCP integer arguments' directly describes the main change: adding bounds validation to MCP integer arguments to prevent oversized values.
Description check ✅ Passed The description includes all critical sections: a clear summary of changes, reproduction steps, comprehensive validation evidence, and bounty reference, closely matching the template requirements.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_api_mcp.py`:
- Around line 847-855: The parametrized test matrix for oversized integers
misses negative overflow and raw-int paths for some tools; update the
pytest.mark.parametrize data in tests/test_api_mcp.py to add entries exercising
the negative overflow value (-2**63 - 1) and the raw 2**63 value for
get_ledger_entry and submit_work_proof in addition to the existing cases (i.e.,
extend the tuples for ("get_ledger_entry", {"sequence": ...}, 18) and both
("submit_work_proof", {"bounty_id": ...}, 19) and ("submit_work_proof",
{"issue_number": ...}, 20) so each changed bounds path is covered).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 34220a7f-8d29-45d1-8b83-714458332d2a

📥 Commits

Reviewing files that changed from the base of the PR and between 4b8baf7 and 130cb8d.

📒 Files selected for processing (2)
  • app/main.py
  • tests/test_api_mcp.py

Comment thread tests/test_api_mcp.py
Comment on lines +847 to +855
@pytest.mark.parametrize(
("tool_name", "arguments", "request_id"),
[
("get_bounty", {"id": "9" * 40}, 16),
("get_bounty", {"id": 2**63}, 17),
("get_ledger_entry", {"sequence": "9" * 40}, 18),
("submit_work_proof", {"bounty_id": "9" * 40}, 19),
("submit_work_proof", {"issue_number": "9" * 40}, 20),
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Expand oversized-integer matrix to cover lower-bound and raw-int paths.

This regression misses the negative overflow branch (< -2**63) and only validates raw oversized JSON int for one tool. Please add cases like -2**63 - 1 and raw 2**63 for get_ledger_entry/submit_work_proof too, so every changed bounds path is exercised.

As per coding guidelines, tests/**/*.py: Add or update tests for changed behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_api_mcp.py` around lines 847 - 855, The parametrized test matrix
for oversized integers misses negative overflow and raw-int paths for some
tools; update the pytest.mark.parametrize data in tests/test_api_mcp.py to add
entries exercising the negative overflow value (-2**63 - 1) and the raw 2**63
value for get_ledger_entry and submit_work_proof in addition to the existing
cases (i.e., extend the tuples for ("get_ledger_entry", {"sequence": ...}, 18)
and both ("submit_work_proof", {"bounty_id": ...}, 19) and ("submit_work_proof",
{"issue_number": ...}, 20) so each changed bounds path is covered).

Copy link
Copy Markdown
Contributor

@ayskobtw-lil ayskobtw-lil left a comment

Choose a reason for hiding this comment

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

No blockers from my review.

Evidence checked:

  • Inspected the PR diff for app/main.py and tests/test_api_mcp.py.
  • Verified int_arg() now rejects bools, non-integer strings, raw integers above SQLite's signed 64-bit range, numeric strings above range, and values below -2**63 before they reach SQLAlchemy/SQLite-backed lookups.
  • Checked the changed MCP paths that consume bounded integers: get_bounty, get_ledger_entry, submit_work_proof by bounty_id, and submit_work_proof by issue_number.
  • Confirmed positive_int_arg() still applies the existing non-positive rejection after range validation, so negative in-range values remain invalid for these positive-only tool arguments.
  • Non-blocking coverage note: CodeRabbit's suggested matrix expansion would add useful explicit cases for raw 2**63 and negative overflow on every tool, but I verified those paths manually and they are covered through the shared int_arg() behavior.

Validation run on current PR head 130cb8d:

  • python -m pytest tests/test_api_mcp.py::test_mcp_rejects_oversized_integer_arguments_without_500 tests/test_api_mcp.py::test_mcp_rejects_invalid_string_arguments tests/test_api_mcp.py::test_mcp_get_bounty_rejects_non_positive_id -q -> 13 passed
  • Extra manual MCP probe for raw 2**63 and -(2**63)-1 on get_ledger_entry, submit_work_proof.bounty_id, and submit_work_proof.issue_number -> all returned JSON-RPC -32602 without 500s.
  • python -m ruff check app/main.py tests/test_api_mcp.py -> All checks passed!
  • python -m ruff format --check app/main.py tests/test_api_mcp.py -> 2 files already formatted
  • git diff --check HEAD~1..HEAD -> clean

Copy link
Copy Markdown

@weilixiong weilixiong left a comment

Choose a reason for hiding this comment

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

Reviewed:

Files: app/main.py (int_arg → bounds check with SQLITE_INTEGER_MAX), tests/test_api_mcp.py (5 parametrized oversized argument tests)

Checked: int_arg now validates parsed value against [-SQLITE_INTEGER_MAX-1, SQLITE_INTEGER_MAX]. Covers int, string, and bool input paths. Consistent with PR#300/#312/#313 hardening pattern. Tests cover get_bounty, get_ledger_entry, submit_work_proof with oversized IDs/sequences.

CI: ✅ Quality/readiness/docs/image

Risk: LOW — 2 files, +53/−4, input validation hardening, consistent with prior PRs

Copy link
Copy Markdown

@rebel117 rebel117 left a comment

Choose a reason for hiding this comment

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

Reviewed the int_arg bounds change.

The core logic is sound: SQLITE_INTEGER_MAX = 2**63 - 1 and the check parsed < -SQLITE_INTEGER_MAX - 1 or parsed > SQLITE_INTEGER_MAX correctly limits accepted values to the SQLite 64-bit signed integer range [-2^63, 2^63-1].

Checked locally:

  • pytest tests/test_api_mcp.py -> 68 passed
  • ruff check app/main.py -> all checks passed

One observation: the test parametrize for get_bounty id: 2**63 sends a Python int that exceeds JavaScript safe integer range (2^53). This is fine for the Python test client and the JSON-RPC handler, but worth noting that a browser-based JSON-RPC caller would lose precision before the server ever sees the value. Not a blocker for this PR, just a note for anyone extending MCP test coverage later.

No secrets, wallet material, or price claims.

@ramimbo ramimbo merged commit 1b41a19 into ramimbo:main May 25, 2026
2 checks passed
@ramimbo ramimbo added mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded labels May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants