Repository navigation
Tighten TypeSafe key host checks and disable SDK redirects - #17
Merged
Merged
Conversation
Require port 443, reject trailing-dot hosts and non-numeric ports, and pass the SDK an httpx2 client with follow_redirects=False. Tools script only; not a package release. Co-authored-by: Jason <jkbennitt@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the merged key allowlist. The TypeSafe API key still only goes to
api.typesafe.aiover HTTPS, and now only on port 443 with an exact host match. The SDK path is given anhttpx2client with redirects disabled.This is not a major production PR. It changes
tools/typesafe-pareto/only. No PackageId, version, CHANGELOG, or NuGet release.1. Port must be omitted or 443
_typesafe_key_hostrequiresparsed.port in (None, 443). Non-numeric ports such as:foomakeurlsplit(...).portraiseValueError(the same propertyurlparseuses). That error is caught and returned asTypeSafeConfigError, before a request is built.Checked:
test_explicit_port_443_ok_other_ports_and_trailing_dot_rejectedacceptshttps://api.typesafe.ai:443and rejects:8443and:foofromresolve_base_urland from_http_system_onewithout constructingRequestor an opener.test_redirect_to_non_443_port_is_refusedscripts a 302 tohttps://api.typesafe.ai:8443/...and recordsAuthorizationonly on the originalhttps://api.typesafe.ai/v1/systemonerequest.2. Trailing-dot hosts are rejected
The host comparison no longer calls
rstrip(".").parsed.hostnamekeeps the trailing dot, soapi.typesafe.ai.is not an exact allowlist match.Checked: the same unit test rejects
https://api.typesafe.ai.andhttps://API.typesafe.ai.withTypeSafeConfigErrorand does not open a request.3. SDK redirect behavior
Read
typesafe-sdk0.7.5 (typesafe_sdk/_core/client/sync/client.py,typesafe_sdk/_core/transport.py) andhttpx22.16.0 (httpx2/_client.py), then installed those versions and constructed a client locally. No request was sent.TypeSafeClientbuildshttpx2.Client(timeout=..., limits=DEFAULT_LIMITS)when the caller does not passhttp_client. It does not setfollow_redirects.send()callshttp_client.request(...)without that argument, so the client default applies.httpx2.Clientdefaultsfollow_redirectstoFalse. In that mode_send_handling_redirectsstoresnext_requestand returns the 3xx. The next request is not sent, soAuthorizationdoes not reach a second host._redirect_headersdropsAuthorizationwhen the origin changes, except_is_https_redirect(onlyhttpport 80 tohttpsport 443 on the same host). A same-host scheme downgrade or a different port would keep the header.The SDK exposes
http_client, so_sdk_system_onenow passeshttpx2.Client(follow_redirects=False, timeout=timeout)and does not rely on the default.TypeSafeClientcloses that client;close()is idempotent, and thefinallyblock closes it again if construction fails first.Checked: local constructor confirmed
client._http_client.follow_redirects is Falseand that it is the same object passed in.test_sdk_path_disables_redirectsmocks the seam (CI does not install the SDK) and assertsfollow_redirects=Falseis what gets passed. The pinned client uses httpx2's default connection limits rather than the SDK'sDEFAULT_LIMITS(100).system_one, retries, and the SDK's ownAuthorizationheader are unchanged.4. Tests
httpstohttponapi.typesafe.ai) was already covered bytest_https_downgrade_redirect_is_refusedand still passes. The scripted 302 raises, and the bearer token is recorded only on the original HTTPS URL.socket.create_connection/socket.getaddrinfo.Full suite:
python3 -m unittest tools/typesafe-pareto/test_score_pareto.py -v(25 tests) andpython3 tools/typesafe-pareto/score_pareto.py --smoke --force-mock --no-metrics.What stayed unchanged
Mock scoring, question shapes, metrics JSONL, and
--force-mockfor an allowlisted base URL. The urllib allowlist redirect handler still follows same-host HTTPS redirects on port 443. The SDK still callsTypeSafeClient.system_oneafter the shared host check.Checklist
dotnet test Unsga3.slnx -c Release— not run; library code is unchangedTest plan
python3 -m unittest tools/typesafe-pareto/test_score_pareto.py -vpython3 tools/typesafe-pareto/score_pareto.py --smoke --force-mock --no-metricstypesafe-sdk0.7.5 /httpx22.16.0 constructor check, no request