Moderate severityNVD Advisory· Published Sep 18, 2012· Updated Apr 29, 2026
CVE-2012-4413
CVE-2012-4413
Description
OpenStack Keystone 2012.1.3 does not invalidate existing tokens when granting or revoking roles, which allows remote authenticated users to retain the privileges of the revoked roles.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
keystonePyPI | < 2012.1.3 | 2012.1.3 |
Affected products
1Patches
158ac6691a216Delete user tokens after role grant/revoke
3 files changed · +26 −10
keystone/identity/core.py+6 −1 modified@@ -525,6 +525,8 @@ def add_role_to_user(self, context, user_id, role_id, tenant_id=None): self.identity_api.add_user_to_tenant(context, tenant_id, user_id) self.identity_api.add_role_to_user_and_tenant( context, user_id, tenant_id, role_id) + self.token_api.revoke_tokens(context, user_id) + role_ref = self.identity_api.get_role(context, role_id) return {'role': role_ref} @@ -555,7 +557,7 @@ def remove_role_from_user(self, context, user_id, role_id, tenant_id=None): if not roles: self.identity_api.remove_user_from_tenant( context, tenant_id, user_id) - return + self.token_api.revoke_tokens(context, user_id) # COMPAT(diablo): CRUD extension def get_role_refs(self, context, user_id): @@ -597,6 +599,8 @@ def create_role_ref(self, context, user_id, role): self.identity_api.add_user_to_tenant(context, tenant_id, user_id) self.identity_api.add_role_to_user_and_tenant( context, user_id, tenant_id, role_id) + self.token_api.revoke_tokens(context, user_id) + role_ref = self.identity_api.get_role(context, role_id) return {'role': role_ref} @@ -624,3 +628,4 @@ def delete_role_ref(self, context, user_id, role_ref_id): if not roles: self.identity_api.remove_user_from_tenant( context, tenant_id, user_id) + self.token_api.revoke_tokens(context, user_id)
keystone/token/core.py+11 −0 modified@@ -38,6 +38,10 @@ class Manager(manager.Manager): def __init__(self): super(Manager, self).__init__(CONF.token.driver) + def revoke_tokens(self, context, user_id): + for token_id in self.list_tokens(context, user_id): + self.delete_token(context, token_id) + class Driver(object): """Interface description for a Token driver.""" @@ -97,6 +101,13 @@ def list_tokens(self, user_id): """ raise exception.NotImplemented() + def revoke_tokens(self, user_id): + """Invalidates all tokens held by a user. + + :raises: keystone.exception.UserNotFound + """ + raise exception.NotImplemented() + def _get_default_expire_time(self): """Determine when a token should expire based on the config.
tests/test_keystoneclient.py+9 −9 modified@@ -769,15 +769,15 @@ def get_checkout(self): def test_tenant_add_and_remove_user(self): client = self.get_client(admin=True) client.roles.add_user_role(tenant=self.tenant_baz['id'], - user=self.user_foo['id'], + user=self.user_two['id'], role=self.role_useless['id']) user_refs = client.tenants.list_users(tenant=self.tenant_baz['id']) - self.assert_(self.user_foo['id'] in [x.id for x in user_refs]) + self.assert_(self.user_two['id'] in [x.id for x in user_refs]) client.roles.remove_user_role(tenant=self.tenant_baz['id'], - user=self.user_foo['id'], + user=self.user_two['id'], role=self.role_useless['id']) user_refs = client.tenants.list_users(tenant=self.tenant_baz['id']) - self.assert_(self.user_foo['id'] not in [x.id for x in user_refs]) + self.assert_(self.user_two['id'] not in [x.id for x in user_refs]) def test_user_role_add_404(self): from keystoneclient import exceptions as client_exceptions @@ -890,28 +890,28 @@ def get_checkout(self): def test_tenant_add_and_remove_user(self): client = self.get_client(admin=True) client.roles.add_user_to_tenant(tenant_id=self.tenant_baz['id'], - user_id=self.user_foo['id'], + user_id=self.user_two['id'], role_id=self.role_useless['id']) role_refs = client.roles.get_user_role_refs( - user_id=self.user_foo['id']) + user_id=self.user_two['id']) self.assert_(self.tenant_baz['id'] in [x.tenantId for x in role_refs]) # get the "role_refs" so we get the proper id, this is how the clients # do it roleref_refs = client.roles.get_user_role_refs( - user_id=self.user_foo['id']) + user_id=self.user_two['id']) for roleref_ref in roleref_refs: if (roleref_ref.roleId == self.role_useless['id'] and roleref_ref.tenantId == self.tenant_baz['id']): # use python's scope fall through to leave roleref_ref set break client.roles.remove_user_from_tenant(tenant_id=self.tenant_baz['id'], - user_id=self.user_foo['id'], + user_id=self.user_two['id'], role_id=roleref_ref.id) role_refs = client.roles.get_user_role_refs( - user_id=self.user_foo['id']) + user_id=self.user_two['id']) self.assert_(self.tenant_baz['id'] not in [x.tenantId for x in role_refs])
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
17- secunia.com/advisories/50531nvdVendor Advisory
- secunia.com/advisories/50590nvdVendor Advisory
- github.com/advisories/GHSA-mrxv-65rv-6hxqghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-4413ghsaADVISORY
- github.com/openstack/keystone/commit/58ac6691a21675be9e2ffb0f84a05fc3cd4d2e2eghsaWEB
- www.openwall.com/lists/oss-security/2012/09/12/7nvdWEB
- www.ubuntu.com/usn/USN-1564-1nvdWEB
- access.redhat.com/errata/RHSA-2012:1378ghsaWEB
- access.redhat.com/security/cve/CVE-2012-4413ghsaWEB
- bugs.launchpad.net/keystone/+bug/1041396ghsaWEB
- bugzilla.redhat.com/show_bug.cgighsaWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/78478nvdWEB
- opendev.org/openstack/keystoneghsaPACKAGE
- review.opendev.org/c/openstack/keystone/+/12870ghsaWEB
- web.archive.org/web/20121114023848/http://www.securityfocus.com/bid/55524ghsaWEB
- osvdb.org/85484nvd
- www.securityfocus.com/bid/55524nvd
News mentions
0No linked articles in our index yet.