
Go CLI that inventories HTTPS endpoints negotiating HTTP/2 via ALPN to identify systems requiring CVE-2023-44487 mitigation review. Non-exploitative, certificate-verified TLS checks with safe defaults.
rapid-reset-check is a small Go CLI for quickly inventorying HTTPS endpoints that expose HTTP/2 and therefore need a CVE-2023-44487 mitigation review.
The scanner is deliberately non-exploitative. It resolves each target, opens a certificate-verified TLS connection, offers h2 and http/1.1 through ALPN, records what the peer selects, and closes the connection. It sends no HTTP request, HTTP/2 connection preface, stream, RST_STREAM frame, or flood traffic.
[!IMPORTANT] Negotiating
h2is an exposure observation, not proof that a service is vulnerable or unpatched. A remote handshake cannot verify an HTTP/2 implementation's Rapid Reset limits, patch level, upstream origin, or DDoS controls.
CVE-2023-44487 is a denial-of-service technique that abuses rapid HTTP/2 stream creation and cancellation. Attempting to prove the condition against a live service would itself require potentially disruptive traffic. This tool instead answers the safe first question: which tested TLS endpoints currently negotiate HTTP/2 and therefore require an operator to verify mitigation?
HTTP/2 over TLS is advertised using the h2 ALPN identifier defined by RFC 9113. Google recommends verifying or patching every HTTP/2-capable server, proxy, and load balancer in the request path; see its CVE-2023-44487 guidance.
Go is not required to run the tool. Download the archive for your platform from the latest GitHub release:
| Platform | Release asset |
|---|---|
| Linux x86-64 | rapid-reset-check_<version>_linux_amd64.tar.gz |
| Linux ARM64 | rapid-reset-check_<version>_linux_arm64.tar.gz |
| macOS Intel | rapid-reset-check_<version>_darwin_amd64.tar.gz |
| macOS Apple silicon | rapid-reset-check_<version>_darwin_arm64.tar.gz |
| Windows x86-64 | rapid-reset-check_<version>_windows_amd64.zip |
| Windows ARM64 | rapid-reset-check_<version>_windows_arm64.zip |
Extract the archive, then run rapid-reset-check --version. On Windows, the executable is named rapid-reset-check.exe.
Each release includes SHA256SUMS. On Linux, verify a downloaded archive from the same directory with:
sha256sum --ignore-missing --check SHA256SUMS
On macOS, compare shasum -a 256 <archive> with the matching line in SHA256SUMS. Published public-release archives also receive a GitHub artifact attestation, which can be checked with the GitHub CLI:
gh attestation verify <archive> --repo ramonzx6/http-script-json
No Node.js, cURL, nghttp2, or WHOIS installation is required.
go test ./...
go build -o rapid-reset-check ./cmd/rapid-reset-check
Source builds report dev from --version; release builds receive their version from the release tag.
Only scan endpoints you own or are authorized to assess.
Scan one or more public endpoints:
./rapid-reset-check example.com api.example.com:8443
Bare hostnames are normalized to HTTPS on port 443. Authority-only HTTPS URLs are also accepted:
./rapid-reset-check https://example.com https://api.example.com:8443
Scan the repository's JSON target list:
./rapid-reset-check --input json/urls.json
Use standard input for automation:
printf '["example.com", "api.example.com"]' | ./rapid-reset-check --input -
Run ./rapid-reset-check --help for all limits and output options.
--input accepts the original JSON array format:
[
"example.com",
"api.example.com:8443",
"https://www.example.net"
]
The object forms {"urls": [...]} and {"targets": [...]} are also supported. Positional targets and --input are intentionally mutually exclusive. Duplicate normalized endpoints are scanned once, and each run is limited to 4,096 input targets.
Only HTTPS endpoints are in scope. Credentials, non-root paths, queries, fragments, unsupported schemes, malformed ports, and ambiguous hostnames are rejected instead of silently rewritten.
| Assessment | Meaning |
|---|---|
h2_observed_review_required | At least one verified TLS peer selected h2. Review every HTTP/2 component in that path; this is not a vulnerability verdict. |
h2_not_observed_on_tested_path | Every selected address completed a verified handshake without selecting h2. This is a point-in-time path observation, not a safety guarantee. |
indeterminate | A DNS, connection, timeout, TLS, certificate, or address-limit issue prevented a complete observation. |
not_scanned_policy | The resolved addresses were excluded by the scanner's network safety policy. |
invalid_target | The input was malformed or outside the supported HTTPS authority scope. |
The report includes each resolved address attempted, negotiated ALPN, TLS version and cipher, limited certificate identity/validity data, timing, policy decisions, omitted-address counts, an explicit completeness flag, and a summary. It does not collect response bodies, response headers, cookies, or raw certificates.
--ca-file to add a private CA; there is no insecure verification mode.--allow-private only for internal endpoints you are authorized to assess.Example options:
./rapid-reset-check \
--format json \
--timeout 5s \
--concurrency 4 \
--max-addresses 8 \
example.com > report.json
For an authorized private-PKI endpoint:
./rapid-reset-check \
--allow-private \
--ca-file ./internal-root-ca.pem \
service.internal:8443
Exit code 0 means every target produced a complete ALPN observation. Exit code 1 means at least one target was invalid, blocked by policy, or indeterminate; the report is still written. CLI usage and configuration errors return 2. Observing h2 does not by itself change the exit code because it is an inventory signal, not a vulnerability verdict.
For every h2_observed_review_required result:
Results are specific to the hostname, DNS answers, network path, TLS endpoint, and scan time. CDNs, anycast, split-horizon DNS, load balancing, alternate ports, and untested addresses can produce different results. The scanner does not:
h2c), QUIC/HTTP/3, redirects, origins hidden behind an edge, or non-HTTPS services;Server headers or CDN fingerprints;gofmt -w ./cmd ./internal
go vet ./...
go test ./...
go test -race ./...
go build ./...
The test suite uses local TLS fixtures and does not scan public services.
Release Please manages release versions and vX.Y.Z tags from Conventional Commit messages. Normal development does not require creating or pushing tags:
main cause Release Please to open or update a release PR containing the version and changelog changes.Use fix: for patch changes, feat: for minor changes, and a breaking-change marker (!) or BREAKING CHANGE: footer for major changes. Maintainers must enable Settings > Actions > General > Workflow permissions > Allow GitHub Actions to create and approve pull requests once for Release Please to manage its PR.
If asset publication fails after Release Please creates a tag, the release remains a draft. Re-run the Release workflow manually with that existing vX.Y.Z tag after fixing the failure. Do not create or push a replacement tag.