What happened?
Description
POST /logout on salt-api (rest_cherrypy) only expires the CherryPy session cookie and regenerates the server-side session id. The underlying Salt eauth token — the value stored in the configured eauth_tokens backend (localfs / redis / rediscluster) and the actual bearer credential used by X-Auth-Token: <token> — is never revoked. It outlives the cookie by token_expire (12 hours by default).
class Logout(LowDataAdapter):
def POST(self):
cherrypy.lib.sessions.expire() # client-side cookie
cherrypy.session.regenerate() # server-side session id
return {"return": "Your token has been cleared"}
The user thinks they have logged out. Anyone who has observed the token value — through access logs, shell history, leaked cookie, browser cache, intermediate proxy — can keep authenticating as that user until the token's natural expiry.
Setup
Any deployment running salt-api with rest_cherrypy and any eauth_tokens backend (the default is localfs).
Steps to Reproduce the behavior
- Authenticate against
salt-api: curl -sSk https://master:8000/login -d username=u -d password=p -d eauth=pam. Receive a token in the JSON response.
- Use the token to issue a request:
curl -sSk https://master:8000/run -H "X-Auth-Token: <token>" -d ... — works.
- Log out:
curl -sSk -X POST https://master:8000/logout -H "X-Auth-Token: <token>". Receive {"return": "Your token has been cleared"}.
- Reuse the same
<token> against /run. Still works — for up to token_expire seconds.
Expected behavior
After POST /logout, the Salt token should be invalid and X-Auth-Token: <token> requests should be rejected with 401.
Additional context
The accompanying PR adds a salt.auth.LoadAuth(self.opts).rm_token(<session_token>) call before the cookie is expired so the backend entry is deleted. If the token backend is unreachable, the failure is logged and the cookie is still expired, so the user-visible logout flow always completes. Three behavioural unit tests cover the happy path, the no-token-in-session path, and the backend-failure path.
Type of salt install
Official deb
Major version
3006.x, 3007.x
What supported OS are you seeing the problem on? Can select multiple. (If bug appears on an unsupported OS, please open a GitHub Discussion instead)
debian-11, debian-12
salt --versions-report output
salt --versions-report
Salt Version:
Salt: 3007.13
Python Version:
Python: 3.10.19 (main, Feb 5 2026, 07:05:38) [GCC 11.2.0]
Dependency Versions:
cffi: 2.0.0
cherrypy: unknown
cryptography: 42.0.5
dateutil: 2.8.2
docker-py: Not Installed
gitdb: Not Installed
gitpython: Not Installed
Jinja2: 3.1.6
libgit2: 1.9.1
looseversion: 1.3.0
M2Crypto: Not Installed
Mako: Not Installed
msgpack: 1.0.7
msgpack-pure: Not Installed
mysql-python: Not Installed
packaging: 24.0
pycparser: 2.21
pycrypto: Not Installed
pycryptodome: 3.19.1
pygit2: 1.18.2
python-gnupg: 0.5.2
PyYAML: 6.0.1
PyZMQ: 25.1.2
relenv: 0.22.3
smmap: Not Installed
timelib: 0.3.0
Tornado: 6.5.4
ZMQ: 4.3.4
Salt Extensions:
saltext.vault: 1.5.0
Salt Package Information:
Package Type: onedir
System Versions:
dist: debian 12.13 bookworm
locale: utf-8
machine: x86_64
release: 6.12.73+deb12-amd64
system: Linux
version: Debian GNU/Linux 12.13 bookworm
What happened?
Description
POST /logoutonsalt-api(rest_cherrypy) only expires the CherryPy session cookie and regenerates the server-side session id. The underlying Salt eauth token — the value stored in the configuredeauth_tokensbackend (localfs / redis / rediscluster) and the actual bearer credential used byX-Auth-Token: <token>— is never revoked. It outlives the cookie bytoken_expire(12 hours by default).The user thinks they have logged out. Anyone who has observed the token value — through access logs, shell history, leaked cookie, browser cache, intermediate proxy — can keep authenticating as that user until the token's natural expiry.
Setup
Any deployment running
salt-apiwithrest_cherrypyand anyeauth_tokensbackend (the default islocalfs).Steps to Reproduce the behavior
salt-api:curl -sSk https://master:8000/login -d username=u -d password=p -d eauth=pam. Receive a token in the JSON response.curl -sSk https://master:8000/run -H "X-Auth-Token: <token>" -d ...— works.curl -sSk -X POST https://master:8000/logout -H "X-Auth-Token: <token>". Receive{"return": "Your token has been cleared"}.<token>against/run. Still works — for up totoken_expireseconds.Expected behavior
After
POST /logout, the Salt token should be invalid andX-Auth-Token: <token>requests should be rejected with 401.Additional context
The accompanying PR adds a
salt.auth.LoadAuth(self.opts).rm_token(<session_token>)call before the cookie is expired so the backend entry is deleted. If the token backend is unreachable, the failure is logged and the cookie is still expired, so the user-visible logout flow always completes. Three behavioural unit tests cover the happy path, the no-token-in-session path, and the backend-failure path.Type of salt install
Official deb
Major version
3006.x, 3007.x
What supported OS are you seeing the problem on? Can select multiple. (If bug appears on an unsupported OS, please open a GitHub Discussion instead)
debian-11, debian-12
salt --versions-report output
salt --versions-report Salt Version: Salt: 3007.13 Python Version: Python: 3.10.19 (main, Feb 5 2026, 07:05:38) [GCC 11.2.0] Dependency Versions: cffi: 2.0.0 cherrypy: unknown cryptography: 42.0.5 dateutil: 2.8.2 docker-py: Not Installed gitdb: Not Installed gitpython: Not Installed Jinja2: 3.1.6 libgit2: 1.9.1 looseversion: 1.3.0 M2Crypto: Not Installed Mako: Not Installed msgpack: 1.0.7 msgpack-pure: Not Installed mysql-python: Not Installed packaging: 24.0 pycparser: 2.21 pycrypto: Not Installed pycryptodome: 3.19.1 pygit2: 1.18.2 python-gnupg: 0.5.2 PyYAML: 6.0.1 PyZMQ: 25.1.2 relenv: 0.22.3 smmap: Not Installed timelib: 0.3.0 Tornado: 6.5.4 ZMQ: 4.3.4 Salt Extensions: saltext.vault: 1.5.0 Salt Package Information: Package Type: onedir System Versions: dist: debian 12.13 bookworm locale: utf-8 machine: x86_64 release: 6.12.73+deb12-amd64 system: Linux version: Debian GNU/Linux 12.13 bookworm