volcano-sh / volcano-sh/agentcube

TokenCache can return authenticated=true after JWT expiry due to sliding TTL (does not check exp)

Open
#375 2 comments 0 reactions 1 assignee View on GitHub

@HarshitPal25 is already working on this.

Since Jun 4, 2026.

kind/bug
Dominant language
Go
Stars
167
Forks
88
Avg merge
44m
Merged PRs (30d)
1

Description

Summary

TokenCache.Get in pkg/workloadmanager/client_cache.go only checks how long ago the cache entry was last accessed (time.Since(entry.lastAccess) > c.ttl). Every time a cached token is used, lastAccess is reset to time.Now(), continuously pushing the expiry window forward. The token's actual JWT exp claim is never checked on cache hits. By contrast, ClientCache.Get (which caches K8s user clients) correctly parses the JWT expiry via parseJWTExpiry and evicts entries once the token has expired. TokenCache has parseJWTExpiry available but does not use it.

Affected code

func (c *TokenCache) Get(token string) (found bool, authenticated bool, username string) {
	c.mu.Lock()
	defer c.mu.Unlock()
 
	entry, exists := c.cache[token]
	if !exists {
		return false, false, ""
	}
 
	// Only checks sliding lastAccess — token's real JWT exp is neververified
	if time.Since(entry.lastAccess) > c.ttl {
		c.lruList.Remove(entry.element)
		delete(c.cache, token)
		return false, false, ""
	}
 
	// Resets the window — a busy token never expires from cache
	entry.lastAccess = time.Now()
	c.lruList.MoveToFront(entry.element)
	return true, entry.authenticated, entry.username
}

Reproduction scenario

  1. Use a K8s service-account token with a 1-minute lifetime.
  2. Validate it once so it gets cached in TokenCache as authenticated=true.
  3. Send requests every 4 minutes.
    • Each hit updates lastAccess, keeping the cache entry alive.
  4. After the token expires , TokenCache continues to return the cached authenticated=true result until there is a full 5-minute gap with no requests.

Expected behavior

TokenCache.Get should not return a cached authentication result once the JWT has expired (based on exp), even if requests keep arriving within the TTL window.

Actual behavior

TokenCache.Get can continue returning authenticated=true after the token has expired because only sliding lastAccess TTL is enforced.

Suggested fix

Store and enforce JWT expiry in tokenCacheEntry similar to clientCacheEntry:

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.