Skip to content

fix: SSRF vulnerability and error handling bugs in wakatime and stats fetchers #4859

@joaopedroplinta

Description

@joaopedroplinta

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions