Send OAuth token request params in POST body instead of URL#7372
Send OAuth token request params in POST body instead of URL#7372isaacroldan merged 1 commit intomainfrom
Conversation
The cli-kit `tokenRequest()` helper was placing all OAuth parameters (`subject_token`, `refresh_token`, `device_code`, `client_id`, etc.) into the URL query string of POST requests to `/oauth/token`. RFC 6749 specifies that these parameters are sent in the request body as `application/x-www-form-urlencoded` data, and putting credentials in URLs causes them to leak into verbose CLI debug output, HTTP access logs, proxies, and anywhere else URLs are recorded. This commit: - Moves the OAuth parameters from the URL query string into the POST request body (form-encoded). - Expands `sanitizeURL` to mask all sensitive OAuth parameter names (`access_token`, `refresh_token`, `id_token`, `subject_token`, `actor_token`, `device_code`, `client_secret`, `code`) so that any URL that ever carries one of these values in the future is still redacted as defence in depth. - Updates tests to assert the new behaviour and adds coverage for every sanitized parameter. Reported through Shopify's bug bounty programme (report #3686978). Requested by Josh Bregar <josh.bregar@shopify.com> Co-authored-by: Josh Bregar <josh.bregar@shopify.com>
089dcf7 to
92b092a
Compare
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20260422144132Caution After installing, validate the version by running |
There was a problem hiding this comment.
Pull request overview
Updates the cli-kit OAuth token exchange flow to avoid leaking credentials by moving OAuth parameters from the URL query string into a form-encoded POST body, and expands URL sanitization to redact a broader set of sensitive OAuth-related query parameters.
Changes:
- Send OAuth token request parameters as
application/x-www-form-urlencodedPOST body data instead of URL query params. - Expand
sanitizeURLto redact additional sensitive OAuth parameter names. - Update/add tests to assert body-based parameter sending and to cover sanitization for each sensitive parameter.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/cli-kit/src/private/node/session/exchange.ts | Moves /oauth/token parameters into POST body with form encoding and explicit content type. |
| packages/cli-kit/src/private/node/session/exchange.test.ts | Updates token-exchange tests to assert no query params and validate form body + headers. |
| packages/cli-kit/src/private/node/api/urls.ts | Reworks sanitizeURL to redact a list of sensitive OAuth query parameters. |
| packages/cli-kit/src/private/node/api/urls.test.ts | Adds parameterized tests to ensure every sensitive query param is sanitized. |
Comments suppressed due to low confidence (1)
packages/cli-kit/src/private/node/api/urls.ts:20
- The JSDoc for
sanitizeURLhas an incorrect@paramdescription (HTTP headers). This function accepts a URL string; updating the doc helps avoid confusion for callers and keeps generated docs accurate.
/**
* Removes the sensitive data from the url and outputs them as a string.
* @param url - HTTP headers.
* @returns A sanitized version of the url as a string.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The cli-kit
tokenRequest()helper was placing all OAuth parameters (subject_token,refresh_token,device_code,client_id, etc.) into the URL query string of POST requests to/oauth/token.RFC 6749 specifies that these parameters are sent in the request body as
application/x-www-form-urlencodeddata, and putting credentials in URLs causes them to leak into verbose CLI debug output, HTTP access logs, proxies, and anywhere else URLs are recorded.This commit:
sanitizeURLto mask all sensitive OAuth parameter names (access_token,refresh_token,id_token,subject_token,actor_token,device_code,client_secret,code) so that any URL that ever carries one of these values in the future is still redacted as defence in depth.WHY are these changes introduced?
Fixes #0000
WHAT is this pull request doing?
How to test your changes?
Using the snapshot:
shopify auth logoutthenshopify auth loginPost-release steps
Checklist
patchfor bug fixes ·minorfor new features ·majorfor breaking changes) and added a changeset withpnpm changeset add