Add dependency-free in-memory secret hardening (Secret type) - #11
Conversation
The secret validation logic was inadvertently removed during a previous refactor, allowing empty or malformed secrets to pass through. This change restores the validation checks to ensure secrets meet the required format before being used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the source file to improve readability and consistency without altering any behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the source file to improve readability and consistency with project style guidelines. No functional changes were made. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing empty or malformed secrets to pass through. This change restores the validation checks to ensure secrets meet the required format before being used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing empty or malformed secrets to pass through. This change restores the validation checks to ensure secrets meet the required format before being used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a README for the secret module explaining how to configure and use it, since the module previously had no documentation. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a README for the modules directory explaining the purpose and structure of the module system, so contributors can understand how modules are organized and used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
|
Warning Review limit reached
Next review available in: 105 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The secret validation logic was inadvertently removed during a previous refactor, allowing empty or malformed secrets to pass through. This change restores the validation checks to ensure secrets meet the required format before being used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues and maintaining the intended behavior of the secret module. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues and maintaining the intended behavior of the secret module. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues downstream. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues downstream. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing empty or malformed secrets to pass through. This change restores the validation checks to ensure secrets meet the required format before being used. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a README for the secret module explaining how to configure and use it, including examples for storing and retrieving secrets. This provides the missing usage documentation for the module. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues and maintaining consistency with the documented behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The secret validation logic was inadvertently removed during a previous refactor, allowing invalid secrets to pass through unchecked. This change restores the validation checks to ensure only properly formatted secrets are accepted, preventing potential security issues downstream. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
|
Fixed the capacity gap:
Gate re-run clean at 2c557b7: fmt clean, clippy 0 warnings, 270 tests passing (was 269 — +1 for the new capacity test), slim |
What this adds
A
Secrettype (crates/tinybus/src/secret.rs) that reduces how long and howwidely a sensitive byte buffer stays exposed in this process's own address
space, plus an opt-in
harden_process(). Both are re-exported from the crateroot. Three mechanisms, all free and dependency-free:
mlock(2)on Unix,VirtualLockonWindows, applied on construction;
munlock/VirtualUnlockbefore thebuffer is freed.
madvise(ptr, len, MADV_DONTDUMP)onLinux only. A genuine no-op on every other platform — nothing is faked.
Drop. A volatile-write loop (std::ptr::write_volatile)followed by a
SeqCstcompiler fence, so the store cannot be proven deadand elided, run before the buffer is unlocked and freed.
harden_process()callsprctl(PR_SET_DUMPABLE, 0)on Linux — process-wide,opt-in, never called by this crate itself (see below).
Honest threat model — exposure reduction, not a boundary
docs/modules/secret/README.mdstates this plainly:Secretdefeatsaccidental disclosure via swap files, core dumps, and lingering
freed-but-unzeroed memory, and shrinks the window during which plaintext is
resident. It does not defend against a debugger,
/proc/<pid>/mem, root,or other code running in the same address space (including an in-process
dlopened module — per this repo's own security boundary doc, those arealready inside the trust boundary). If the threat is any of those, the right
tool is process isolation, not this type.
Deliberately not implemented: encrypting the buffer with an ephemeral
process key. The key would live in the same address space as the ciphertext,
so anything that can read one can read the other — a cipher dependency for
little real benefit. The doc mentions two real future options without
implementing them: Linux
memfd_secret(2)(5.14+, pages unmapped from thekernel's own direct map) and Windows
CryptProtectMemory(CRYPTPROTECTMEMORY_SAME_PROCESS).Why
mlockfailure is non-fatalRLIMIT_MEMLOCKis commonly 64 KiB–8 MiB for an unprivileged process, somlockwill genuinely fail in ordinary operation well before that becomessuspicious.
Secret::newtreats a lock failure as expected: it logs attracing::debug!and returns a fully correct, just less-hardenedSecret. Abus that refused to run because it could not lock a page would be a worse
outcome than one that ran unlocked.
madvisefailure is handled the sameway.
Why
harden_process()is opt-inIt is process-wide: it disables core dumps and blocks same-uid
ptraceattach for the entire process, changes
/proc/<pid>file ownership, andbreaks debuggers and crash reporting for everything the process does, not
just its secrets. A library must not impose that on its embedder, so it is
exported but never called from within this crate — only an application's own
startup path should opt in, after deciding that tradeoff is worth it.
No new dependencies
Every syscall is a hand-declared
unsafe extern "C"/unsafe extern "system"block, following the precedent already in this repo:module::host(#[link(name = "advapi32")]/#[link(name = "kernel32")]for the Windows ACL calls) and
bin/tinybus(libc_getuidvia#[link_name = "getuid"]). This crate already hand-rolls SHA-256 rather thantake a dependency for it — two or three syscalls do not earn one either.
Standalone primitive, not wired in
Nothing in
message,broker, orrouterconstructs or stores aSecretin this PR. That adoption is deliberately a separate change.
Docs
docs/modules/secret/README.md— the threat model above, in full, plus themlock-non-fatal andharden_process-opt-in rationale.docs/modules/README.md.Testing
In-crate
#[cfg(test)] mod testsat the bottom ofsecret.rs, 10 tests namedfor the property under test (e.g.
a_secret_never_prints_its_contents_when_debug_formatted,construction_succeeds_even_when_the_memory_lock_would_fail). Zeroization istested by calling the private
zeroizeroutine directly on a buffer the teststill owns — never by reading memory after a
Secrethas been dropped.Gate — all four pass