T09 · Insecure Skill Coding Practices
- Location
references/examples.md:770- Finding
Unbounded Retry Loop on HTTP 401 Responses
- Content
View full analysis
Vulnerability Details
File Location:
references/examples.md, lines 770-779
Vulnerability Type: Unbounded authentication retry
Risk Level: MediumVulnerable Code
typescript this.client.interceptors.response.use( (response) => response, async (error) => { if (error.response?.status === 401) { // Handle token refresh await this.refreshToken(); return this.client.request(error.config); } return Promise.reject(error); } );The referenced token-refresh method is an unimplemented stub:
typescript private async refreshToken(): Promise<void> { // Implement token refresh logic }Technical Analysis
The generated Axios client retries every request that receives an HTTP 401 response. The request configuration does not contain a retry marker or attempt counter, and there is no maximum retry limit. The
refreshToken()method is also an empty stub, so it does not update the credentials before the original request is replayed.Because the replayed request passes through the same response interceptor, another 401 response triggers the same logic again. This creates an unbounded asynchronous request loop whenever authentication cannot be restored.
Attack Path
- An application uses a client generated from this example.
- The client sends an authenticated request to an API.
- The API, an unavailable authentication service, or an attacker-controlled endpoint returns HTTP 401.
- The response interceptor calls the no-op
refreshToken()method. - The interceptor replays the original request without changing its invalid credentials.
- The server returns HTTP 401 again.
- Steps 4 through 6 repeat indefinitely because no retry limit or retry marker is present.
Impact Assessment
Exploitation does not directly grant additional privileges or access to protected data. However, a persistent or attacker-induced 401 ...[truncated 552 chars]
- Remediation
View remediation
Remediation Suggestions
- Add a private retry marker to the Axios request configuration and permit at most one replay after a 401 response.
- Reject the request immediately if it has already been retried.
- Implement
refreshToken()so that it either installs a valid replacement token or throws a handled authentication error. - Never invoke refresh-and-retry logic for the token-refresh endpoint itself.
- Clear credentials and propagate an authentication failure when refresh fails.
- Deduplicate concurrent refresh attempts so multiple 401 responses do not create a refresh-request storm.
- Add tests covering persistent 401 responses, failed refreshes, refresh-endpoint 401 responses, and concurrent authentication failures.
A guarded implementation can use logic equivalent to:
typescript const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { await this.refreshToken(); return this.client.request(originalRequest); } catch (refreshError) { return Promise.reject(refreshError); } } return Promise.reject(error);
