CVE-2022-21126 (Java, published 2022-11-29T17:15Z)
Description: value: The package com.github.samtools:htsjdk before 3.0.1 are vulnerable to Creation of Temporary File in Directory with Insecure Permissions due to the createTempDir() function in util/IOUtil.java not checking for the existence of the temporary directory before attempting to create it.
Severity: nan (CVSS v3 base score: 7.8)
Weakness: CWE-668 \u2014 Exposure of Resource to Wrong Sphere
The product exposes a resource to the wrong control sphere, providing unintended actors with inappropriate access to the resource.
Repository: https://github.com/samtools/htsjdk
Files changed:
src/main/java/htsjdk/samtools/CoordinateSortedPairInfoMap.java
src/main/java/htsjdk/samtools/util/IOUtil.java
src/test/java/htsjdk/samtools/BAMMergerTest.java
src/test/java/htsjdk/samtools/CRAMFileWriterTest.java
src/test/java/htsjdk/samtools/CRAMMergerTest.java
src/test/java/htsjdk/samtools/reference/FastaSequenceIndexCreatorTest.java
src/test/java/htsjdk/samtools/seekablestream/SeekableStreamFactoryTest.java
src/test/java/htsjdk/samtools/util/IOUtilTest.java
src/test/java/htsjdk/tribble/index/IndexFactoryTest.java
src/test/java/htsjdk/tribble/index/IndexTest.java
src/test/java/htsjdk/tribble/index/tabix/TabixIndexTest.java
src/test/java/htsjdk/variant/vcf/VCFFileReaderTest.java
src/test/java/htsjdk/variant/vcf/VCFMergerTest.java
Commit message: Fix temporary directory hijacking or temporary directory information disclosure (#1621)

This replaces and closes #1617.

Fix a vulnerability which allows a malicious user access files created in a temp directory if it was created using IOUtils.createTempDir.  
The implementation has been changed to use the more secure Files.createTemporaryDirectory(). This has a side effect of making the second "suffix" argument no longer usable and it is now simply appended to the existing prefix.  
Deprecating IOUtils.createTempDir(String, String) and adding a new single argument version instead which returns a Path.

This potentially exposed data created by CoordinateSortedPairInfoMaps on shared systems to a malicious users with access to the global temp directory.  

It is recommended that user upgrade if they use CoordinateSortedPairInfoMap or IOUTils.createTempDir() in their code.

* vuln-fix: Temporary Directory Hijacking or Information Disclosure

This fixes either Temporary Directory Hijacking, or Temporary Directory Local Information Disclosure.

Weakness: CWE-379: Creation of Temporary File in Directory with Insecure Permissions
Severity: High
CVSSS: 7.3
Detection: CodeQL & OpenRewrite (https://public.moderne.io/recipes/org.openrewrite.java.security.UseFilesCreateTempDirectory)

Reported-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>

Bug-tracker: https://github.com/JLLeitschuh/security-research/issues/10

Co-authored-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
Co-authored-by: Moderne <team@moderne.io>

Vulnerable code:
    private final File workDir = IOUtil.createTempDir("CSPI.", null);
     * Create a temporary subdirectory in the default temporary-file directory, using the given prefix and suffix to generate the name.
     * @param prefix The prefix string to be used in generating the file's name; must be at least three characters long
     * @param suffix The suffix string to be used in generating the file's name; may be null, in which case the suffix ".tmp" will be used
    public static File createTempDir(final String prefix, final String suffix) {
            final File tmp = File.createTempFile(prefix, suffix);
            if (!tmp.delete()) {
                throw new SAMException("Could not delete temporary file " + tmp);
            }
            if (!tmp.mkdir()) {
                throw new SAMException("Could not create temporary directory " + tmp);
            }
            return tmp;
        } catch (IOException e) {
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".", ".tmp").toPath();
        final File outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".", ".tmp");
        final Path fastaDir = IOUtil.createTempDir("CRAMFileWriterTest", "").toPath();
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".", ".tmp").toPath();
        final File tempDir = IOUtil.createTempDir("FastaSequenceIndexCreatorTest", "testCreate");
        final File tempDir = IOUtil.createTempDir("test spaces", "");
        final File tmpDir = IOUtil.createTempDir("testDeletePath", "");
        final File tmpDir = IOUtil.createTempDir("testDeletePath", "");
    private static List<Path> createLocalFiles(final File tmpDir, final List<String> fileNames) throws Exception {
            final File file = new File(tmpDir, f);
            Assert.assertTrue(file.createNewFile(), "failed to create test file" +file);
            paths.add(file.toPath());
        final File tempDir = IOUtil.createTempDir("testCreateTabixIndexFromVCF", null);
        final File tempDir = IOUtil.createTempDir("testCreateIndexFromBCF", null);
        final File dir = IOUtil.createTempDir("redirec-test", "dir");
        final File tmpFolder = IOUtil.createTempDir("NonRegultarFeatureFile", null);
        final File tempDir = IOUtil.createTempDir("testBedTabixIndex", null);
        final File tempDir = IOUtil.createTempDir("test spaces", "");
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".", ".tmp").toPath();

