From 8a60eae387c454f00e03e915b0a62c0dd0c621bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 01:09:11 +0000 Subject: [PATCH 1/3] fix: bump the go-minor-and-patch group across 1 directory with 2 updates Bumps the go-minor-and-patch group with 2 updates in the / directory: [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) and [golang.org/x/net](https://github.com/golang/net). Updates `github.com/quic-go/quic-go` from 0.61.0 to 0.63.0 - [Release notes](https://github.com/quic-go/quic-go/releases) - [Commits](https://github.com/quic-go/quic-go/compare/v0.61.0...v0.63.0) Updates `golang.org/x/net` from 0.58.0 to 0.59.0 - [Commits](https://github.com/golang/net/compare/v0.58.0...v0.59.0) --- updated-dependencies: - dependency-name: github.com/quic-go/quic-go dependency-version: 0.62.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-and-patch - dependency-name: golang.org/x/net dependency-version: 0.59.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-minor-and-patch ... Signed-off-by: dependabot[bot] --- go.mod | 13 ++++++------- go.sum | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index ce497fe..5faffc8 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,19 @@ module github.com/cppla/autocar -go 1.25.13 +go 1.26.0 require ( github.com/apernet/quic-go v0.61.1-0.20260806010916-184d081eef3e - github.com/quic-go/quic-go v0.61.0 + github.com/quic-go/quic-go v0.63.0 github.com/refraction-networking/utls v1.8.2 - golang.org/x/net v0.58.0 + golang.org/x/net v0.59.0 ) require ( github.com/andybalholm/brotli v1.0.6 // indirect github.com/klauspost/compress v1.17.4 // indirect github.com/quic-go/qpack v0.6.0 // indirect - github.com/stretchr/testify v1.12.1 // indirect - golang.org/x/crypto v0.55.0 // indirect - golang.org/x/sys v0.47.0 // indirect - golang.org/x/text v0.41.0 // indirect + golang.org/x/crypto v0.57.0 // indirect + golang.org/x/sys v0.48.0 // indirect + golang.org/x/text v0.42.0 // indirect ) diff --git a/go.sum b/go.sum index cefc4c5..d1d9c2d 100644 --- a/go.sum +++ b/go.sum @@ -8,8 +8,8 @@ github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4 github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk= github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.61.0 h1:ui88A53s8MSVYLC56en0KQ17HARk+9986Dn0SBfKNvA= -github.com/quic-go/quic-go v0.61.0/go.mod h1:9So2anK4Tp22URSQq00k+Vo2PNkle96ycDPDHL4s9vs= +github.com/quic-go/quic-go v0.63.0 h1:LIFGHI4PFUhhw2dDD1ARHdCff143ffMHwZtbnbuJ78A= +github.com/quic-go/quic-go v0.63.0/go.mod h1:RAro2j2yN9a9EiPACLHT9IB2NXCvGQmmo/alT0yYI0w= github.com/refraction-networking/utls v1.8.2 h1:j4Q1gJj0xngdeH+Ox/qND11aEfhpgoEvV+S9iJ2IdQo= github.com/refraction-networking/utls v1.8.2/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM= github.com/stretchr/testify v1.12.1 h1:EuwCh5fleGS7H32xRwO3wRGT7DxrDhLAT6FF8MpWDWE= @@ -18,11 +18,11 @@ go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= -golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= -golang.org/x/net v0.58.0/go.mod h1:YwCddHnFlT7eLQqVprV19OnhLGtc5xOKgE0RyqgfWAU= -golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= -golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= -golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/crypto v0.57.0 h1:3ZVCjf8Ggz7zneR/EHRVx68Ctf+2pmIMP2UFhh9cC6M= +golang.org/x/crypto v0.57.0/go.mod h1:Fdz0i5U6CoizGwLda9DttjSk6qlZo25zYNtR+ycvuZA= +golang.org/x/net v0.59.0 h1:5zfYln+w5XCxwrnMMJPufRgNoXEaGxl0wo5GqPXyues= +golang.org/x/net v0.59.0/go.mod h1:2DA/G1UfVbCpQPeWTmMPGY7Cs2PkBkwu743bVX5PIVg= +golang.org/x/sys v0.48.0 h1:bbX/i/6MgT9BVLM9RT1thmxL04yeTAhbEz4SyadbXoo= +golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= +golang.org/x/text v0.42.0 h1:JbOZXgfeCPU9gacVtYliJqOhD+zhrEqK4LfdpmlUZqI= +golang.org/x/text v0.42.0/go.mod h1:ojzP1Z+2QtioaF8DTtO8K5q7JWVVYwZKenzujK0Zd0E= From 0253bea758f290033381f5f59b4ab70c3abe8834 Mon Sep 17 00:00:00 2001 From: cppla Date: Thu, 8 Oct 2026 14:47:57 +0800 Subject: [PATCH 2/3] build: align dependency upgrade with Go 1.26.8 --- .github/workflows/ci.yml | 12 ++++++------ README.md | 2 +- THIRD_PARTY_NOTICES.md | 10 +++++----- go.mod | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 416b5aa..f0490cb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - go: ['1.25.13', '1.27.x'] + go: ['1.26.8', '1.27.x'] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 @@ -60,26 +60,26 @@ jobs: if-no-files-found: error macos-test: - name: macOS test (Go 1.25.13) + name: macOS test (Go 1.26.8) runs-on: macos-14 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.25.13 + go-version: 1.26.8 cache: true - name: Test run: go test -shuffle=on -count=1 ./... windows-udp-test: - name: Windows UDP continuity (Go 1.25.13) + name: Windows UDP continuity (Go 1.26.8) runs-on: windows-2022 timeout-minutes: 10 steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.25.13 + go-version: 1.26.8 cache: true - name: Exercise native UDP continuity and platform bind errors shell: pwsh @@ -134,7 +134,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.25.13 + go-version: 1.26.8 cache: true - name: Run govulncheck run: ./scripts/govulncheck.sh diff --git a/README.md b/README.md index d032da6..570a088 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Web cover 的目标是正常网站兼容、减少主动探测暴露并在 UDP ## 快速开始 -客户端和服务端分别在各自机器上构建,需要 Go 1.25.13 或更高版本: +客户端和服务端分别在各自机器上构建,需要 Go 1.26.8 或更高版本: ```bash git clone https://github.com/cppla/autocar.git diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index d2e0c9a..56f912c 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -393,7 +393,7 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` -## `github.com/quic-go/quic-go` `v0.61.0` +## `github.com/quic-go/quic-go` `v0.63.0` ### `LICENSE` @@ -459,7 +459,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ``` -## `golang.org/x/crypto` `v0.55.0` +## `golang.org/x/crypto` `v0.57.0` ### `LICENSE` @@ -523,7 +523,7 @@ rights granted to you under this License for this implementation of Go shall terminate as of the date such litigation is filed. ``` -## `golang.org/x/net` `v0.58.0` +## `golang.org/x/net` `v0.59.0` ### `LICENSE` @@ -587,7 +587,7 @@ rights granted to you under this License for this implementation of Go shall terminate as of the date such litigation is filed. ``` -## `golang.org/x/sys` `v0.47.0` +## `golang.org/x/sys` `v0.48.0` ### `LICENSE` @@ -651,7 +651,7 @@ rights granted to you under this License for this implementation of Go shall terminate as of the date such litigation is filed. ``` -## `golang.org/x/text` `v0.41.0` +## `golang.org/x/text` `v0.42.0` ### `LICENSE` diff --git a/go.mod b/go.mod index 5faffc8..5ef27ee 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/cppla/autocar -go 1.26.0 +go 1.26.8 require ( github.com/apernet/quic-go v0.61.1-0.20260806010916-184d081eef3e From 1d70baa4a4c9673d4ec564208fb94c0b26eddb9b Mon Sep 17 00:00:00 2001 From: cppla Date: Thu, 8 Oct 2026 15:02:29 +0800 Subject: [PATCH 3/3] test: respect reverse proxy request body ownership --- docs/ACCELERATION.md | 2 +- docs/ARCHITECTURE.md | 2 +- docs/STEALTH-PILOT.md | 2 +- internal/cover/request_trailer_test.go | 47 ++++++++++++++++++++++---- scripts/stealth-pilot-config.py | 6 ++-- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/docs/ACCELERATION.md b/docs/ACCELERATION.md index 663ed27..97b07db 100644 --- a/docs/ACCELERATION.md +++ b/docs/ACCELERATION.md @@ -153,7 +153,7 @@ delay test matters at least as much as bulk throughput. ## `reno` `reno` bypasses AutoCAR's application-layer admission. It does not implement -Reno itself; the native pinned upstream quic-go v0.61.0 transport selects Reno +Reno itself; the native pinned upstream quic-go v0.63.0 transport selects Reno for its default sender. This mode therefore measures that actual upstream baseline and is useful for A/B tests or for operators who do not want an additional application pacing diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 95caaf3..6a69393 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -35,7 +35,7 @@ flowchart LR | `internal/security` | TLS policy, secrets, remote resolution and SSRF/port/CIDR enforcement | | `internal/transport` | Small TCP and packet interfaces shared by frontends | -The native transport uses upstream `github.com/quic-go/quic-go` v0.61.0. Web H3 +The native transport uses upstream `github.com/quic-go/quic-go` v0.63.0. Web H3 uses the `github.com/apernet/quic-go` fork, pinned exactly to `v0.61.1-0.20260806010916-184d081eef3e`, because its client-only ChromeParrot profile controls the TLS ClientHello, QUIC transport parameters, connection IDs diff --git a/docs/STEALTH-PILOT.md b/docs/STEALTH-PILOT.md index 05010c6..7648b51 100644 --- a/docs/STEALTH-PILOT.md +++ b/docs/STEALTH-PILOT.md @@ -7,7 +7,7 @@ collection before paying the cost of the preregistered corpus. The result is always **calibration / `insufficient_evidence`**. Two captures per product and cell cannot establish that AutoCAR is less distinguishable than -the baseline. The control uses upstream quic-go v0.61.0 and is deliberately +the baseline. The control uses upstream quic-go v0.63.0 and is deliberately recorded as **not a real browser**. A later claim-bearing campaign still needs the preregistered browser diversity, sample count, held-out evaluation, and statistical gates in `docs/STEALTH-BENCHMARK.md`. diff --git a/internal/cover/request_trailer_test.go b/internal/cover/request_trailer_test.go index 5ef862d..ad31a1a 100644 --- a/internal/cover/request_trailer_test.go +++ b/internal/cover/request_trailer_test.go @@ -512,12 +512,31 @@ func requestTrailerHTTPSExchange(t *testing.T, constructor string, protocol int) } ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() + outboundClosed := make(chan struct{}) + var outboundCloseOnce sync.Once + var outboundCloses atomic.Int64 + observedTransport := roundTripFunc(func(request *http.Request) (*http.Response, error) { + // Observe the body handed to the real transport. A shallow copy keeps + // the trailer bridge's destination map; Request.Clone would detach it. + out := *request + body := out.Body + out.Body = &requestTrailerUnitBody{ + read: body.Read, + close: func() error { + err := body.Close() + outboundCloses.Add(1) + outboundCloseOnce.Do(func() { close(outboundClosed) }) + return err + }, + } + return transport.RoundTrip(&out) + }) var handler http.Handler if constructor == "public_origin" { public, _ := url.Parse("https://public.example") - handler, err = NewReverseProxyHandlerWithPublicOrigin(origin, public, transport) + handler, err = NewReverseProxyHandlerWithPublicOrigin(origin, public, observedTransport) } else { - handler, err = NewReverseProxyHandler(origin, transport) + handler, err = NewReverseProxyHandler(origin, observedTransport) } if err != nil { t.Fatal(err) @@ -539,7 +558,7 @@ func requestTrailerHTTPSExchange(t *testing.T, constructor string, protocol int) reader := strings.NewReader(payload) sourceEOF := make(chan struct{}) var eofOnce sync.Once - var bodyCloses atomic.Int64 + var inboundCloses atomic.Int64 request.Body = &requestTrailerUnitBody{ read: func(p []byte) (int, error) { n, err := reader.Read(p) @@ -556,10 +575,26 @@ func requestTrailerHTTPSExchange(t *testing.T, constructor string, protocol int) } return n, err }, - close: func() error { bodyCloses.Add(1); return nil }, + close: func() error { inboundCloses.Add(1); return nil }, } + // This direct ServeHTTP fixture owns inbound cleanup, as an HTTP server + // would. ReverseProxy may shield that body from outbound Close calls. + var inboundCloseOnce sync.Once + closeInbound := func() { + inboundCloseOnce.Do(func() { + if err := request.Body.Close(); err != nil { + t.Errorf("owned inbound body close: %v", err) + } + }) + } + t.Cleanup(closeInbound) recorder := httptest.NewRecorder() handler.ServeHTTP(recorder, request) + // RoundTrip may close its request body asynchronously after returning. + if !requestTrailerWait(t, outboundClosed, "owned outbound transport body close") { + return + } + closeInbound() var got observation select { case got = <-observed: @@ -592,8 +627,8 @@ func requestTrailerHTTPSExchange(t *testing.T, constructor string, protocol int) } else if got.trailer.Get("Forwarded") != "host=fictional.example" { t.Error("the opt-in trailer forwarding policy affected the default constructor") } - if requests.Load() != 1 || unexpected.Load() != 0 || verified.Load() != 1 || badDials.Load() != 0 || bodyCloses.Load() == 0 { - t.Errorf("owned lifecycle controls: requests=%d unexpected=%d verified=%d badDials=%d bodyCloses=%d", requests.Load(), unexpected.Load(), verified.Load(), badDials.Load(), bodyCloses.Load()) + if requests.Load() != 1 || unexpected.Load() != 0 || verified.Load() != 1 || badDials.Load() != 0 || outboundCloses.Load() == 0 || inboundCloses.Load() == 0 { + t.Errorf("owned lifecycle controls: requests=%d unexpected=%d verified=%d badDials=%d outboundCloses=%d inboundCloses=%d", requests.Load(), unexpected.Load(), verified.Load(), badDials.Load(), outboundCloses.Load(), inboundCloses.Load()) } if !reflect.DeepEqual(request.Header, beforeHeader) || !reflect.DeepEqual(initial, beforeInitial) || request.ContentLength != int64(len(payload)) || request.Trailer.Get("Authorization") != "fictional-trailer" || request.Trailer.Get("X-Hop") != "fictional-hop" { diff --git a/scripts/stealth-pilot-config.py b/scripts/stealth-pilot-config.py index 46a5229..5134b10 100755 --- a/scripts/stealth-pilot-config.py +++ b/scripts/stealth-pilot-config.py @@ -172,9 +172,9 @@ def prepare(args: argparse.Namespace) -> None: "products": { "cover": {"variants": [{ "name": "quic-go-standard-h3-control", - "client_implementation": "quic-go v0.61.0 standard H3 control (not a browser)", - "server_implementation": "quic-go v0.61.0 HTTP/3 fixture", - "implementation_version": "v0.61.0-calibration-control", + "client_implementation": "quic-go v0.63.0 standard H3 control (not a browser)", + "server_implementation": "quic-go v0.63.0 HTTP/3 fixture", + "implementation_version": "v0.63.0-calibration-control", "real_browser": False, "runner_image": args.runner_image, "server_container": args.control_container,