Merge nucleic/brisk-yarn-dingo-50se into dev

This commit is contained in:
2026-07-26 21:33:53 -07:00
parent 3a3489d276
commit 1d6b240dbb
2 changed files with 120 additions and 1 deletions
+14 -1
View File
@@ -93,6 +93,11 @@ enum Event {
pipeline_id: u64,
from_index: u64,
to_index: u64,
/// The commands either side of this link, as written — brush-core renders them from the
/// AST at spawn, so they name a compound stage correctly and arrive with the very first
/// link rather than waiting on the stages to exit.
from_text: String,
to_text: String,
bytes: u64,
truncated: bool,
hash: String,
@@ -311,7 +316,11 @@ fn redact(text: &str) -> String {
}
fn looks_secret(word: &str) -> bool {
let w = word.trim_matches(|c: char| c == '"' || c == '\'' || c == ',');
// `…` is trimmed alongside the quoting because brush-core appends it when it caps a pipeline
// stage label (docs/NASH.md §5.3). Glued onto the final token with no separator, it otherwise
// failed the charset test below and walked a truncated credential straight past the entropy
// branch — a secret that happened to straddle the cap left the guest in the clear.
let w = word.trim_matches(|c: char| c == '"' || c == '\'' || c == ',' || c == '…');
// Common token prefixes (GitHub PATs, Slack, Stripe, AWS, OpenAI/Anthropic, …).
const PREFIXES: [&str; 10] =
["ghp_", "gho_", "ghs_", "github_pat_", "xoxb-", "xoxp-", "sk-", "AKIA", "ASIA", "AIza"];
@@ -523,6 +532,10 @@ impl brush_core::gate::Gate for RecordingGate {
pipeline_id: ev.pipeline_id,
from_index: ev.from_index as u64,
to_index: ev.to_index as u64,
// Stage text is source, so it can carry a literal credential the same way argv
// can — every outbound string goes through the same masking (docs/NASH.md §5.4).
from_text: redact(&ev.from_text),
to_text: redact(&ev.to_text),
bytes: ev.total_bytes,
truncated: ev.truncated || ev.captured.len() > capped,
// Hash over the captured prefix (the full stream isn't buffered).