VYPR
Moderate severityNVD Advisory· Published Feb 8, 2021· Updated Aug 3, 2024

Local Information Disclosure Vulnerability in Netty on Unix-Like systems due temporary files

CVE-2021-21290

Description

Netty is an open-source, asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. In Netty before version 4.1.59.Final there is a vulnerability on Unix-like systems involving an insecure temp file. When netty's multipart decoders are used local information disclosure can occur via the local system temporary directory if temporary storing uploads on the disk is enabled. On unix-like systems, the temporary directory is shared between all user. As such, writing to this directory using APIs that do not explicitly set the file/directory permissions can lead to information disclosure. Of note, this does not impact modern MacOS Operating Systems. The method "File.createTempFile" on unix-like systems creates a random file, but, by default will create this file with the permissions "-rw-r--r--". Thus, if sensitive information is written to this file, other local users can read this information. This is the case in netty's "AbstractDiskHttpData" is vulnerable. This has been fixed in version 4.1.59.Final. As a workaround, one may specify your own "java.io.tmpdir" when you start the JVM or use "DefaultHttpDataFactory.setBaseDir(...)" to set the directory to something that is only readable by the current user.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
io.netty:netty-codec-httpMaven
>= 4.0.0, < 4.1.59.Final4.1.59.Final
org.jboss.netty:nettyMaven
>= 0
io.netty:nettyMaven
>= 0

Affected products

1

Patches

1
c735357bf29d

Use Files.createTempFile(...) to ensure the file is created with proper permissions

