Dashboard › cli › Distillation
199cdfe6-7e97-494b-ac56-af240f12c4e4["lore_tm_v1_U2xFWKZ8yF2wKkkGoD1aCriCOx_N3F9epBRCLNtcaZ4","lore_tm_v1_TARF1o_c8zXj9SZy32sd452oeWN9F8Oz-bKm8UmJzn8","lore_tm_v1_mz9YJCZE6lPccTre033IYVukFuQd24Yh8n_pOwOgnfg","lore_tm_v1_u3Z86UZgOi1Llo26o0EVXieatN6m8x3Jr2cpdLqke-I","lore_tm_v1_93EJZCLbqBBvtRffHW9QH1w0a0Kp_SAOQkaIrfSgsFg","lore_tm_v1_h33LZkuaKinoSob3e5pV9lzj4mDXFwgoVHry0k3o9Rg","lore_tm_v1_IV7tt399Tp4juJQ4lC8_KMkOq_QdgIaHJqarqeWJmAo","lore_tm_v1_t3QtmK3taJUeC2BTDQPNRnSTHm_Wq6dk0hSWlo6vB_k","lore_tm_v1_oq423aucSV-rs7t7lniaNPIBjOiZjiKIxiVt0IHx71U","lore_tm_v1_KtfcChL0i3k10jJBk17Gy7V5CIx7LpA0pXaOvWFDAl0","lore_tm_v1_TrkJiqpABeWu3iagWph3lXAFT4D5B1XmQk_i3xcHkYA","lore_tm_v1_qSVHsXlNhZfzmJWsjHzL1r8gqQYmsJDOKQD5VIPisRk"]
Date: Sep 10, 2026
packages/cli/test/lib/sentry-client.test.ts trusted-307 redirect coverage at lines 119–164; packages/cli/test/lib/security/sntrys-claim-mismatch.test.ts cross-origin custom-header redirect refusal at lines 261–286; and packages/cli/test/lib/security/refresh-token-poison.test.ts refresh-token exfiltration regressions at lines 1–95.packages/cli/test/lib/sentry-client.test.ts test "follows a trusted 307 redirect without consuming a Request body" sends a POST Request with payload {"redirect":"preserve-body"} from https://us.sentry.io/api/0/__test_redirect_request_body__/ to same-origin destination https://us.sentry.io/api/0/__test_redirect_request_body__/redirected/; it expects both requests to retain the body and Authorization: Bearer test-token.packages/cli/test/lib/sentry-client.test.ts also covers: retrying a string POST body after a 503; retrying a Request POST body after a 502; retrying a ReadableStream body materialized once after a 500 with duplex: "half"; and retrying FormData without losing its auto-negotiated Content-Type: multipart/form-data; boundary=... header..lore.md; packages/cli/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md, event.md, explore.md, feedback.md, issue.md, log.md, replay.md, span.md, and trace.md; packages/cli/src/lib/constants.ts, packages/cli/src/lib/region.ts, and packages/cli/src/lib/sentry-client.ts; and packages/cli/test/lib/constants.test.ts, packages/cli/test/lib/security/sntrys-claim-mismatch.test.ts, and packages/cli/test/lib/sentry-client.test.ts.packages/cli/src/lib/sentry-client.ts diff introduces MAX_REDIRECTS = 20 (“Matches native fetch”), FetchWithTimeoutResult containing response: Response and headers: Headers, redirect recognition for statuses 301, 302, 303, 307, and 308, plus getRedirectUrl(response, request) which throws ApiError when Location is missing.packages/cli/src/lib/sentry-client.ts redirect flow clones an existing Request or obtains one via getInitialRedirectRequest(input, init), and includes a security check documented as “Never forward headers across an unvalidated origin.”packages/cli/test/lib/oauth.test.ts verifies resolveOAuthScopeString: no selection returns OAUTH_SCOPES.join(" "); { readOnly: true } returns only :read scopes in OAUTH_SCOPES order; explicit scopes override readOnly; explicit scopes lowercase and preserve first-seen order; duplicates are removed; blank entries are skipped; unknown scope throws ValidationError with field "scope"; and empty resolved scopes throw ValidationError.readOnly OAuth scope selection never includes write or admin scopes.packages/cli/test/lib/oauth.test.ts use fast-check constantFrom(...SENTRY_SCOPES), uniqueArray, and DEFAULT_NUM_RUNS; every nonempty unique SENTRY_SCOPES subset must round-trip to its lowercased, space-joined form, and every individual known scope must be accepted.registerTrustedRegionUrls(urls) in packages/cli/src/lib/db/regions.ts line 64; setOrgRegion(orgSlug, regionUrl) at line 182 registers its region URL; setOrgRegions(entries) at line 204 registers entries.map((e) => e.regionUrl); and callers in packages/cli/src/lib/api/organizations.ts, packages/cli/src/lib/api/projects.ts, and packages/cli/src/lib/region.ts.packages/cli/test/lib/security/refresh-token-poison.test.ts documents the CVE defense: poisoning env.SENTRY_URL after boot previously could POST a refresh token to an attacker’s /oauth/token/; refreshAccessToken now calls assertRefreshHostTrusted() before building the request body and throws CliError on host mismatch.captureEnvTokenHost() snapshots the default SaaS host, setting process.env.SENTRY_URL = "https://evil.com" causes await refreshAccessToken("fake-refresh-token") to throw before any fetch; expected fetchCalls is [], and the error matches /does not match|sentry auth login --url/.SENTRY_HOST and SENTRY_URL to https://sentry.example.com, then capturing the environment-token host, permits refreshAccessToken("fake-refresh-token") through host validation; the mocked fetch is attempted exactly once at https://sentry.example.com/oauth/token/.