Skip to content

Commit 3a722e8

Browse files
authored
docs: improve & expand security documentation (#317)
Alternative to #311 (this patch includes a few miscellaneous documentation fixes from that PR as well). The previous documentation didn't sufficiently cover permissions issues and mixed all the security concerns into a single section. This patch separates things out into separate sections and hopefully makes all this easier to understand. This patch also documents the DOS mitigation introduced in #314. I've also removed the link to the OWASP documentation to avoid confusing users (their documentation is mostly concerned with low-level C and platform-specific temporary file creation functions).
1 parent e7a40e3 commit 3a722e8

File tree

3 files changed

+69
-18
lines changed

3 files changed

+69
-18
lines changed

src/dir/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,20 @@ use crate::env;
2222

2323
/// Create a new temporary directory.
2424
///
25-
/// The `tempdir` function creates a directory in the file system
26-
/// and returns a [`TempDir`].
27-
/// The directory will be automatically deleted when the `TempDir`s
25+
/// The `tempdir` function creates a directory in the file system and returns a
26+
/// [`TempDir`]. The directory will be automatically deleted when the `TempDir`'s
2827
/// destructor is run.
2928
///
3029
/// # Resource Leaking
3130
///
3231
/// See [the resource leaking][resource-leaking] docs on `TempDir`.
3332
///
33+
/// # Security
34+
///
35+
/// Temporary directories are created with the default permissions unless otherwise
36+
/// specified via [`Builder::permissions`]. Depending on your platform, this may make
37+
/// them world-readable.
38+
///
3439
/// # Errors
3540
///
3641
/// If the directory can not be created, `Err` is returned.

src/env.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ static DEFAULT_TEMPDIR: OnceLock<PathBuf> = OnceLock::new();
88

99
/// Override the default temporary directory (defaults to [`std::env::temp_dir`]). This function
1010
/// changes the _global_ default temporary directory for the entire program and should not be called
11-
/// except in exceptional cases where it's not configured correctly by the platform.
11+
/// except in exceptional cases where it's not configured correctly by the platform. Applications
12+
/// should first check if the path returned by [`env::temp_dir`] is acceptable.
1213
///
1314
/// Only the first call to this function will succeed. All further calls will fail with `Err(path)`
1415
/// where `path` is previously set default temporary directory override.

src/lib.rs

+59-14
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,69 @@
1414
//!
1515
//! ## Resource Leaking
1616
//!
17-
//! `tempfile` will (almost) never fail to cleanup temporary resources. However `TempDir` and `NamedTempFile` will
18-
//! fail if their destructors don't run. This is because `tempfile` relies on the OS to cleanup the
19-
//! underlying file, while `TempDir` and `NamedTempFile` rely on rust destructors to do so.
20-
//! Destructors may fail to run if the process exits through an unhandled signal interrupt (like `SIGINT`),
21-
//! or if the instance is declared statically (like with [`lazy_static`]), among other possible
22-
//! reasons.
17+
//! `tempfile` will (almost) never fail to cleanup temporary resources. However `TempDir` and
18+
//! `NamedTempFile` will fail if their destructors don't run. This is because `tempfile` relies on
19+
//! the OS to cleanup the underlying file, while `TempDir` and `NamedTempFile` rely on rust
20+
//! destructors to do so. Destructors may fail to run if the process exits through an unhandled
21+
//! signal interrupt (like `SIGINT`), or if the instance is declared statically (like with
22+
//! [`lazy_static`]), among other possible reasons.
23+
//!
24+
//! ## Unexpected File Deletion
25+
//!
26+
//! Most operating systems periodically clean up temporary files that haven't been accessed recently
27+
//! (often on the order of multiple days). This issue does not affect unnamed temporary files but
28+
//! can invalidate the paths associated with named temporary files on Unix-like systems because the
29+
//! temporary file can be unlinked from the filesystem while still open and in-use. See the
30+
//! [temporary file cleaner](#temporary-file-cleaners) section for more security implications.
2331
//!
2432
//! ## Security
2533
//!
34+
//! This section discusses security issues relevant to Unix-like operating systems that use shared
35+
//! temporary directories by default. Importantly, it's not relevant for Windows or macOS as both
36+
//! operating systems use private per-user temporary directories by default.
37+
//!
38+
//! Applications can mitigate the issues described below by using [`env::override_temp_dir`] to
39+
//! change the default temporary directory but should do so if and only if default the temporary
40+
//! directory ([`env::temp_dir`]) is unsuitable (is world readable, world writable, managed by a
41+
//! temporary file cleaner, etc.).
42+
//!
43+
//! ### Temporary File Cleaners
44+
//!
2645
//! In the presence of pathological temporary file cleaner, relying on file paths is unsafe because
2746
//! a temporary file cleaner could delete the temporary file which an attacker could then replace.
2847
//!
29-
//! `tempfile` doesn't rely on file paths so this isn't an issue. However, `NamedTempFile` does
30-
//! rely on file paths for _some_ operations. See the security documentation on
31-
//! the `NamedTempFile` type for more information.
48+
//! This isn't an issue for [`tempfile`] as it doesn't rely on file paths. However, [`NamedTempFile`]
49+
//! and temporary directories _do_ rely on file paths for _some_ operations. See the security
50+
//! documentation on the [`NamedTempFile`] and the [`TempDir`] types for more information.
51+
//!
52+
//! Mitigation:
53+
//!
54+
//! - This is rarely an issue for short-lived files as temporary file cleaners usually only remove
55+
//! temporary files that haven't been modified or accessed within many (10-30) days.
56+
//! - Very long lived temporary files should be placed in directories not managed by temporary file
57+
//! cleaners.
58+
//!
59+
//! ### Access Permissions
60+
//!
61+
//! Temporary _files_ created with this library are private by default on all operating systems.
62+
//! However, temporary _directories_ are created with the default permissions and will therefore be
63+
//! world-readable by default unless the user has changed their umask and/or default temporary
64+
//! directory.
65+
//!
66+
//! ### Denial of Service
67+
//!
68+
//! If the file-name randomness ([`Builder::rand_bytes`]) is too small and/or this crate is built
69+
//! without the `getrandom` feature, it may be possible for an attacker to predict the random file
70+
//! names chosen by this library, preventing temporary file creation by creating temporary files
71+
//! with these predicted file names. By default, this library mitigates this denial of service
72+
//! attack by:
3273
//!
33-
//! The OWASP Foundation provides a resource on vulnerabilities concerning insecure
34-
//! temporary files: https://owasp.org/www-community/vulnerabilities/Insecure_Temporary_File
74+
//! 1. Defaulting to 6 random characters per temporary file forcing an attacker to create billions
75+
//! of files before random collisions are expected (at which point you probably have larger
76+
//! problems).
77+
//! 2. Re-seeding the random filename generator from system randomness after 3 failed attempts to
78+
//! create temporary a file (when the `getrandom` feature is enabled as it is by default on all
79+
//! major platforms).
3580
//!
3681
//! ## Early drop pitfall
3782
//!
@@ -172,7 +217,7 @@ pub use crate::file::{
172217
};
173218
pub use crate::spooled::{spooled_tempfile, SpooledData, SpooledTempFile};
174219

175-
/// Create a new temporary file or directory with custom parameters.
220+
/// Create a new temporary file or directory with custom options.
176221
#[derive(Debug, Clone, Eq, PartialEq)]
177222
pub struct Builder<'a, 'b> {
178223
random_len: usize,
@@ -349,7 +394,7 @@ impl<'a, 'b> Builder<'a, 'b> {
349394
///
350395
/// # Security
351396
///
352-
/// By default, the permissions of tempfiles on unix are set for it to be
397+
/// By default, the permissions of tempfiles on Unix are set for it to be
353398
/// readable and writable by the owner only, yielding the greatest amount
354399
/// of security.
355400
/// As this method allows to widen the permissions, security would be
@@ -369,7 +414,7 @@ impl<'a, 'b> Builder<'a, 'b> {
369414
/// ## Windows and others
370415
///
371416
/// This setting is unsupported and trying to set a file or directory read-only
372-
/// will cause an error to be returned..
417+
/// will return an error.
373418
///
374419
/// # Examples
375420
///

0 commit comments

Comments
 (0)