https://github.com/netty/nettyNorman MaurerFeb 8, 2021via ghsa
16 files changed · +47 20
  • buffer/src/test/java/io/netty/buffer/AbstractByteBufTest.java+2 2 modified
    @@ -4551,7 +4551,7 @@ private void testGetReadOnlyDst(boolean direct) {
     
         @Test
         public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
    -        File file = File.createTempFile("file-channel", ".tmp");
    +        File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
             RandomAccessFile randomAccessFile = null;
             try {
                 randomAccessFile = new RandomAccessFile(file, "rw");
    @@ -4594,7 +4594,7 @@ public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
     
         @Test
         public void testGetBytesAndSetBytesWithFileChannel() throws IOException {
    -        File file = File.createTempFile("file-channel", ".tmp");
    +        File file = PlatformDependent.createTempFile("file-channel", ".tmp", null);
             RandomAccessFile randomAccessFile = null;
             try {
                 randomAccessFile = new RandomAccessFile(file, "rw");
    
  • buffer/src/test/java/io/netty/buffer/ReadOnlyDirectByteBufferBufTest.java+1 1 modified
    @@ -306,7 +306,7 @@ public void testWrapBufferRoundTrip() {
     
         @Test
         public void testWrapMemoryMapped() throws Exception {
    -        File file = File.createTempFile("netty-test", "tmp");
    +        File file = PlatformDependent.createTempFile("netty-test", "tmp", null);
             FileChannel output = null;
             FileChannel input = null;
             ByteBuf b1 = null;
    
  • codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpData.java+3 2 modified
    @@ -19,6 +19,7 @@
     import io.netty.handler.codec.http.HttpConstants;
     import io.netty.util.internal.EmptyArrays;
     import io.netty.util.internal.ObjectUtil;
    +import io.netty.util.internal.PlatformDependent;
     import io.netty.util.internal.logging.InternalLogger;
     import io.netty.util.internal.logging.InternalLoggerFactory;
     
    @@ -88,9 +89,9 @@ private File tempFile() throws IOException {
             File tmpFile;
             if (getBaseDirectory() == null) {
                 // create a temporary file
    -            tmpFile = File.createTempFile(getPrefix(), newpostfix);
    +            tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, null);
             } else {
    -            tmpFile = File.createTempFile(getPrefix(), newpostfix, new File(
    +            tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, new File(
                         getBaseDirectory()));
             }
             if (deleteOnExit()) {
    
  • codec-http/src/test/java/io/netty/handler/codec/http/HttpChunkedInputTest.java+2 1 modified
    @@ -25,6 +25,7 @@
     import io.netty.handler.stream.ChunkedNioStream;
     import io.netty.handler.stream.ChunkedStream;
     import io.netty.handler.stream.ChunkedWriteHandler;
    +import io.netty.util.internal.PlatformDependent;
     import org.junit.Test;
     
     import java.io.ByteArrayInputStream;
    @@ -46,7 +47,7 @@ public class HttpChunkedInputTest {
     
             FileOutputStream out = null;
             try {
    -            TMP = File.createTempFile("netty-chunk-", ".tmp");
    +            TMP = PlatformDependent.createTempFile("netty-chunk-", ".tmp", null);
                 TMP.deleteOnExit();
                 out = new FileOutputStream(TMP);
                 out.write(BYTES);
    
  • codec-http/src/test/java/io/netty/handler/codec/http/multipart/AbstractDiskHttpDataTest.java+1 1 modified
    @@ -39,7 +39,7 @@ public class AbstractDiskHttpDataTest {
         public void testGetChunk() throws Exception {
             TestHttpData test = new TestHttpData("test", UTF_8, 0);
             try {
    -            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
    +            File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
                 tmpFile.deleteOnExit();
                 FileOutputStream fos = new FileOutputStream(tmpFile);
                 byte[] bytes = new byte[4096];
    
  • codec-http/src/test/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpDataTest.java+2 2 modified
    @@ -43,7 +43,7 @@ public class AbstractMemoryHttpDataTest {
         public void testSetContentFromFile() throws Exception {
             TestHttpData test = new TestHttpData("test", UTF_8, 0);
             try {
    -            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
    +            File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
                 tmpFile.deleteOnExit();
                 FileOutputStream fos = new FileOutputStream(tmpFile);
                 byte[] bytes = new byte[4096];
    @@ -70,7 +70,7 @@ public void testSetContentFromFile() throws Exception {
         public void testRenameTo() throws Exception {
             TestHttpData test = new TestHttpData("test", UTF_8, 0);
             try {
    -            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
    +            File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
                 tmpFile.deleteOnExit();
                 final int totalByteCount = 4096;
                 byte[] bytes = new byte[totalByteCount];
    
  • codec-http/src/test/java/io/netty/handler/codec/http/multipart/DiskFileUploadTest.java+1 1 modified
    @@ -273,7 +273,7 @@ public void setSetContentFromFileExceptionally() throws Exception {
                 assertEquals(maxSize, f1.length());
                 byte[] bytes = new byte[8];
                 PlatformDependent.threadLocalRandom().nextBytes(bytes);
    -            File tmpFile = File.createTempFile(UUID.randomUUID().toString(), ".tmp");
    +            File tmpFile = PlatformDependent.createTempFile(UUID.randomUUID().toString(), ".tmp", null);
                 tmpFile.deleteOnExit();
                 FileOutputStream fos = new FileOutputStream(tmpFile);
                 try {
    
  • common/src/main/java/io/netty/util/internal/NativeLibraryLoader.java+1 1 modified
    @@ -177,7 +177,7 @@ public static void load(String originalName, ClassLoader loader) {
                 String prefix = libname.substring(0, index);
                 String suffix = libname.substring(index);
     
    -            tmpFile = File.createTempFile(prefix, suffix, WORKDIR);
    +            tmpFile = PlatformDependent.createTempFile(prefix, suffix, WORKDIR);
                 in = url.openStream();
                 out = new FileOutputStream(tmpFile);
     
    
  • common/src/main/java/io/netty/util/internal/PlatformDependent.java+19 0 modified
    @@ -38,6 +38,7 @@
     import java.lang.reflect.Method;
     import java.nio.ByteBuffer;
     import java.nio.ByteOrder;
    +import java.nio.file.Files;
     import java.security.AccessController;
     import java.security.PrivilegedAction;
     import java.util.Arrays;
    @@ -1389,6 +1390,24 @@ public static Set<String> normalizedLinuxClassifiers() {
             return LINUX_OS_CLASSIFIERS;
         }
     
    +    @SuppressJava6Requirement(reason = "Guarded by version check")
    +    public static File createTempFile(String prefix, String suffix, File directory) throws IOException {
    +        if (javaVersion() >= 7) {
    +            if (directory == null) {
    +                return Files.createTempFile(prefix, suffix).toFile();
    +            }
    +            return Files.createTempFile(directory.toPath(), prefix, suffix).toFile();
    +        }
    +        if (directory == null) {
    +            return File.createTempFile(prefix, suffix);
    +        }
    +        File file = File.createTempFile(prefix, suffix, directory);
    +        // Try to adjust the perms, if this fails there is not much else we can do...
    +        file.setReadable(false, false);
    +        file.setReadable(true, true);
    +        return file;
    +    }
    +
         /**
          * Adds only those classifier strings to <tt>dest</tt> which are present in <tt>allowed</tt>.
          *
    
  • handler/src/main/java/io/netty/handler/ssl/util/SelfSignedCertificate.java+4 2 modified
    @@ -20,6 +20,7 @@
     import io.netty.buffer.Unpooled;
     import io.netty.handler.codec.base64.Base64;
     import io.netty.util.CharsetUtil;
    +import io.netty.util.internal.PlatformDependent;
     import io.netty.util.internal.SystemPropertyUtil;
     import io.netty.util.internal.ThrowableUtil;
     import io.netty.util.internal.logging.InternalLogger;
    @@ -30,6 +31,7 @@
     import java.io.FileOutputStream;
     import java.io.IOException;
     import java.io.OutputStream;
    +import java.nio.file.Files;
     import java.security.KeyPair;
     import java.security.KeyPairGenerator;
     import java.security.NoSuchAlgorithmException;
    @@ -330,7 +332,7 @@ static String[] newSelfSignedCertificate(
                 wrappedBuf.release();
             }
     
    -        File keyFile = File.createTempFile("keyutil_" + fqdn + '_', ".key");
    +        File keyFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".key", null);
             keyFile.deleteOnExit();
     
             OutputStream keyOut = new FileOutputStream(keyFile);
    @@ -361,7 +363,7 @@ static String[] newSelfSignedCertificate(
                 wrappedBuf.release();
             }
     
    -        File certFile = File.createTempFile("keyutil_" + fqdn + '_', ".crt");
    +        File certFile = PlatformDependent.createTempFile("keyutil_" + fqdn + '_', ".crt", null);
             certFile.deleteOnExit();
     
             OutputStream certOut = new FileOutputStream(certFile);
    
  • handler/src/test/java/io/netty/handler/stream/ChunkedWriteHandlerTest.java+2 1 modified
    @@ -26,6 +26,7 @@
     import io.netty.channel.embedded.EmbeddedChannel;
     import io.netty.util.CharsetUtil;
     import io.netty.util.ReferenceCountUtil;
    +import io.netty.util.internal.PlatformDependent;
     import org.junit.Assert;
     import org.junit.Test;
     
    @@ -55,7 +56,7 @@ public class ChunkedWriteHandlerTest {
     
             FileOutputStream out = null;
             try {
    -            TMP = File.createTempFile("netty-chunk-", ".tmp");
    +            TMP = PlatformDependent.createTempFile("netty-chunk-", ".tmp", null);
                 TMP.deleteOnExit();
                 out = new FileOutputStream(TMP);
                 out.write(BYTES);
    
  • handler/src/test/java/io/netty/handler/traffic/FileRegionThrottleTest.java+2 1 modified
    @@ -32,6 +32,7 @@
     import io.netty.channel.socket.nio.NioSocketChannel;
     import io.netty.handler.codec.LineBasedFrameDecoder;
     import io.netty.util.CharsetUtil;
    +import io.netty.util.internal.PlatformDependent;
     import org.junit.After;
     import org.junit.Before;
     import org.junit.BeforeClass;
    @@ -61,7 +62,7 @@ public static void beforeClass() throws IOException {
                 BYTES[i] = (byte) r.nextInt(255);
             }
     
    -        tmp = File.createTempFile("netty-traffic", ".tmp");
    +        tmp = PlatformDependent.createTempFile("netty-traffic", ".tmp", null);
             tmp.deleteOnExit();
             FileOutputStream out = null;
             try {
    
  • testsuite/src/main/java/io/netty/testsuite/transport/socket/SocketFileRegionTest.java+2 2 modified
    @@ -102,7 +102,7 @@ public void testFileRegionVoidPromiseNotAutoRead(ServerBootstrap sb, Bootstrap c
         }
     
         public void testFileRegionCountLargerThenFile(ServerBootstrap sb, Bootstrap cb) throws Throwable {
    -        File file = File.createTempFile("netty-", ".tmp");
    +        File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
             file.deleteOnExit();
     
             final FileOutputStream out = new FileOutputStream(file);
    @@ -136,7 +136,7 @@ private static void testFileRegion0(
             cb.option(ChannelOption.AUTO_READ, autoRead);
     
             final int bufferSize = 1024;
    -        final File file = File.createTempFile("netty-", ".tmp");
    +        final File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
             file.deleteOnExit();
     
             final FileOutputStream out = new FileOutputStream(file);
    
  • transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSpliceTest.java+2 1 modified
    @@ -28,6 +28,7 @@
     import io.netty.channel.SimpleChannelInboundHandler;
     import io.netty.channel.unix.FileDescriptor;
     import io.netty.util.NetUtil;
    +import io.netty.util.internal.PlatformDependent;
     import org.junit.Assert;
     import org.junit.Test;
     
    @@ -192,7 +193,7 @@ public void operationComplete(ChannelFuture future) throws Exception {
         @Test(timeout = 10000)
         public void spliceToFile() throws Throwable {
             EventLoopGroup group = new EpollEventLoopGroup(1);
    -        File file = File.createTempFile("netty-splice", null);
    +        File file = PlatformDependent.createTempFile("netty-splice", null, null);
             file.deleteOnExit();
     
             SpliceHandler sh = new SpliceHandler(file);
    
  • transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/UnixTestUtils.java+2 1 modified
    @@ -17,6 +17,7 @@
     
     import io.netty.channel.unix.DomainSocketAddress;
     import io.netty.channel.unix.Socket;
    +import io.netty.util.internal.PlatformDependent;
     
     import java.io.File;
     import java.io.IOException;
    @@ -26,7 +27,7 @@ public static DomainSocketAddress newSocketAddress() {
             try {
                 File file;
                 do {
    -                file = File.createTempFile("NETTY", "UDS");
    +                file = PlatformDependent.createTempFile("NETTY", "UDS", null);
                     if (!file.delete()) {
                         throw new IOException("failed to delete: " + file);
                     }
    
  • transport/src/test/java/io/netty/channel/DefaultFileRegionTest.java+1 1 modified
    @@ -39,7 +39,7 @@ public class DefaultFileRegionTest {
         }
     
         private static File newFile() throws IOException {
    -        File file = File.createTempFile("netty-", ".tmp");
    +        File file = PlatformDependent.createTempFile("netty-", ".tmp", null);
             file.deleteOnExit();
     
             final FileOutputStream out = new FileOutputStream(file);
    

Vulnerability mechanics

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

References

72

News mentions

0

No linked articles in our index yet.