VYPR
High severityNVD Advisory· Published Oct 1, 2020· Updated Aug 4, 2024

CVE-2020-11979

CVE-2020-11979

Description

As mitigation for CVE-2020-1945 Apache Ant 1.10.8 changed the permissions of temporary files it created so that only the current user was allowed to access them. Unfortunately the fixcrlf task deleted the temporary file and created a new one without said protection, effectively nullifying the effort. This would still allow an attacker to inject modified source files into the build process.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Apache Ant's fixcrlf task bypassed temporary file permission hardening, allowing local attackers to inject modified source files during builds.

Vulnerability

Overview

CVE-2020-11979 describes a flaw in Apache Ant where the fixcrlf task undermines the temporary file permission hardening introduced to address CVE-2020-1945. In Ant 1.10.8, temporary files were created with permissions restricted to the current user. However, the fixcrlf task deleted that protected temporary file and created a new one without the same restrictions, effectively nullifying the security fix [1][4].

Exploitation

A local attacker with access to the build system can exploit this insecure temporary file creation. By monitoring or interfering with the temporary file creation process, the attacker can inject modified source files into the build process. No authentication beyond local system access is required [1].

Impact

Successful exploitation allows an attacker to inject arbitrary source files into the build, potentially leading to the inclusion of malicious code in the final build artifacts. This could result in arbitrary code execution in environments where the build output is used [1][4].

Mitigation

The vulnerability is fixed in Apache Ant 1.10.9, which ensures that temporary files created by fixcrlf are also protected. The fix is implemented in commit 87ac51d [3]. Gradle has also issued a security advisory (GHSA-j45w-qrgf-25vm) recommending users upgrade to a patched version [4].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
org.apache.ant:antMaven
< 1.10.91.10.9

Affected products

7

Patches

1
87ac51d3c22b

fallback to a separate owner-only tempdir if possible

