#logging #privacy #arti #tor #debugging

safelog

Conditionally suppress confidential information from logs

19 releases

new 0.4.2 Dec 2, 2024
0.4.1 Oct 31, 2024
0.4.0 Sep 30, 2024
0.3.7 Jun 5, 2024
0.1.1 Jun 24, 2022

#344 in Rust patterns

Download history 1523/week @ 2024-08-17 2043/week @ 2024-08-24 2371/week @ 2024-08-31 1993/week @ 2024-09-07 1463/week @ 2024-09-14 1636/week @ 2024-09-21 1909/week @ 2024-09-28 1486/week @ 2024-10-05 1386/week @ 2024-10-12 1688/week @ 2024-10-19 1934/week @ 2024-10-26 2762/week @ 2024-11-02 1500/week @ 2024-11-09 2852/week @ 2024-11-16 2147/week @ 2024-11-23 2710/week @ 2024-11-30

9,506 downloads per month
Used in 59 crates (20 directly)

MIT/Apache

36KB
632 lines

safelog

Mark data as sensitive for logging purposes.

Some information is too sensitive to routinely write to system logs, but must nonetheless sometimes be displayed. This crate provides a way to mark such information, and log it conditionally, but not by default.

Examples

There are two main ways to mark a piece of data as sensitive: by storing it within a Sensitive object long-term, or by wrapping it in a Sensitive object right before passing it to a formatter:

use safelog::{Sensitive, sensitive};

// With this declaration, a student's name and gpa will be suppressed by default
// when passing the student to Debug.
#[derive(Debug)]
struct Student {
   name: Sensitive<String>,
   grade: u8,
   homeroom: String,
   gpa: Sensitive<f32>,
}

// In this function, a user's IP will not be printed by default.
fn record_login(username: &str, ip: &std::net::IpAddr) {
    println!("Login from {} at {}", username, sensitive(ip));
}

You can disable safe-logging globally (across all threads) or locally (across a single thread).

# let debug_mode = true;
# let log_encrypted_data = |_|();
# let big_secret = ();
use safelog::{disable_safe_logging, with_safe_logging_suppressed};

// If we're running in debug mode, turn off safe logging
// globally.  Safe logging will remain disabled until the
// guard object is dropped.
let guard = if debug_mode {
   // This call can fail if safe logging has already been enforced.
   disable_safe_logging().ok()
} else {
   None
};

// If we know that it's safe to record sensitive data with a given API,
// we can disable safe logging temporarily. This affects only the current thread.
with_safe_logging_suppressed(|| log_encrypted_data(big_secret));

An example deployment

This crate was originally created for use in the arti project, which tries to implements the Tor anonymity protocol in Rust. In arti, we want to avoid logging information by default if it could compromise users' anonymity, or create an incentive for attacking users and relays in order to access their logs.

In general, Arti treats the following information as Sensitive:

  • Client addresses.
  • The destinations (target addresses) of client requests.

Arti does not label all private information as Sensitive: when information isn't ever suitable for logging, we omit it entirely.

License: MIT OR Apache-2.0

Dependencies

~0.8–1.5MB
~31K SLoC