diff --git a/java/jenkins/authz/executor-interrupt-without-permission.yaml b/java/jenkins/authz/executor-interrupt-without-permission.yaml new file mode 100644 index 0000000..9ad310c --- /dev/null +++ b/java/jenkins/authz/executor-interrupt-without-permission.yaml @@ -0,0 +1,50 @@ +rules: + - id: codevigilant.java.jenkins.authz.executor-interrupt-without-permission + patterns: + - pattern-inside: | + $RET $M(...) { + ... + } + - pattern: $EXEC.interrupt($RESULT); + - pattern-not-inside: | + $RET $M(...) { + ... + if (!$OBJ.hasPermission($PERM)) { + ... + } + ... + } + - pattern-not-inside: | + $RET $M(...) { + ... + if ($OBJ.hasPermission($PERM)) { + ... + } + ... + } + - pattern-not-inside: | + $RET $M(...) { + ... + $OBJ.checkPermission($PERM); + ... + } + message: | + Detected Executor.interrupt() invoked in a method that performs no ACL + permission check. Interrupting an executor aborts the running build, + which can leave artifacts and post-build steps in an inconsistent state. + In Jenkins this must be guarded by a permission check on the affected + build's project (e.g. Item.CANCEL / Item.BUILD); otherwise any code path + reaching the method can deny service on arbitrary jobs. + metadata: + category: security + cwe: "CWE-862: Missing Authorization" + owasp: "A01:2021 - Broken Access Control" + technology: jenkins + confidence: MEDIUM + references: + - https://www.jenkins.io/doc/developer/security/ + source: independent security review + license: MIT + languages: [java] + mode: search + severity: HIGH diff --git a/testcases/java/executor-interrupt-without-permission-neg.java b/testcases/java/executor-interrupt-without-permission-neg.java new file mode 100644 index 0000000..16a2788 --- /dev/null +++ b/testcases/java/executor-interrupt-without-permission-neg.java @@ -0,0 +1,26 @@ +import hudson.model.Executor; +import hudson.model.Item; +import hudson.model.Result; + +public class ExecutorInterruptNeg { + private final Object project; + + public ExecutorInterruptNeg(Object project) { + this.project = project; + } + + // fixed: permission check on the affected build's project before aborting + public void doKillRunningBuild() { + if (!((Item) project).hasPermission(Item.CANCEL)) { + return; + } + Executor executor = getExecutorOfLastBuild(); + if (executor != null) { + executor.interrupt(Result.ABORTED); + } + } + + private Executor getExecutorOfLastBuild() { + return null; + } +} diff --git a/testcases/java/executor-interrupt-without-permission-pos.java b/testcases/java/executor-interrupt-without-permission-pos.java new file mode 100644 index 0000000..a9c30af --- /dev/null +++ b/testcases/java/executor-interrupt-without-permission-pos.java @@ -0,0 +1,16 @@ +import hudson.model.Executor; +import hudson.model.Result; + +public class ExecutorInterruptPos { + // vulnerable: aborts whatever build is running, no ACL check anywhere + public void doKillRunningBuild() { + Executor executor = getExecutorOfLastBuild(); + if (executor != null) { + executor.interrupt(Result.ABORTED); + } + } + + private Executor getExecutorOfLastBuild() { + return null; + } +}