[Bug]: Token Expiration Bypass in @segment/analytics-node 2.3.0
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 45/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Stale
- Tech stack
- typescript
- Domain
- authentication
Research direction
Start in src/lib/token-manager.ts at isValidToken around lines 320-326, then read the OAuth token handling around line 137 where expires_at is calculated. Reproduce the OAuth flow with an expired token and verify that expiration validation rejects it and triggers refresh rather than reusing the cached token.
Written by the indexing model from the issue text.
Description
Summary
The isValidToken method in the TokenManager class contains a logic error that causes token expiration checks to always pass, effectively disabling token expiration validation entirely.
Vulnerable Code
// src/lib/token-manager.ts, lines 320-326
isValidToken(token?: AccessToken): token is AccessToken {
return (
typeof token !== 'undefined' &&
token !== null &&
token.expires_in < Date.now() / 1000 // BUG: Wrong field and wrong comparison
)
}
Root Cause
The validation logic has two compounding errors:
-
Wrong field: The code checks
expires_in(a duration in seconds, e.g.,3600) instead ofexpires_at(the actual expiration timestamp). -
Wrong comparison operator: Even if the correct field were used, the comparison should check if the expiration time is greater than the current time, not less than.
How tokens are structured
When a token is received (line 137), the code correctly calculates expires_at:
token.expires_at = Math.round(Date.now() / 1000) + token.expires_in
For a token with expires_in: 3600 (1 hour):
expires_at= current timestamp + 3600 ≈1707004600expires_in=3600
Why the bug occurs
The current check token.expires_in < Date.now() / 1000 evaluates:
3600 < 1707000000 → true (always)
This condition is always true for any realistic token, meaning:
- Expired tokens are incorrectly considered valid
- Token refresh is never triggered based on expiration
- The SDK continues using stale/expired tokens
Impact
- Expired tokens remain in use: The SDK will continue sending requests with expired OAuth tokens until an external failure occurs.
- Authentication failures: Requests made with expired tokens will fail at the Segment API, causing data loss or delivery failures.
- Silent failures: Depending on error handling, these failures may go unnoticed.
Suggested Fix
isValidToken(token?: AccessToken): token is AccessToken {
return (
typeof token !== 'undefined' &&
token !== null &&
typeof token.expires_at === 'number' &&
token.expires_at > Date.now() / 1000 // Use expires_at with correct comparison
)
}
Reproduction
Any usage of the OAuth flow in @segment/analytics-node is affected. The bug can be confirmed by:
- Obtaining a valid OAuth token
- Waiting for the token to expire
- Observing that
isValidToken()still returnstrue - Observing that the cached expired token continues to be used
- Dominant language
- TypeScript
- Stars
- 477
- Forks
- 160
- Avg merge
- 6h 19m
- Merged PRs (30d)
- 4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from segmentio/analytics-next
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
segmentio/analytics-next#1324 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
segmentio/analytics-next#1366 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
segmentio/analytics-next#1337 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
segmentio/analytics-next#1332 ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
segmentio/analytics-next#1331 ·
All issues in segmentio/analytics-next
Similar issues
-
comp/dashboard P3 type/bug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
NousResearch/hermes-agent#117722 ·
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·