Fixed code:
    private final File workDir = IOUtil.createTempDir("CSPI.tmp").toFile();
     * Create a temporary subdirectory in the default temporary-file directory, using the given prefix and morePrefix to generate the name.
     * This has been updated to avoid the problem in https://github.com/samtools/htsjdk/pull/1617
     *
     * @param prefix The prefix string to be used in generating the file's name;
     * @param morePrefix This was previously a suffix but the implementation changed; may be null, in which case the morePrefix ".tmp" will be used
     * @deprecated  Use {@link #createTempDir(String)} instead.
     *              It turns out the mechanism was not "good enough" and caused security issues, the new implementation
     *              combines the prefix/morePrefix into a single prefix.  The security flaw is fixed but due to the now
     *              extraneous morePrefix argument it is recommended to use the 1 argument form.
     */
    @Deprecated
    public static File createTempDir(final String prefix, final String morePrefix) {
        final String dotSeparatedSuffix = morePrefix == null ? ".tmp" : morePrefix.startsWith(".") ? morePrefix : "." + morePrefix;
        return createTempDir(prefix + dotSeparatedSuffix).toFile() ;
    }

    /*
     * Create a temporary subdirectory in the default temporary-file directory, using the given prefix and suffix to generate the name.
     * @param prefix The prefix string to be used in generating the file's name, may be null
    public static Path createTempDir(final String prefix) {
            return Files.createTempDirectory(prefix);
        } catch (final IOException e) {
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".tmp");
        final File outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".tmp").toFile();
        final Path fastaDir = IOUtil.createTempDir("CRAMFileWriterTest");
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".tmp");
        final File tempDir = IOUtil.createTempDir("FastaSequenceIndexCreatorTest.testCreate").toFile();
        final File tempDir = IOUtil.createTempDir("test spaces").toFile();
        final Path tmpDir = IOUtil.createTempDir("testDeletePath");
        final Path tmpDir = IOUtil.createTempDir("testDeletePath");
    private static List<Path> createLocalFiles(final Path tmpDir, final List<String> fileNames) throws Exception {
            final Path file = Files.createFile(tmpDir.resolve(f));
            paths.add(file);
        final File tempDir = IOUtil.createTempDir("testCreateTabixIndexFromVCF").toFile();
        final File tempDir = IOUtil.createTempDir("testCreateIndexFromBCF").toFile();
        final File dir = IOUtil.createTempDir("redirec-test.dir").toFile();
        final File tmpFolder = IOUtil.createTempDir("NonRegultarFeatureFile").toFile();
        final File tempDir = IOUtil.createTempDir("testBedTabixIndex.tmp").toFile();
        final File tempDir = IOUtil.createTempDir("test spaces").toFile();
        final Path outputDir = IOUtil.createTempDir(this.getClass().getSimpleName() + ".tmp");