Impact
On Unix-like systems, the system temporary directory can be created with open permissions that allow multiple users to create and delete files within it. Gradle builds could be vulnerable to a local privilege escalation from an attacker quickly deleting and recreating files in the system temporary directory.
This vulnerability impacted builds using precompiled script plugins written in Kotlin DSL and tests for Gradle plugins written using ProjectBuilder
or TestKit.
If you are on Windows or modern versions of macOS, you are not vulnerable.
If you are on a Unix-like operating system with the "sticky" bit set on your system temporary directory, you are not vulnerable.
Precompiled script plugins
When compiling precompiled script plugins written in Kotlin DSL, Gradle uses a temporary directory in the system temporary directory to execute a build-like process.
A local privilege escalation can occur due to a race condition in the creation of this temporary directory. If an attacker is able to write files into the directory created by Gradle, the attacker can execute commands at the same privilege level as the build.
If you do not use precompiled script plugins, you are not vulnerable.
ProjectBuilder
API in tests
ProjectBuilder
is most commonly used by plugin authors to write unit tests. With this API, if you do not specify a project directory, Gradle will create one for you in a temporary directory.
A local privilege escalation can occur due to a race condition in the creation of this temporary directory. If an attacker is able to write files into the project directory created for the test, the attacker can execute commands at the same privilege level as the build.
If you do not use ProjectBuilder
or you always specify a project directory, you are not vulnerable.
Gradle TestKit in tests
TestKit is also used by plugin authors to write integration tests. These tests execute full Gradle builds. TestKit uses a well-known path in the system temporary directory to cache some information between runs, like Gradle distributions and dependency downloads.
A local privilege escalation can occur if an attacker controls the creation of this directory. If an attacker is able to write files into the directory created for TestKit, the attacker can execute commands at the same privilege level as the build.
If you do not use TestKit, you are not vulnerable.
What should you do?
Upgrade to Gradle 7.0
As of Gradle 7.0, ProjectBuilder
, TestKit and other uses of the system temporary directory have been removed where possible. Instead of relying on the system temporary directory, Gradle now uses a combination of the Gradle User Home and project's build directory.
Workaround for older versions
On Unix-like operating systems, ensure that the "sticky" bit is set. This only allows the original user (or root) to delete a file.
If you are unable to change the permissions of the system temporary directory, you can move the Java temporary directory by setting the System Property java.io.tmpdir
. The new path needs to limit permissions to the build user only.
References
The vulnerable code:
|
try { |
|
// TODO: This is not a great paradigm for creating a temporary directory. |
|
// See http://guava-libraries.googlecode.com/svn/tags/release08/javadoc/com/google/common/io/Files.html#createTempDir%28%29 for an alternative. |
|
File tmpDir = File.createTempFile("gradle", "projectDir", dir); |
|
tmpDir.delete(); |
|
tmpDir.mkdir(); |
|
return tmpDir; |
|
private File createTestKitDir(TestKitDirProvider testKitDirProvider) { |
|
File dir = testKitDirProvider.getDir(); |
|
if (dir.isDirectory()) { |
|
if (!dir.canWrite()) { |
|
throw new InvalidRunnerConfigurationException("Unable to write to test kit directory: " + dir.getAbsolutePath()); |
|
} |
|
return dir; |
|
} else if (dir.exists() && !dir.isDirectory()) { |
|
throw new InvalidRunnerConfigurationException("Unable to use non-directory as test kit directory: " + dir.getAbsolutePath()); |
|
} else if (dir.mkdirs() || dir.isDirectory()) { |
|
return dir; |
|
} else { |
|
throw new InvalidRunnerConfigurationException("Unable to create test kit directory: " + dir.getAbsolutePath()); |
|
} |
|
} |
- #15240
- #15654
These other projects experienced similar vulnerabilities:
More about this type of vulnerability:
Questions?
- For security related issues, please email us at security@gradle.com.
- For non-security related issues, please open an issue on GitHub.
Impact
On Unix-like systems, the system temporary directory can be created with open permissions that allow multiple users to create and delete files within it. Gradle builds could be vulnerable to a local privilege escalation from an attacker quickly deleting and recreating files in the system temporary directory.
This vulnerability impacted builds using precompiled script plugins written in Kotlin DSL and tests for Gradle plugins written using
ProjectBuilder
or TestKit.If you are on Windows or modern versions of macOS, you are not vulnerable.
If you are on a Unix-like operating system with the "sticky" bit set on your system temporary directory, you are not vulnerable.
Precompiled script plugins
When compiling precompiled script plugins written in Kotlin DSL, Gradle uses a temporary directory in the system temporary directory to execute a build-like process.
A local privilege escalation can occur due to a race condition in the creation of this temporary directory. If an attacker is able to write files into the directory created by Gradle, the attacker can execute commands at the same privilege level as the build.
If you do not use precompiled script plugins, you are not vulnerable.
ProjectBuilder
API in testsProjectBuilder
is most commonly used by plugin authors to write unit tests. With this API, if you do not specify a project directory, Gradle will create one for you in a temporary directory.A local privilege escalation can occur due to a race condition in the creation of this temporary directory. If an attacker is able to write files into the project directory created for the test, the attacker can execute commands at the same privilege level as the build.
If you do not use
ProjectBuilder
or you always specify a project directory, you are not vulnerable.Gradle TestKit in tests
TestKit is also used by plugin authors to write integration tests. These tests execute full Gradle builds. TestKit uses a well-known path in the system temporary directory to cache some information between runs, like Gradle distributions and dependency downloads.
A local privilege escalation can occur if an attacker controls the creation of this directory. If an attacker is able to write files into the directory created for TestKit, the attacker can execute commands at the same privilege level as the build.
If you do not use TestKit, you are not vulnerable.
What should you do?
Upgrade to Gradle 7.0
As of Gradle 7.0,
ProjectBuilder
, TestKit and other uses of the system temporary directory have been removed where possible. Instead of relying on the system temporary directory, Gradle now uses a combination of the Gradle User Home and project's build directory.Workaround for older versions
On Unix-like operating systems, ensure that the "sticky" bit is set. This only allows the original user (or root) to delete a file.
If you are unable to change the permissions of the system temporary directory, you can move the Java temporary directory by setting the System Property
java.io.tmpdir
. The new path needs to limit permissions to the build user only.References
The vulnerable code:
gradle/subprojects/core/src/main/java/org/gradle/api/internal/file/DefaultTemporaryFileProvider.java
Lines 57 to 63 in ff5dc12
gradle/subprojects/test-kit/src/main/java/org/gradle/testkit/runner/internal/DefaultGradleRunner.java
Lines 336 to 350 in d024846
These other projects experienced similar vulnerabilities:
More about this type of vulnerability:
Questions?