VYPR
Moderate severityNVD Advisory· Published Apr 6, 2022· Updated Aug 3, 2024

Insufficiently protected credentials

CVE-2022-26850

Description

When creating or updating credentials for single-user access, Apache NiFi wrote a copy of the Login Identity Providers configuration to the operating system temporary directory. On most platforms, the operating system temporary directory has global read permissions. NiFi immediately moved the temporary file to the final configuration directory, which significantly limited the window of opportunity for access. NiFi 1.16.0 includes updates to replace the Login Identity Providers configuration without writing a file to the operating system temporary directory.

AI Insight

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

Apache NiFi before 1.16.0 wrote Login Identity Providers config to a world-readable temporary directory during credential updates, risking information disclosure.

Vulnerability

Apache NiFi prior to version 1.16.0, when creating or updating credentials for single-user access, wrote a copy of the Login Identity Providers configuration to the operating system temporary directory, which typically has global read permissions on most platforms. The file was then moved immediately to the final configuration directory, but the temporary file remained briefly with world-readable permissions [1][2]. The vulnerability affects versions before 1.16.0.

Exploitation

An attacker with local access to the system could read the temporary file during the short window before it is moved. No authentication is required beyond local file system access. The attacker would need to monitor the temporary directory for new files and read the configuration before it is deleted (though the file is moved, not deleted, but the temporary file path is known). The race window is limited but exploitable if the attacker can continuously scan the directory [2][3].

Impact

Successful exploitation could lead to disclosure of the Login Identity Providers configuration, which may contain sensitive information such as usernames, password hashes, or other authentication-related data. This could allow an attacker to gain further access to the NiFi instance. The impact is limited to information disclosure, as the temporary file is removed after move [1][2].

Mitigation

The fix is included in Apache NiFi version 1.16.0, released March 2022, which rewrites the configuration without writing a temporary file to disk [1][3]. Users should upgrade to 1.16.0 or later. No workarounds are documented for earlier versions. This vulnerability is not listed on the CISA KEV at the time of this writing.

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.nifi:nifi-single-user-utilsMaven
< 1.161.16

Affected products

3

Patches

2
859d5fe8cfe0

NIFI-9785 Improved Login Credentials Writer File Handling

