Skip to content

Pin the TypeSafe Pareto API key to allowlisted hosts - #16

Merged
jkbennitt merged 1 commit into
mainfrom
cursor/typesafe-key-allowlist-cd5d
Nov 1, 2026
Merged

jkbennitt merged 1 commit into
mainfrom
cursor/typesafe-key-allowlist-cd5d

Conversation

@jkbennitt

Copy link
Copy Markdown
Member

Summary

urllib.request keeps Authorization on cross-host redirects, and --base-url / TYPESAFE_BASE_URL could aim the TypeSafe API key at any host. The key is now pinned to api.typesafe.ai: other base URLs are rejected before a request, and redirects whose host is off that allowlist are refused before a second request is opened.

This is not a major production PR. It changes the tools/typesafe-pareto script and its unit tests only. No PackageId, version, CHANGELOG, or NuGet release.

What broke in live use

_http_system_one sent Authorization: Bearer <TYPESAFE_API_KEY> through urllib.request.urlopen. On Python 3.12, HTTPRedirectHandler.redirect_request copies those request headers onto the redirected request, including when Location points at another host. resolve_base_url also returned --base-url (and run_pass(base_url=...)) or TYPESAFE_BASE_URL with no host check, so the same key could be pointed at an arbitrary origin. The default remains https://api.typesafe.ai.

How you checked

  • New unit tests in tools/typesafe-pareto/test_score_pareto.py (no sockets): the allowlisted default https://api.typesafe.ai is accepted and a scripted 200 receives Authorization only there; disallowed --base-url / TYPESAFE_BASE_URL values raise TypeSafeConfigError before Request, build_opener, or an injected post; a scripted cross-host 302 raises and the bearer token is recorded only for api.typesafe.ai.
  • Existing suite: python3 -m unittest tools/typesafe-pareto/test_score_pareto.py -v (22 tests) and python3 tools/typesafe-pareto/score_pareto.py --smoke --force-mock --no-metrics.

What stayed unchanged

  • Mock scoring, question shapes, metrics JSONL, and --force-mock when the base URL is allowlisted.
  • SDK calls still go through TypeSafeClient with the same arguments when typesafe-sdk is installed. A base URL whose host is off the allowlist is rejected before that client is constructed. SDK-internal redirect behavior is unchanged.
  • No NuGet package, public API, version, or CHANGELOG edits.

Checklist

  • dotnet test Unsga3.slnx -c Release — not run; library code is unchanged
  • CHANGELOG.md — intentionally unchanged (tools script only, not a package release)
  • Public API docs — no NuGet / XML doc change
  • Survival / normalization / metrics — unchanged; no oracle re-run

Test plan

  • python3 -m unittest tools/typesafe-pareto/test_score_pareto.py -v
  • python3 tools/typesafe-pareto/score_pareto.py --smoke --force-mock --no-metrics
  • python3 tools/typesafe-pareto/score_pareto.py --smoke --force-mock --no-metrics --base-url https://evil.example exits 2 and does not write metrics
Open in Web Open in Cursor 

urllib kept Authorization across cross-host redirects, and a base URL
override could aim the key at any host. Reject other hosts before a
request and refuse redirects that leave the allowlist.

Tools script only; not a package release.

Co-authored-by: Jason <jkbennitt@users.noreply.github.com>
@jkbennitt
jkbennitt merged commit a47e78f into main Nov 1, 2026
3 checks passed
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.

2 participants