Using publicly writable directories such as /tmp to store temporary files exposes an application to race condition
vulnerabilities.
Why is this an issue?
Operating systems provide globally writable directories—such as /tmp on Linux or \Windows\Temp on Windows—where any user
can create, read, and modify files. When an application creates files in these directories with predictable names, it becomes vulnerable to race
conditions: an attacker can create a file with the same name before the application does, potentially causing the application to read or write
attacker-controlled content.
This rule raises an issue when it detects hard-coded paths to publicly writable directories, such as:
/tmp/var/tmp/usr/tmp/dev/shm/dev/mqueue/run/lock/var/run/lock/Library/Caches/Users/Shared/private/tmp/private/var/tmp\Windows\Temp\Temp\TMP%USERPROFILE%\AppData\Local\Temp
It also raises an issue when it detects reads of environment variables that point to publicly writable directories: TMP,
TMPDIR, and TEMP.
What is the potential impact?
Information disclosure
By winning the race condition, an attacker can access files written by the application to a publicly writable directory. If those files contain sensitive data—credentials, session tokens, or personal information—the attacker can read them before the application removes them.
Data tampering
An attacker can replace or modify a file before the application reads it, causing the application to process attacker-controlled content. This can result in data corruption, unexpected behavior, or indirect code execution. The risk is significantly higher when the application runs with elevated privileges.
How to fix it in .NET
Out of the box, .NET is missing secure-by-design APIs to create temporary files. To overcome this, one of the following options can be used:
- Use a dedicated sub-folder with tightly controlled permissions
- Created temporary files in a publicly writable folder and make sure:
- Generated filename is unpredictable
- File is readable and writable only by the creating user ID
- File descriptor is not inherited by child processes
- File is destroyed as soon as it is closed
Code examples
Noncompliant code example
Using Writer As New StreamWriter("/tmp/f") ' Noncompliant
' ...
End Using
Dim Tmp As String = Environment.GetEnvironmentVariable("TMP") ' Noncompliant
Compliant solution
Dim RandomPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())
' Creates a new file with write, non inheritable permissions which is deleted on close.
Using FileStream As New FileStream(RandomPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.DeleteOnClose)
Using Writer As New StreamWriter(FileStream)
' ...
End Using
End Using
Dim RandomPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName())
' Creates a new file with write, non inheritable permissions which is deleted on close.
Using FileStream As New FileStream(RandomPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.DeleteOnClose)
Using Writer As New StreamWriter(FileStream)
' ...
End Using
End Using
Resources
Articles & blog posts
Standards
- OWASP - Top 10 2021 Category A1 - Broken Access Control
- OWASP - Top 10 2017 Category A5 - Broken Access Control
- OWASP - Top 10 2017 Category A3 - Sensitive Data Exposure
- CWE - CWE-377 - Insecure Temporary File
- CWE - CWE-379 - Creation of Temporary File in Directory with Incorrect Permissions
- STIG Viewer - Application Security and Development: V-222567 - The application must not be vulnerable to race conditions.