Describe the bug
Three bugs were found in the fetcher modules that affect security and reliability:
Bug 1 — SSRF via unvalidated api_domain in src/fetchers/wakatime.js
The api_domain query parameter is user-controlled and inserted directly into the outgoing URL without any domain validation:
const { data } = await axios.get(
`https://${
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
}/api/v1/users/${username}/stats?is_including_today=true`,
);
A malicious actor can supply api_domain=evil.com and the server will make an outgoing HTTP request to https://evil.com/api/v1/users/... — a Server-Side Request Forgery (SSRF) vulnerability.
Bug 2 — Unsafe err.response.status access in src/fetchers/wakatime.js:26
} catch (err) {
if (err.response.status < 200 || err.response.status > 299) {
If err.response is undefined (network timeout, DNS failure), this throws an uncaught TypeError, swallowing the original error and crashing the handler.
Bug 3 — throw new Error(err) loses original stack trace in src/fetchers/stats.js:202
} catch (err) {
logger.log(err);
throw new Error(err);
}
Wrapping the caught error in new Error(err) coerces it to a string, losing the original stack trace and error type.
Expected behavior
- Bug 1:
api_domain should be validated against an allowlist of trusted domains. Invalid domains should return a clear error instead of making an outbound request.
- Bug 2: A network error in the WakaTime fetcher should be handled gracefully without throwing a
TypeError. Optional chaining (err.response?.status) prevents the crash.
- Bug 3: The original error should be rethrown directly (
throw err) to preserve its stack trace and type for debugging.
Additional context
A fix for all three bugs is proposed in the linked pull request, with all existing tests passing.
Describe the bug
Three bugs were found in the fetcher modules that affect security and reliability:
Bug 1 — SSRF via unvalidated
api_domaininsrc/fetchers/wakatime.jsThe
api_domainquery parameter is user-controlled and inserted directly into the outgoing URL without any domain validation:A malicious actor can supply
api_domain=evil.comand the server will make an outgoing HTTP request tohttps://evil.com/api/v1/users/...— a Server-Side Request Forgery (SSRF) vulnerability.Bug 2 — Unsafe
err.response.statusaccess insrc/fetchers/wakatime.js:26If
err.responseisundefined(network timeout, DNS failure), this throws an uncaughtTypeError, swallowing the original error and crashing the handler.Bug 3 —
throw new Error(err)loses original stack trace insrc/fetchers/stats.js:202Wrapping the caught error in
new Error(err)coerces it to a string, losing the original stack trace and error type.Expected behavior
api_domainshould be validated against an allowlist of trusted domains. Invalid domains should return a clear error instead of making an outbound request.TypeError. Optional chaining (err.response?.status) prevents the crash.throw err) to preserve its stack trace and type for debugging.Additional context
A fix for all three bugs is proposed in the linked pull request, with all existing tests passing.