https://github.com/apache/antStefan BodewigJul 4, 2020via ghsa
3 files changed · +105 5
  • src/main/org/apache/tools/ant/MagicNames.java+10 0 modified
    @@ -337,5 +337,15 @@ private MagicNames() {
          * @since Ant 1.10.8
          */
         public static final String TMPDIR = "ant.tmpdir";
    +
    +    /**
    +     * Magic property that will be set to override java.io.tmpdir
    +     * system property as the location for Ant's default temporary
    +     * directory if a temp file is created and {@link #TMPDIR} is not
    +     * set.
    +     * Value: {@value}
    +     * @since Ant 1.10.9
    +     */
    +    public static final String AUTO_TMPDIR = "ant.auto.tmpdir";
     }
     
    
  • src/main/org/apache/tools/ant/util/FileUtils.java+31 5 modified
    @@ -110,6 +110,11 @@ public class FileUtils {
                 PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ,
                     PosixFilePermission.OWNER_WRITE))
             };
    +    private static final FileAttribute[] TMPDIR_ATTRIBUTES =
    +        new FileAttribute[] {
    +            PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ,
    +                PosixFilePermission.OWNER_WRITE, PosixFilePermission.OWNER_EXECUTE))
    +        };
         private static final FileAttribute[] NO_TMPFILE_ATTRIBUTES = new FileAttribute[0];
     
         /**
    @@ -991,14 +996,35 @@ public File createTempFile(String prefix, String suffix, File parentDir,
         public File createTempFile(final Project project, String prefix, String suffix,
                 final File parentDir, final boolean deleteOnExit, final boolean createFile) {
             File result;
    -        final String parent;
    +        String p = null;
             if (parentDir != null) {
    -            parent = parentDir.getPath();
    +            p = parentDir.getPath();
             } else if (project != null && project.getProperty(MagicNames.TMPDIR) != null) {
    -            parent = project.getProperty(MagicNames.TMPDIR);
    -        } else {
    -            parent = System.getProperty("java.io.tmpdir");
    +            p = project.getProperty(MagicNames.TMPDIR);
    +        } else if (project != null && deleteOnExit) {
    +            if (project.getProperty(MagicNames.AUTO_TMPDIR) != null) {
    +                p = project.getProperty(MagicNames.AUTO_TMPDIR);
    +            } else {
    +                final Path systemTempDirPath =
    +                    new File(System.getProperty("java.io.tmpdir")).toPath();
    +                final PosixFileAttributeView systemTempDirPosixAttributes =
    +                    Files.getFileAttributeView(systemTempDirPath, PosixFileAttributeView.class);
    +                if (systemTempDirPosixAttributes != null) {
    +                    // no reason to create an extra temp dir if we cannot set permissions
    +                    try {
    +                        final File projectTempDir = Files.createTempDirectory(systemTempDirPath,
    +                            "ant", TMPDIR_ATTRIBUTES)
    +                            .toFile();
    +                        projectTempDir.deleteOnExit();
    +                        p = projectTempDir.getAbsolutePath();
    +                        project.setProperty(MagicNames.AUTO_TMPDIR, p);
    +                    } catch (IOException ex) {
    +                        // silently fall back to system temp directory
    +                    }
    +                }
    +            }
             }
    +        final String parent = p != null ? p : System.getProperty("java.io.tmpdir");
             if (prefix == null) {
                 prefix = NULL_PLACEHOLDER;
             }
    
  • src/tests/junit/org/apache/tools/ant/util/FileUtilsTest.java+64 0 modified
    @@ -50,6 +50,8 @@
     import static org.junit.Assert.assertEquals;
     import static org.junit.Assert.assertFalse;
     import static org.junit.Assert.assertNotEquals;
    +import static org.junit.Assert.assertNotNull;
    +import static org.junit.Assert.assertNull;
     import static org.junit.Assert.assertThat;
     import static org.junit.Assert.assertTrue;
     import static org.junit.Assume.assumeFalse;
    @@ -450,6 +452,68 @@ public void testCreateTempFile() throws IOException {
                     tmp2.getAbsolutePath()));
         }
     
    +    @Test
    +    public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsTrue() throws IOException {
    +        final Project project = new Project();
    +        final File projectTmpDir = folder.newFolder("subdir");
    +        project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
    +        assertTrue(tmpFile + " must be child of " + projectTmpDir,
    +                   tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath()));
    +    }
    +
    +    @Test
    +    public void createTempFileUsesAntTmpDirIfSetAndDeleteOnExitIsFalse() throws IOException {
    +        final Project project = new Project();
    +        final File projectTmpDir = folder.newFolder("subdir");
    +        project.setProperty("ant.tmpdir", projectTmpDir.getAbsolutePath());
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true);
    +        assertTrue(tmpFile + " must be child of " + projectTmpDir,
    +                   tmpFile.getAbsolutePath().startsWith(projectTmpDir.getAbsolutePath()));
    +    }
    +
    +    @Test
    +    public void createTempFileCreatesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException {
    +        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
    +        final Project project = new Project();
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
    +        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
    +        assertNotNull(autoTempDir);
    +        assertTrue(tmpFile + " must be child of " + autoTempDir,
    +                   tmpFile.getAbsolutePath().startsWith(autoTempDir));
    +    }
    +
    +    @Test
    +    public void createTempFileDoesntCreateAutoTmpDirIfDeleteOnExitIsFalse() throws IOException {
    +        final Project project = new Project();
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, false, true);
    +        assertNull(project.getProperty("ant.auto.tmpdir"));
    +    }
    +
    +    @Test
    +    public void createTempFileReusesAutoTmpDirIfDeleteOnExitIsTrueOnUnix() throws IOException {
    +        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
    +        final Project project = new Project();
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
    +        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
    +        assertNotNull(autoTempDir);
    +        final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, true, true);
    +        assertTrue(tmpFile2 + " must be child of " + autoTempDir,
    +                   tmpFile2.getAbsolutePath().startsWith(autoTempDir));
    +    }
    +
    +    @Test
    +    public void createTempFileDoesntReusesAutoTmpDirIfDeleteOnExitIsFalse() throws IOException {
    +        assumeFalse("Test doesn't run on DOS", Os.isFamily("dos"));
    +        final Project project = new Project();
    +        final File tmpFile = getFileUtils().createTempFile(project, null, null, null, true, true);
    +        final String autoTempDir = project.getProperty("ant.auto.tmpdir");
    +        assertNotNull(autoTempDir);
    +        final File tmpFile2 = getFileUtils().createTempFile(project, null, null, null, false, true);
    +        assertFalse(tmpFile2 + " must not be child of " + autoTempDir,
    +                    tmpFile2.getAbsolutePath().startsWith(autoTempDir));
    +    }
    +
         /**
          * Test contentEquals
          */
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

32

News mentions

0

No linked articles in our index yet.