Skip to content

Commit

Permalink
Don't leak access token in error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
darthmaim committed Aug 19, 2024
1 parent ac2f4cf commit 88114b2
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/cold-maps-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@gw2api/fetch": patch
---

Don't leak access token in error messages
13 changes: 9 additions & 4 deletions packages/fetch/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,37 @@ export async function fetchGw2Api<
// check if the response is json (`application/json; charset=utf-8`)
const isJson = response.headers.get('content-type').startsWith('application/json');

// censor access token in url to not leak it in error messages
const erroredUrl = hasAccessToken(options)
? url.toString().replace(options.accessToken, '***')
: url.toString();

// check if the response is an error
if(!response.ok) {
// if the response is JSON, it might have more details in the `text` prop
if(isJson) {
const error: unknown = await response.json();

if(typeof error === 'object' && 'text' in error && typeof error.text === 'string') {
throw new Gw2ApiError(`The GW2 API call to '${url.toString()}' returned ${response.status} ${response.statusText}: ${error.text}.`, response);
throw new Gw2ApiError(`The GW2 API call to '${erroredUrl}' returned ${response.status} ${response.statusText}: ${error.text}.`, response);
}
}

// otherwise just throw error with the status code
throw new Gw2ApiError(`The GW2 API call to '${url.toString()}' returned ${response.status} ${response.statusText}.`, response);
throw new Gw2ApiError(`The GW2 API call to '${erroredUrl}' returned ${response.status} ${response.statusText}.`, response);
}

// if the response is not JSON, throw an error
if(!isJson) {
throw new Gw2ApiError(`The GW2 API call to '${url.toString()}' did not respond with a JSON response`, response);
throw new Gw2ApiError(`The GW2 API call to '${erroredUrl}' did not respond with a JSON response`, response);
}

// parse json
const json = await response.json();

// check that json is not `["v1", "v2"]` which sometimes happens for authenticated endpoints
if(url.toString() !== 'https://api.guildwars2.com/' && Array.isArray(json) && json.length === 2 && json[0] === 'v1' && json[1] === 'v2') {
throw new Gw2ApiError(`The GW2 API call to '${url.toString()}' did returned an invalid response (["v1", "v2"])`, response);
throw new Gw2ApiError(`The GW2 API call to '${erroredUrl}' did returned an invalid response (["v1", "v2"])`, response);
}

// TODO: catch more errors
Expand Down

0 comments on commit 88114b2

Please sign in to comment.