mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-31 21:27:00 -06:00
Security: private temp paths for the signing certificate and test output; web font licences stay inside the checkout (#3871)
* Audit: private temp paths for the signing certificate and testkit output; confine web font licences to the checkout * testkit: refuse a pre-made private temp directory this user cannot write to
This commit is contained in:
@@ -39,10 +39,24 @@ pub use vectorcraft_engine::{Session, doc::NodeId};
|
||||
/// Re-exports so dependents without direct dependencies (e.g. app test crates) can use them.
|
||||
pub use {vectorcraft_doc as doc, vectorcraft_format as format, vectorcraft_render as render, vectorcraft_svg as svg};
|
||||
|
||||
/// A per-process temporary directory for test output (created on first use).
|
||||
/// A per-process temporary directory for test output (created on first use). It is made with
|
||||
/// `create_dir` (owner-only on Unix), and a directory that already exists is reused only when it is a
|
||||
/// real directory, not a link, with no access for others and writable by this user: one pre-made in a shared temp folder is refused.
|
||||
pub fn temp_dir(tag: &str) -> std::path::PathBuf {
|
||||
let dir = std::env::temp_dir().join(format!("vectorcraft-testkit-{tag}-{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).expect("create temp dir");
|
||||
let mut b = std::fs::DirBuilder::new();
|
||||
#[cfg(unix)]
|
||||
std::os::unix::fs::DirBuilderExt::mode(&mut b, 0o700);
|
||||
if let Err(e) = b.create(&dir) {
|
||||
let m = std::fs::symlink_metadata(&dir).expect("temp dir");
|
||||
assert!(e.kind() == std::io::ErrorKind::AlreadyExists && m.is_dir(), "create temp dir: {e}");
|
||||
#[cfg(unix)]
|
||||
assert!(std::os::unix::fs::PermissionsExt::mode(&m.permissions()) & 0o077 == 0, "{}: not private", dir.display());
|
||||
// A private directory made by another user passes the mode check but is closed to this one:
|
||||
// writing a probe file tells it apart from ours without needing the user ids.
|
||||
let probe = dir.join(".probe");
|
||||
assert!(std::fs::write(&probe, b"").and_then(|()| std::fs::remove_file(&probe)).is_ok(), "{}: not owned by this user", dir.display());
|
||||
}
|
||||
dir
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user