From 313fe39a5b950bbd90b0c9fa1a7fb974e43977e7 Mon Sep 17 00:00:00 2001 From: ai-anant Date: Fri, 4 Sep 2026 00:23:29 +0530 Subject: [PATCH 1/2] feat(java): detect credential lookups with ACL.SYSTEM inside doFill* form handlers (CWE-522) --- .../acl-system-fill-credential-lookup.yaml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 java/jenkins/credentials/acl-system-fill-credential-lookup.yaml diff --git a/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml b/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml new file mode 100644 index 0000000..5129c86 --- /dev/null +++ b/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml @@ -0,0 +1,44 @@ +rules: + - id: codevigilant.java.jenkins.credentials.acl-system-fill-credential-lookup + patterns: + - pattern-inside: | + public $RET $HANDLER(...) { + ... + } + - metavariable-regex: + metavariable: $HANDLER + regex: ^doFill[A-Z] + - pattern-either: + - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM) + - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM, $EXTRA) + - pattern-not-inside: | + public $RET $HANDLER(...) { + ... + $X.checkPermission($PERM); + ... + } + message: | + Detected a Stapler form-filling handler (doFill*) that resolves + credentials with ACL.SYSTEM instead of the requesting user's + authentication. The resulting credential list (IDs, usernames, endpoint + metadata) is returned unfiltered by the caller's permissions, so any + user who can reach the descriptor URL can enumerate every stored + credential of this type even without Credentials/View permission + (CWE-522/CWE-200). Pass the caller's authentication (e.g. the + ItemGroup/context or Jenkins.getAuthentication2()) into + lookupCredentials and restrict the results with withMatching(...), and + guard the handler with an explicit permission check. + metadata: + category: security + cwe: "CWE-522: Insufficiently Protected Credentials" + owasp: "A01:2021 - Broken Access Control" + technology: jenkins + confidence: HIGH + references: + - https://www.jenkins.io/doc/developer/security/ + - https://javadoc.jenkins.io/plugin/credentials/com/cloudbees/plugins/credentials/CredentialsProvider.html + source: independent security review + license: MIT + languages: [java] + mode: search + severity: HIGH \ No newline at end of file From eff95f3ba768fb13d852e4eb165c6faac3217ed7 Mon Sep 17 00:00:00 2001 From: ai-anant Date: Fri, 18 Sep 2026 21:14:11 +0530 Subject: [PATCH 2/2] feat(java): extend ACL.SYSTEM doFill credential rule to credential-listing/listbox APIs (CWE-522) --- .../acl-system-fill-credential-lookup.yaml | 73 ++++++++++++++----- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml b/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml index 5129c86..54cd89f 100644 --- a/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml +++ b/java/jenkins/credentials/acl-system-fill-credential-lookup.yaml @@ -1,33 +1,68 @@ rules: - id: codevigilant.java.jenkins.credentials.acl-system-fill-credential-lookup patterns: - - pattern-inside: | + - pattern-either: + - patterns: + - pattern-inside: | + public $RET $HANDLER(...) { + ... + } + - metavariable-regex: + metavariable: $HANDLER + regex: ^doFill[A-Z] + - pattern-either: + - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM) + - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM, $EXTRA) + - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM, ...) + - pattern: $MODEL.includeMatchingAs(ACL.SYSTEM, ...) + - pattern: $MODEL.includeAs(ACL.SYSTEM, ...) + - pattern: $MODEL.listCredentials(..., ACL.SYSTEM, ...) + - pattern: $MODEL.getCredentialIds(..., ACL.SYSTEM, ...) + - patterns: + - pattern-inside: | + $RET $HANDLER(...) { + ... + } + - metavariable-regex: + metavariable: $RET + regex: .*ListBoxModel + - pattern-either: + - pattern: $MODEL.includeMatchingAs(ACL.SYSTEM, ...) + - pattern: $MODEL.includeAs(ACL.SYSTEM, ...) + - pattern: $MODEL.listCredentials(..., ACL.SYSTEM, ...) + - pattern: $MODEL.getCredentialIds(..., ACL.SYSTEM, ...) + - pattern: | + $CTX instanceof Queue.Task ? ((Queue.Task) $CTX).getDefaultAuthentication() : ACL.SYSTEM + - pattern-not-inside: | public $RET $HANDLER(...) { ... + $X.checkPermission($PERM); + ... } - - metavariable-regex: - metavariable: $HANDLER - regex: ^doFill[A-Z] - - pattern-either: - - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM) - - pattern: CredentialsProvider.lookupCredentials($TYPE, $CTX, ACL.SYSTEM, $EXTRA) - pattern-not-inside: | public $RET $HANDLER(...) { ... - $X.checkPermission($PERM); + $X.hasPermission($PERM); ... } message: | - Detected a Stapler form-filling handler (doFill*) that resolves - credentials with ACL.SYSTEM instead of the requesting user's - authentication. The resulting credential list (IDs, usernames, endpoint - metadata) is returned unfiltered by the caller's permissions, so any - user who can reach the descriptor URL can enumerate every stored - credential of this type even without Credentials/View permission - (CWE-522/CWE-200). Pass the caller's authentication (e.g. the - ItemGroup/context or Jenkins.getAuthentication2()) into - lookupCredentials and restrict the results with withMatching(...), and - guard the handler with an explicit permission check. + Detected credential enumeration performed with the ACL.SYSTEM + authentication instead of the requesting user's authentication. This + happens in a Stapler form-filling handler (doFill*), or in a + listbox-building helper that such a handler calls, either by passing + ACL.SYSTEM to a credential-listing API -- CredentialsProvider + lookupCredentials / listCredentials / getCredentialIds, or the + credentials-plugin listbox API includeMatchingAs / includeAs -- or by + falling back to Queue.Task#getDefaultAuthentication(), whose Jenkins + core default is ACL.SYSTEM. Credential metadata (IDs, names, usernames, + endpoint metadata) is then returned unfiltered by the caller's + permissions, so any user who can reach the descriptor URL can enumerate + every stored credential of that type even without Credentials/View + permission (CWE-522/CWE-200). Resolve credentials with the caller's + authentication (e.g. Jenkins.getAuthentication2(), + Tasks.getAuthenticationOf(context)) and guard the handler with an + explicit permission check (e.g. context.hasPermission(Item.CONFIGURE)), + returning an empty selection when the guard fails. metadata: category: security cwe: "CWE-522: Insufficiently Protected Credentials" @@ -41,4 +76,4 @@ rules: license: MIT languages: [java] mode: search - severity: HIGH \ No newline at end of file + severity: HIGH