Fix Keystone CVE-2026-{42999,42998,43000,43001,44394} (Yoga)#23
Open
seunghun1ee wants to merge 11 commits into
Open
Fix Keystone CVE-2026-{42999,42998,43000,43001,44394} (Yoga)#23seunghun1ee wants to merge 11 commits into
seunghun1ee wants to merge 11 commits into
Conversation
The s3tokens and ec2tokens endpoint is a public API that does not require authentication to be called but that is what the testing does today. This duplicates the "good request" tests by also testing with noauth set so that we don't send a token in the request, this can prevent bugs where we would unintentionally require auth for these endpoints. Change-Id: Ibbde313ac8bcf3187c139bbd0840702f229534d0 (cherry picked from commit bd70653)
Add a policy to enforce authentication with a user in the service group. This maintains AWS compatibility with the added security layer. Closes-Bug: 2119646 Change-Id: Ic84b84247e05f29874e2c5636a033aaedd4de83c Signed-off-by: Grzegorz Grasza <xek@redhat.com> Signed-off-by: Jeremy Stanley <fungi@yuggoth.org> Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com> (cherry picked from commit b59e533bfd94d7dc8d404573179d00f2490f2ad1)
A restricted application credential could be used to create EC2 credentials granting full user access to S3, bypassing the role restriction. Add the same _check_unrestricted_application_credential guard that already protects application credential create/delete endpoints. Additionally, tighten the ec2_create_credential and ec2_delete_credential policies to require at least member role, as these are write operations that should not be accessible to reader-role users regardless of whether they are using an application credential. Change-Id: Ib6904ec9f1bc069a9f607d39814b1d2633c17f53 Closes-Bug: #2142138 Signed-off-by: Grzegorz Grasza <xek@redhat.com> (cherry picked from commit 34b7c572d065267bb31dbd6846aa48b9f11fe8c9)
…ials The POST /v3/credentials endpoint accepted EC2 credential creation from restricted application credential tokens, bypassing the guard on the dedicated OS-EC2 endpoint. Add the same unrestricted application credential check to the generic credentials API for EC2-type credentials, and update the existing test to use an unrestricted application credential. Related-Bug: #2142138 Generated-By: claude-opus-4-6 (OpenCode) Signed-off-by: Boris Bobrov <b.bobrov@sap.com> Change-Id: Idb192a2fd370fc26c7d76788e9ad1856483d3239 (cherry picked from commit afb7c20)
POST /v3/credentials did not validate that the caller-supplied project_id for an EC2-type credential matched the project of the authenticating application credential. This allowed an attacker holding an unrestricted application credential for project A to create an EC2 credential targeting project B; a subsequent /v3/ec2tokens exchange would then issue a Keystone token scoped to project B while still carrying the original app_cred_id, enabling cross-project lateral movement within the credential owner's role footprint. Two fixes: 1. credentials.py: after extracting app_cred_id from the token, check that credential['project_id'] == app_cred['project_id'] for EC2-type credentials and raise ForbiddenAction otherwise. 2. EC2_S3_Resource.py: in handle_authenticate(), assert that the stored EC2 credential project_id matches the application credential's project before issuing the token. This issue is orthogonal to CVE-2026-33551 (LP#2142138 / Gerrit 983655), which blocks restricted application credentials from creating EC2 credentials at all. The project-boundary check is absent regardless of the restricted flag and requires separate treatment. Closes-Bug: #2149775 Related-Bug: #OSPRH-29345 Assisted-by: claude-sonnet-4-6 <noreply@anthropic.com> Change-Id: I7c10c8a52e57e63cb9c66d03d69540abefe5425c Signed-off-by: Grzegorz Grasza <xek@redhat.com> (cherry picked from commit b6fd809) (cherry picked from commit d9e18a3) (cherry picked from commit 0892b69)
Delegated tokens (trusts, application credentials, OAuth1 access tokens)
are scoped to a single project at delegation time. This must be enforced
thoroughly while granting the API access to Keystone resources that
might be also bound to a single project. Without this it is possible to
gain different access (using trust to see application credentials for a
different project, reuse the MFA seed, etc).
* Credentials CRUD (/v3/credentials)
All five CRUD operations verified ownership via user_id but did not bind
credential.project_id to the delegating token's project scope.
Fix: _check_credential_project_scope() - no-op for non-delegated tokens,
raises ForbiddenAction on project mismatch. For list, out-of-scope
credentials are silently filtered.
Credentials with project_id=None (TOTP/MFA bindings) are treated as
out-of-scope for any delegated token: they are user-level secrets with no
project anchor, and a delegated token should never be able to enumerate,
read, or mutate them - doing so would allow a stolen delegation token to
exfiltrate or destroy a user's MFA binding.
* OS-EC2 credential CRUD (/v3/users/{id}/credentials/OS-EC2)
POST accepted any tenant_id from a delegated token. GET and DELETE had
no delegation check at all.
Fix: _check_delegation_for_ec2() enforces the project boundary;
list silently filters.
Additionally, pre-existing OAuth1 access-token-backed EC2 credentials
with a mismatched project_id could be used at auth-time (POST /v3/ec2tokens)
to obtain a cross-project token. Added a check in EC2_S3_Resource.py that
cred_data['project_id'] matches access_token['project_id'] before issuing
the token. The trust branch does not need this check - the token provider
uses the trust's project regardless of the credential's project_id.
* OS-OAUTH1 access token management (/v3/users/{id}/OS-OAUTH1/access_tokens)
GET and DELETE had no delegation check. List blocked trust/OAuth but not
app-cred tokens.
Fix: _block_delegated_token() raises Forbidden for any delegation type
on list, get, and delete.
* Application credential management (/v3/users/{id}/application_credentials)
Trust-scoped and OAuth1 tokens had no guard on the application credential
and access rule management APIs. An impersonating trust could LIST, CREATE,
or DELETE application credentials, creating a persistent backdoor that
outlives the trust's own expiry. App credential tokens are intentionally
excluded - the unrestricted/restricted distinction is handled separately by
_check_unrestricted_application_credential.
Fix: _block_delegated_token_app_creds() raises Forbidden for trust-scoped
and OAuth1 tokens on all six app credential and access rule endpoints.
Closes-Bug: #2150089
Related-Bug: #2149789
Related-Bug: #2149775
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Change-Id: Iaaa0ec713a0a5e062acc3209d6010982899d8f6f
Signed-off-by: Grzegorz Grasza <xek@redhat.com>
Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com>
(cherry picked from commit 16582e5192be354e26ebef4badca1213ddc4dc07)
(cherry picked from commit d88779a)
When authenticating by application credential ID, the caller can supply a 'user' field in the payload. AppCredInfo conditionally set the user from the credential owner only when no user field was present. If present, BaseUserInfo resolved the caller-supplied user and attributed the resulting token to that user instead of the credential owner. Fix: always set auth_payload['user'] from the credential's stored user_id, ignoring any caller-supplied value. Closes-Bug: #2148477 Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Boris Bobrov <b.bobrov@sap.com> Change-Id: I2fe6089886eebf3775930451b87771e40b5e179e Signed-off-by: Grzegorz Grasza <xek@redhat.com> Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com> (cherry picked from commit 6cd25fecdab8b9261e916ee10f3dba5aeb0c1984) (cherry picked from commit 0a57564)
Previously only restricted application credentials were blocked, and only for trust create and delete. This change blocks all application credentials (restricted and unrestricted alike) from all trust operations: list, get, create, delete, list-roles, and get-role. The 'unrestricted' flag governs credential management, not trust management. Closes-Bug: #2148477 Related-Bug: #2149789 Related-Bug: #2150089 Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Boris Bobrov <b.bobrov@sap.com> Change-Id: I750156df18a1d6293ce99c42eb524575fcf16ea3 Signed-off-by: Grzegorz Grasza <xek@redhat.com> Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com> (cherry picked from commit 3c2043ab003cb4b8aa34502fe9a5a69b0a6a6e54) (cherry picked from commit 7befe0a)
When a federated token is rescoped via POST /v3/auth/tokens the
handle_scoped_token function returned response_data without an expires_at
value. Because issue_token falls back to default_expire_time when
expires_at is None, each rescope issued a fresh full-TTL token instead of
inheriting the remaining lifetime of the original token.
A user with a federated token could extend their session indefinitely by
rescoping repeatedly before expiry, bypassing operator-configured TTL
policies and IdP-level account revocation.
Fix: propagate token.expires_at from handle_scoped_token so that
issue_token uses the original token's expiry rather than resetting to
the default. The non-federated path in token.py already did this via
response_data.setdefault('expires_at', token.expires_at).
Closes-Bug: #2150379
Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Artem Goncharov <artem.goncharov@gmail.com>
Change-Id: I0bbb8520e12c52edd01fb47c873f0227819706f5
Signed-off-by: Grzegorz Grasza <xek@redhat.com>
(cherry picked from commit 75a4a0c354c7f568b28dd85182dc729553fb3a33)
(cherry picked from commit 778250f)
…42999) The RBAC enforcer unconditionally merged the raw JSON request body into the policy enforcement dictionary after trusted target data had been set from the database. An attacker could include a "target" key in the JSON body to overwrite database-sourced RBAC target attributes, causing all %(target.*)s policy substitutions to evaluate against attacker-controlled values. This affected 88 endpoint/method combinations across all Keystone API resources. The fix namespaces user-controlled JSON body data under a "request_body" key in the policy dict, making it structurally impossible for request body fields to collide with internal keys like "target" or view_args. The only in-tree policy rule that depended on the old JSON body merge behavior was identity:create_trust, which referenced %(trust.trustor_user_id)s from the request body at the top level of the policy dict. This is updated to use target_attr and the %(target.trust.trustor_user_id)s substitution, consistent with all other trust policy rules. Additionally, query-string filter values had the same structural issue: _extract_filter_values() results were merged at the top level, meaning a filter key matching a view_arg key (e.g. user_id on /v3/users/{user_id}/... endpoints using ADMIN_OR_SYSTEM_READER_OR_OWNER) could be overwritten by an attacker-controlled ?user_id= query param, bypassing ownership checks. Filter values are now namespaced under "filter_attr". No in-tree policy rule references filter values via %(key)s substitutions, so this is backwards-compatible for upstream deployments. Closes-Bug: #2148398 Assisted-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Boris Bobrov <b.bobrov@sap.com> Co-authored-by: Artem Goncharov <artem.goncharov@gmail.com> Change-Id: I295d1ac27faad05a680bb2b3fac8cfa27fa1c4bd Signed-off-by: Grzegorz Grasza <xek@redhat.com> (cherry picked from commit 22b51f5d5d86350d3fbc66697e4097bacf2a8ce9) (cherry picked from commit fda75e5)
Alex-Welsh
approved these changes
May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.