Repository navigation
Description
Describe the bug
These tools advertise page with minimum: 1 (and perPage 1..100) in tools/list. At runtime they validate against a relaxed clone of the schema with the bounds removed, and they forward the value unchanged:
page: -1is sent as?page=-1.page: 9007199254740992(2^53) is sent as is. Forlist_commits, GitHub answers HTTP 500 and the tool returnsfailed to list commits: : GET …/commits?page=9007199254740992&per_page=1: 500 [], with an empty message.page: 2147483647is accepted by GitHub and returns[].
The relaxation is intentional, per the comment at pkg/github/git_gist_types.go:236-242 ("the SDK continues accepting legacy out-of-range values (e.g. page=-1, perPage=101) that the handler has always forwarded unmodified"). The result is that the advertised contract and the behaviour disagree, and very large values produce an opaque upstream 500.
Separately, -9223372036854775808 (-2^63) passes the integer range check, which is inclusive at the lower end (pkg/github/params.go:63-66; typed_read_normalizers.go:45 uses the same inSignedIntRange), and then, by code reading, fails in the typed decode with a raw encoding/json error that exposes internal type names and a fragment of the arguments:
json: cannot unmarshal number -9223372036854776000,"perPage":1... overflows into Go struct field github.ListCommitsInput.page of type int (also github.IssueReadInput.issue_number via issue_read).
Related: #3647 / PR #3649 (list_label turns perPage: 0 into 100 despite minimum: 1), the same class in a different tool. #3489 / PR #3650 fixed the upper bound (2^63) only.
Code (main 99d6d65, unchanged since v2.1.0): relaxedPaginationValidationSchema at pkg/github/git_gist_types.go:243-253, used at repositories.go:75 (get_commit), repositories.go:248 (list_commits), gists.go:49 (list_gists). actionsValidationSchema at actions_types.go:114 (actions_list). Range check at params.go:63-66.
perPage out-of-range values were not tested; the relaxation also clears the perPage min/max per the code.
Affected version
v2.1.0 (image sha256:f6056fc1…0f8a, commit 4bcdcdf) and main nightly (image sha256:48bc16d0…338f, revision 99d6d65). --read-only --toolsets=all, read-only fine-grained PAT.
Steps to reproduce the behavior
The forwarded value is visible in the request URL of the error result:
{"name":"list_commits","arguments":{"owner":"OWNER","repo":"REPO","sha":"no-such-ref","page":-1,"perPage":1}}Result: GET …/commits?page=-1&per_page=1&sha=no-such-ref: 404.
{"name":"list_gists","arguments":{"username":"no-such-user-zz9","page":-1,"perPage":1}}Result: GET …/users/no-such-user-zz9/gists?page=-1&per_page=1: 404.
{"name":"actions_list","arguments":{"owner":"OWNER","repo":"REPO","method":"list_workflows","page":9007199254740992,"perPage":1}}Result: GET …/actions/workflows?page=9007199254740992&per_page=1 (403 here because the PAT has no Actions scope, but the page value is visible).
{"name":"list_commits","arguments":{"owner":"OWNER","repo":"REPO","page":9007199254740992,"perPage":1}}Result: failed to list commits: : GET …/commits?page=9007199254740992&per_page=1: 500 [].
{"name":"list_commits","arguments":{"owner":"OWNER","repo":"REPO","page":-9223372036854775808,"perPage":1}}Result: the raw decode error quoted above.
get_commit with page: -1 and page: 2^53 returns success with no validation error. Its error messages don't show the URL; by code it forwards page to ListOptions the same way.
Expected vs actual behavior
Expected: values outside the advertised range are clamped or rejected with a message that names the parameter. An out-of-range integer gets the same "value out of range" message as at the upper end.
Actual: the values are forwarded unmodified (opaque 500 at 2^53), and -2^63 leaks a Go decode error.
Suggested fix: if accepting legacy values must stay, normalise in the handler: page < 1 → 1, and reject page above a sane cap (for example, 2^31-1) with a clear error. Alternatively, stop advertising bounds that aren't enforced. Make the lower bound in inSignedIntRange exclusive (f > -limit), matching the upper bound, so -2^63 gets the existing range error.
Logs
list_commits page=-1 (bad ref) -> …/commits?page=-1&per_page=1&sha=no-such-ref: 404 Not Found []
list_gists page=-1 (bad user) -> …/users/no-such-user-zz9/gists?page=-1&per_page=1: 404 Not Found []
actions_list page=2^53 -> …/actions/workflows?page=9007199254740992&per_page=1: 403 …
list_commits page=2^53 -> failed to list commits: : GET …/commits?page=9007199254740992&per_page=1: 500 []
list_commits page=2147483647 -> OK []
list_commits page=-2^63 -> json: cannot unmarshal number -9223372036854776000,"perPage":1... overflows into Go struct field github.ListCommitsInput.page of type int
tools/list list_commits page: {"type":"number","minimum":1}
Same on v2.1.0 and main.
Found during an independent audit of v2.1.0 on a throwaway org and private test repo. Prepared with AI assistance (Claude Code); reproduced by two independent test runs before filing.
Activity