Skip to content

Refuse a request that names more branch patterns than MaxBranchPatternsPerRequest [patch] - #117

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/116-cap-branch-patterns
Nov 4, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/116-cap-branch-patterns

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #116

What changes

BranchStateHandler.TryParsePatterns capped each pattern's length but not how many patterns a request could send. Every pattern is matched against every mirror branch synchronously, so one POST /state with tens of thousands of patterns could hold a request thread for minutes.

  • New GitBranchStateCacheOptions.MaxBranchPatternsPerRequest, default 256. GitBranchStateCacheOptionsValidator refuses a value of zero or less.
  • TryParsePatterns takes the limit and returns a 400 when the request goes over it. The check runs before the mirror is cloned or fetched, and it covers both POST /state and GET /branches?pattern=.
  • The README configuration block and GitBranchStateCache.Tool/appsettings.json list the new setting next to MaxPathsPerRequest. The README also says in a sentence that both limits are refused before anything is fetched.

I left out passing the CancellationToken into RefResolver.Match. The issue marks that as optional, and the cap alone bounds the work.

Tests

  • StateFlowTests.Post_State_MoreBranchPatternsThanTheLimit_Is400BeforeAnyFetch: with the limit set to 3, sending 4 patterns returns 400 with "at most 3" in the message, and git never runs clone or fetch.
  • StateFlowTests.Post_State_BranchPatternsAtTheLimit_AreAccepted: a request with exactly the limit still returns 200.
  • StateFlowTests.Get_Branches_MoreBranchPatternsThanTheLimit_Is400: the same check on /branches.
  • GitBranchStateCacheOptionsValidatorTests.Validate_NonPositiveMaxBranchPatternsPerRequest_Fails for 0 and -1.

With the handler check disabled, both over-limit tests fail. With it in place, the full GitBranchStateCache.Tests suite passes (290/290, net10.0).


Generated by Claude Code

…nsPerRequest [patch]

POST /state and GET /branches capped each pattern's length but not how
many patterns one request could send. Every pattern is matched against
every mirror branch synchronously, so one request with tens of thousands
of patterns could hold a thread for minutes.

Add MaxBranchPatternsPerRequest (default 256, validated > 0) and refuse a
request over it with a 400 in TryParsePatterns, before any clone or fetch.

Fixes #116

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT
@sonarqubecloud

sonarqubecloud Bot commented Nov 3, 2026

Copy link
Copy Markdown

matt-edmondson pushed a commit that referenced this pull request Nov 3, 2026
Keeps it clear of the lines #117 adds, so the two PRs merge in either order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT
@matt-edmondson
matt-edmondson merged commit 5f532e1 into main Nov 4, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/116-cap-branch-patterns branch November 4, 2026 01:01
matt-edmondson added a commit that referenced this pull request Nov 4, 2026
…sting [patch] (#118)

* Skip a branch whose name is not UTF-8 instead of failing every ref listing [patch]

RefResolver.ListAsync read for-each-ref output through GitRunner's strict
UTF-8 decoding, so one ref name git allows but UTF-8 cannot read failed
the whole listing, and every /state and /branches request for that
repository returned 502 refs-unreadable until the branch was deleted.

GitInvocation.ReadStandardOutputAsBytes now returns stdout one character
per byte. RefResolver decodes each line on its own, skips a line that is
not UTF-8, and logs a warning with the hex of the ref name. Every other
branch is still served.

Fixes #114

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT

* Move the #114 end-to-end test to the end of StateFlowTests

Keeps it clear of the lines #117 adds, so the two PRs merge in either order.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW24ManL6mVAsf34qvT

---------

Co-authored-by: Claude <noreply@anthropic.com>
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.

POST /state accepts an unlimited number of branchPatterns, so one request can pin a CPU for minutes and keeps running after the client disconnects

2 participants