https://github.com/apache/nifiexceptionfactoryMar 10, 2022via ghsa
2 files changed · +35 19
  • nifi-commons/nifi-single-user-utils/src/main/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriter.java+18 19 modified
    @@ -29,26 +29,20 @@
     import javax.xml.stream.events.EndElement;
     import javax.xml.stream.events.StartElement;
     import javax.xml.stream.events.XMLEvent;
    +import java.io.ByteArrayInputStream;
     import java.io.File;
    -import java.io.FileInputStream;
     import java.io.FileOutputStream;
     import java.io.IOException;
     import java.io.InputStream;
     import java.io.OutputStream;
     import java.io.UncheckedIOException;
     import java.nio.file.Files;
    -import java.nio.file.StandardCopyOption;
     import java.util.Iterator;
     
     /**
      * Standard Login Credentials Writer updates Login Identity Providers Single User definition with Login Credentials
      */
     public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
    -
    -    private static final String PROVIDERS_PREFIX = "login-identity-providers-";
    -
    -    private static final String PROVIDERS_SUFFIX = ".xml";
    -
         private static final String CLASS_TAG = "class";
     
         private static final String PROVIDER_TAG = "provider";
    @@ -71,25 +65,30 @@ public StandardLoginCredentialsWriter(final File providersFile) {
     
         @Override
         public void writeLoginCredentials(final SingleUserCredentials singleUserCredentials) {
    -        try {
    -            final File updatedProvidersFile = File.createTempFile(PROVIDERS_PREFIX, PROVIDERS_SUFFIX);
    -            writeLoginCredentials(singleUserCredentials, updatedProvidersFile);
    -            Files.move(updatedProvidersFile.toPath(), providersFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
    +        final byte[] providers = readProviders();
    +        try (final InputStream providersInputStream = new ByteArrayInputStream(providers)) {
    +            writeLoginCredentials(singleUserCredentials, providersInputStream);
             } catch (final IOException e) {
                 throw new UncheckedIOException("Writing Login Identity Providers Failed", e);
             } catch (final XMLStreamException e) {
                 throw new RuntimeException("Processing Login Identity Providers Failed", e);
             }
         }
     
    -    private void writeLoginCredentials(final SingleUserCredentials singleUserCredentials, final File updatedProvidersFile) throws IOException, XMLStreamException {
    -        try (final OutputStream outputStream = new FileOutputStream(updatedProvidersFile)) {
    +    private byte[] readProviders() {
    +        try {
    +            return Files.readAllBytes(providersFile.toPath());
    +        } catch (final IOException e) {
    +            throw new UncheckedIOException("Reading Login Identity Providers Failed", e);
    +        }
    +    }
    +
    +    private void writeLoginCredentials(final SingleUserCredentials singleUserCredentials, final InputStream inputStream) throws IOException, XMLStreamException {
    +        try (final OutputStream outputStream = new FileOutputStream(providersFile)) {
                 final XMLEventWriter providersWriter = getProvidersWriter(outputStream);
    -            try (final InputStream inputStream = new FileInputStream(providersFile)) {
    -                final XMLEventReader providersReader = getProvidersReader(inputStream);
    -                updateLoginIdentityProviders(singleUserCredentials, providersReader, providersWriter);
    -                providersReader.close();
    -            }
    +            final XMLEventReader providersReader = getProvidersReader(inputStream);
    +            updateLoginIdentityProviders(singleUserCredentials, providersReader, providersWriter);
    +            providersReader.close();
                 providersWriter.close();
             }
         }
    @@ -131,7 +130,7 @@ private void updateLoginIdentityProviders(final SingleUserCredentials singleUser
          *
          * @param providersReader Providers Reader
          * @param providersWriter Providers Writer
    -     * @param propertyValue Property Value to be added
    +     * @param propertyValue   Property Value to be added
          * @throws XMLStreamException Thrown on XMLEventReader.nextEvent()
          */
         private void processProperty(final XMLEventReader providersReader, final XMLEventWriter providersWriter, final String propertyValue) throws XMLStreamException {
    
  • nifi-commons/nifi-single-user-utils/src/test/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriterTest.java+17 0 modified
    @@ -19,14 +19,18 @@
     import org.apache.nifi.authentication.single.user.SingleUserCredentials;
     import org.junit.jupiter.api.Test;
     
    +import java.io.File;
     import java.io.IOException;
    +import java.io.UncheckedIOException;
     import java.net.URISyntaxException;
     import java.nio.file.Files;
     import java.nio.file.Path;
     import java.nio.file.Paths;
     import java.nio.file.StandardCopyOption;
     import java.util.UUID;
     
    +import static org.junit.jupiter.api.Assertions.assertFalse;
    +import static org.junit.jupiter.api.Assertions.assertThrows;
     import static org.junit.jupiter.api.Assertions.assertTrue;
     
     public class StandardLoginCredentialsWriterTest {
    @@ -38,6 +42,19 @@ public class StandardLoginCredentialsWriterTest {
     
         private static final String PROVIDER_CLASS = SingleUserCredentials.class.getName();
     
    +    @Test
    +    public void testWriteLoginCredentialsProvidersNotFound() {
    +        final File providersNotFound = new File(UUID.randomUUID().toString());
    +        assertFalse(providersNotFound.exists());
    +
    +        final StandardLoginCredentialsWriter writer = new StandardLoginCredentialsWriter(providersNotFound);
    +
    +        final String username = UUID.randomUUID().toString();
    +        final String password = UUID.randomUUID().toString();
    +        final SingleUserCredentials credentials = new SingleUserCredentials(username, password, PROVIDER_CLASS);
    +        assertThrows(UncheckedIOException.class, () -> writer.writeLoginCredentials(credentials));
    +    }
    +
         @Test
         public void testWriteLoginCredentialsBlankProviders() throws IOException, URISyntaxException {
             final Path sourceProvidersPath = Paths.get(getClass().getResource(BLANK_PROVIDERS).toURI());
    
859d5fe

NIFI-9785 Improved Login Credentials Writer File Handling

https://github.com/apache/nifiexceptionfactoryMar 10, 2022via ghsa
2 files changed · +35 19
  • nifi-commons/nifi-single-user-utils/src/main/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriter.java+18 19 modified
    @@ -29,26 +29,20 @@
     import javax.xml.stream.events.EndElement;
     import javax.xml.stream.events.StartElement;
     import javax.xml.stream.events.XMLEvent;
    +import java.io.ByteArrayInputStream;
     import java.io.File;
    -import java.io.FileInputStream;
     import java.io.FileOutputStream;
     import java.io.IOException;
     import java.io.InputStream;
     import java.io.OutputStream;
     import java.io.UncheckedIOException;
     import java.nio.file.Files;
    -import java.nio.file.StandardCopyOption;
     import java.util.Iterator;
     
     /**
      * Standard Login Credentials Writer updates Login Identity Providers Single User definition with Login Credentials
      */
     public class StandardLoginCredentialsWriter implements LoginCredentialsWriter {
    -
    -    private static final String PROVIDERS_PREFIX = "login-identity-providers-";
    -
    -    private static final String PROVIDERS_SUFFIX = ".xml";
    -
         private static final String CLASS_TAG = "class";
     
         private static final String PROVIDER_TAG = "provider";
    @@ -71,25 +65,30 @@ public StandardLoginCredentialsWriter(final File providersFile) {
     
         @Override
         public void writeLoginCredentials(final SingleUserCredentials singleUserCredentials) {
    -        try {
    -            final File updatedProvidersFile = File.createTempFile(PROVIDERS_PREFIX, PROVIDERS_SUFFIX);
    -            writeLoginCredentials(singleUserCredentials, updatedProvidersFile);
    -            Files.move(updatedProvidersFile.toPath(), providersFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
    +        final byte[] providers = readProviders();
    +        try (final InputStream providersInputStream = new ByteArrayInputStream(providers)) {
    +            writeLoginCredentials(singleUserCredentials, providersInputStream);
             } catch (final IOException e) {
                 throw new UncheckedIOException("Writing Login Identity Providers Failed", e);
             } catch (final XMLStreamException e) {
                 throw new RuntimeException("Processing Login Identity Providers Failed", e);
             }
         }
     
    -    private void writeLoginCredentials(final SingleUserCredentials singleUserCredentials, final File updatedProvidersFile) throws IOException, XMLStreamException {
    -        try (final OutputStream outputStream = new FileOutputStream(updatedProvidersFile)) {
    +    private byte[] readProviders() {
    +        try {
    +            return Files.readAllBytes(providersFile.toPath());
    +        } catch (final IOException e) {
    +            throw new UncheckedIOException("Reading Login Identity Providers Failed", e);
    +        }
    +    }
    +
    +    private void writeLoginCredentials(final SingleUserCredentials singleUserCredentials, final InputStream inputStream) throws IOException, XMLStreamException {
    +        try (final OutputStream outputStream = new FileOutputStream(providersFile)) {
                 final XMLEventWriter providersWriter = getProvidersWriter(outputStream);
    -            try (final InputStream inputStream = new FileInputStream(providersFile)) {
    -                final XMLEventReader providersReader = getProvidersReader(inputStream);
    -                updateLoginIdentityProviders(singleUserCredentials, providersReader, providersWriter);
    -                providersReader.close();
    -            }
    +            final XMLEventReader providersReader = getProvidersReader(inputStream);
    +            updateLoginIdentityProviders(singleUserCredentials, providersReader, providersWriter);
    +            providersReader.close();
                 providersWriter.close();
             }
         }
    @@ -131,7 +130,7 @@ private void updateLoginIdentityProviders(final SingleUserCredentials singleUser
          *
          * @param providersReader Providers Reader
          * @param providersWriter Providers Writer
    -     * @param propertyValue Property Value to be added
    +     * @param propertyValue   Property Value to be added
          * @throws XMLStreamException Thrown on XMLEventReader.nextEvent()
          */
         private void processProperty(final XMLEventReader providersReader, final XMLEventWriter providersWriter, final String propertyValue) throws XMLStreamException {
    
  • nifi-commons/nifi-single-user-utils/src/test/java/org/apache/nifi/authentication/single/user/writer/StandardLoginCredentialsWriterTest.java+17 0 modified
    @@ -19,14 +19,18 @@
     import org.apache.nifi.authentication.single.user.SingleUserCredentials;
     import org.junit.jupiter.api.Test;
     
    +import java.io.File;
     import java.io.IOException;
    +import java.io.UncheckedIOException;
     import java.net.URISyntaxException;
     import java.nio.file.Files;
     import java.nio.file.Path;
     import java.nio.file.Paths;
     import java.nio.file.StandardCopyOption;
     import java.util.UUID;
     
    +import static org.junit.jupiter.api.Assertions.assertFalse;
    +import static org.junit.jupiter.api.Assertions.assertThrows;
     import static org.junit.jupiter.api.Assertions.assertTrue;
     
     public class StandardLoginCredentialsWriterTest {
    @@ -38,6 +42,19 @@ public class StandardLoginCredentialsWriterTest {
     
         private static final String PROVIDER_CLASS = SingleUserCredentials.class.getName();
     
    +    @Test
    +    public void testWriteLoginCredentialsProvidersNotFound() {
    +        final File providersNotFound = new File(UUID.randomUUID().toString());
    +        assertFalse(providersNotFound.exists());
    +
    +        final StandardLoginCredentialsWriter writer = new StandardLoginCredentialsWriter(providersNotFound);
    +
    +        final String username = UUID.randomUUID().toString();
    +        final String password = UUID.randomUUID().toString();
    +        final SingleUserCredentials credentials = new SingleUserCredentials(username, password, PROVIDER_CLASS);
    +        assertThrows(UncheckedIOException.class, () -> writer.writeLoginCredentials(credentials));
    +    }
    +
         @Test
         public void testWriteLoginCredentialsBlankProviders() throws IOException, URISyntaxException {
             final Path sourceProvidersPath = Paths.get(getClass().getResource(BLANK_PROVIDERS).toURI());
    

Vulnerability mechanics

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

References

7

News mentions

0

No linked articles in our index yet.