Qubit Sanitize
Reusable sanitization utilities for Rust.
Overview
Qubit Sanitize provides reusable tools for masking sensitive data in logs,
diagnostics, and structured debug output. The core layer handles the common
field-value problem shared by HTTP clients, command runners, configuration
objects, and other crates: given a (field, value) pair, decide whether the
field is sensitive and return the safe value to display.
The adapter layer builds on that core policy for common structured inputs such as URLs, URL-encoded forms, HTTP headers, HTTP bodies, argv vectors, and environment variables. Adapters parse only the formats they explicitly model; shell command strings and other application-specific protocols should still be handled by caller crates that have the full context.
Features
- Field-name canonicalization for separator-insensitive matching
- Built-in sensitive field defaults for credentials, tokens, HTTP auth, cookies, and sessions
- Configurable sensitivity levels:
Low,Medium,High, andSecret - Level-specific masking through
MaskPolicies - Mask strategies for fixed replacement, edge preservation, suffix preservation, and full removal
- A
FieldSanitizerobject that sanitizes single field-value pairs - Convenience helpers for sanitizing
BTreeMap<String, String>values by key - Adapters for URLs, URL-encoded forms, HTTP headers, HTTP bodies, argv vectors, and environment variables
Quick Start
use ;
let sanitizer = default;
assert_eq!;
assert_eq!;
Sensitivity Levels
Sensitive fields are assigned one of four levels:
| Level | Intended use | Default mask |
|---|---|---|
Low |
Values where a small prefix and suffix help diagnostics | ab****yz |
Medium |
Identifiers where only the tail should remain visible | ****z |
High |
Tokens or API keys that should not expose edges | **** |
Secret |
Passwords, private keys, or client secrets | <redacted> |
The defaults are conservative for operational logs. You can replace any level's
masking strategy through MaskPolicies.
Mask Policies
use MaskPolicy;
let edge = preserve_edges;
assert_eq!;
let suffix = preserve_suffix;
assert_eq!;
let fixed = fixed;
assert_eq!;
Empty values are kept empty. This avoids changing the semantics of fields that are present but intentionally blank.
Sensitive Fields
SensitiveFields::default() contains common sensitive names such as:
password,passwd,secret,client_secret,private_keyapi_key,x_api_keytoken,access_token,refresh_token,id_tokenauthorization,proxy_authorization,cookie,set_cookiesession,session_id,session_token
Field names are canonicalized before lookup. Separators such as _, -, .,
and whitespace are ignored, and names are lowercased:
use canonicalize_field_name;
assert_eq!;
assert_eq!;
assert_eq!;
Name Matching Modes
Core methods such as sanitize_value and sanitize_map require callers to
choose a field-name matching mode. Use NameMatchMode::Exact for exact
canonical field-name matching. For contextual names where callers want
OPENAI_API_KEY to match the configured field api_key, use
NameMatchMode::ExactOrSuffix.
use ;
let sanitizer = default;
assert_eq!;
assert_eq!;
Custom Fields
use ;
let mut sanitizer = default;
sanitizer.insert_sensitive_field;
assert_eq!;
You can also start from an empty policy when you do not want built-in field names:
use ;
let mut sanitizer = new;
sanitizer.insert_sensitive_field;
Map Sanitization
use BTreeMap;
use ;
let sanitizer = default;
let mut values = new;
values.insert;
values.insert;
let sanitized = sanitizer.sanitize_map;
assert_eq!;
assert_eq!;
assert_eq!;
For mutable structured data, use sanitize_map_in_place with an explicit
NameMatchMode.
Adapter Sanitization
use ;
use AUTHORIZATION;
use HeaderValue;
let url = default
.sanitize_url_str
.expect;
assert_eq!;
let form = default
.sanitize_str;
assert_eq!;
let header = default
.sanitize_value;
assert_eq!;
let body_content_type = from_static;
let body = default.sanitize_body;
assert_eq!;
let argv = default
.sanitize_argv_display;
assert_eq!;
Adapter methods require an explicit NameMatchMode, just like the core
FieldSanitizer methods. Use NameMatchMode::ExactOrSuffix when contextual
names such as OPENAI_API_KEY should match the configured field api_key.
Integration Guidance
The crate has two layers:
- Use
core/ root exports such asFieldSanitizerfor field-name matching and value masking. - Use
adapter/ root exports such asUrlSanitizer,HttpBodySanitizer, andArgvSanitizerfor supported structured inputs. - Keep protocol-specific parsing in caller crates when the adapter cannot model the full context, especially shell command strings and application-specific payloads.
For example, an HTTP crate can use UrlSanitizer for parsed URLs and
HttpHeaderSanitizer for http::HeaderMap and http::HeaderValue values. It
can use HttpBodySanitizer when it has body bytes plus an optional
Content-Type header; the adapter supports JSON, NDJSON, URL-encoded forms,
multipart bodies, declared text/* bodies, and binary fallback markers.
Unsupported UTF-8 media types are redacted rather than passed through. The
returned body string is for logs and diagnostics, not a replayable HTTP body:
structured output may be compacted and may not preserve original whitespace,
field order, or JSON value types for redacted fields. The caller still owns
capture limits, decompression, streaming boundaries, and any
application-specific parsing. A command runner can use ArgvSanitizer for
structured argv and EnvSanitizer for explicit environment overrides, but
should not claim to safely parse arbitrary shell scripts.
Testing
A minimal local run:
To mirror what continuous integration enforces, run the repository scripts from
the project root: ./align-ci.sh brings local tooling and configuration in line
with CI, then ./ci-check.sh runs the same checks the pipeline uses. For test
coverage, use ./coverage.sh to generate or open reports.
Contributing
Issues and pull requests are welcome.
- Keep the core focused on reusable field-value sanitization primitives.
- Keep adapters scoped to formats with clear, bounded parsing rules.
- Add or update tests when changing matching or masking behavior.
- Update this README and public rustdoc when user-visible behavior changes.
- Before submitting, run
./align-ci.shand then./ci-check.sh.
By contributing, you agree to license your contributions under the Apache License, Version 2.0, the same license as this project.
License
Copyright © 2026 Haixing Hu, Qubit Co. Ltd.
This project is licensed under the Apache License, Version 2.0. See
the LICENSE file in the repository for the full text.
Author
Haixing Hu — Qubit Co. Ltd.
| Repository | github.com/qubit-ltd/rs-sanitize |
| Documentation | docs.rs/qubit-sanitize |
| Crate | crates.io/crates/qubit-sanitize |