use std::path::{Path, PathBuf};
const FORBIDDEN: &[&str] = &[
"secret_texts",
"secret_bytes",
"secret_literals",
"secret_values",
"secret",
];
const ALLOWED: &[(&str, &str)] = &[(
"secret_tainted_paths",
"returns redacted dotted labels of the tainted cone, never secret bytes",
)];
fn rust_sources(root: &Path) -> Vec<PathBuf> {
let mut out = Vec::new();
let mut stack = vec![root.to_path_buf()];
while let Some(directory) = stack.pop() {
for entry in std::fs::read_dir(&directory).expect("src directory") {
let path = entry.expect("directory entry").path();
if path.is_dir() {
stack.push(path);
} else if path.extension().and_then(|ext| ext.to_str()) == Some("rs") {
out.push(path);
}
}
}
out.sort();
out
}
fn logical_lines(text: &str) -> Vec<(usize, String)> {
let lines: Vec<&str> = text.lines().collect();
let mut out = Vec::new();
let mut buffer = String::new();
let mut start = 0usize;
for (index, line) in lines.iter().enumerate() {
let trimmed = line.trim();
if buffer.is_empty() {
start = index + 1;
} else {
buffer.push(' ');
}
buffer.push_str(trimmed);
let balanced = buffer.matches('(').count() == buffer.matches(')').count();
let next = lines.get(index + 1).map(|line| line.trim());
let continues = next.is_some_and(|next| {
buffer.ends_with("->") || next.starts_with("->") || next.starts_with("where")
});
if balanced && !continues {
out.push((start, std::mem::take(&mut buffer)));
}
}
if !buffer.is_empty() {
out.push((start, buffer));
}
out
}
fn declaration(line: &str) -> &str {
let mut rest = line.trim_start();
loop {
if rest.starts_with("#[") {
match rest.find(']') {
Some(close) => rest = rest[close + 1..].trim_start(),
None => return rest,
}
} else if rest.starts_with("///") || rest.starts_with("//") {
return "";
} else {
return rest;
}
}
}
fn public_fn_name(line: &str) -> Option<&str> {
let mut rest = line.strip_prefix("pub ")?;
loop {
let stripped = ["const ", "async ", "unsafe "]
.iter()
.find_map(|modifier| rest.strip_prefix(modifier))
.or_else(|| {
if rest.starts_with("extern ") {
let after = rest.trim_start_matches("extern ");
let after = match after.strip_prefix('"') {
Some(rest) => rest.split_once('"').map(|(_, rest)| rest).unwrap_or(after),
None => after,
};
Some(after.trim_start())
} else {
None
}
});
match stripped {
Some(next) => rest = next,
None => break,
}
}
let rest = rest.strip_prefix("fn ")?;
Some(rest.split('(').next().unwrap_or("").trim())
}
fn returns_raw_text(line: &str) -> bool {
let signature = line.split('{').next().unwrap_or(line);
let signature = signature.split(" where ").next().unwrap_or(signature);
let Some(arrow) = signature.rfind("->") else {
return false;
};
let tail = &signature[arrow + 2..];
tail.contains("String")
|| tail.contains("Vec<String>")
|| tail.contains("str")
|| tail.contains("char")
|| tail.contains("u8")
}
#[test]
fn the_crate_exposes_no_plaintext_secret_accessor() {
let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("src");
let mut offenders = Vec::new();
for path in rust_sources(&root) {
let relative = path
.strip_prefix(env!("CARGO_MANIFEST_DIR"))
.unwrap_or(&path)
.display()
.to_string();
let text = std::fs::read_to_string(&path).expect("source file");
for (line_number, raw) in logical_lines(&text) {
let line = declaration(&raw);
if line.is_empty() {
continue;
}
if let Some(name) = public_fn_name(line) {
if FORBIDDEN.contains(&name) {
offenders.push(format!("{relative}:{line_number}: {line}"));
continue;
}
if name.contains("secret") {
let allowed = ALLOWED.iter().any(|(allowed, _)| *allowed == name);
if !allowed && returns_raw_text(line) {
offenders.push(format!("{relative}:{line_number}: {line}"));
}
}
}
if line.starts_with("pub use") {
if line.contains("::*") {
offenders.push(format!(
"{relative}:{line_number}: glob re-export cannot be audited: {line}"
));
}
if let Some((_, alias)) = line.split_once(" as ") {
if alias.trim().trim_end_matches(';').contains("secret") {
offenders.push(format!(
"{relative}:{line_number}: aliased re-export with a secret \
name cannot be audited: {line}"
));
}
}
for forbidden in FORBIDDEN {
if line
.split(|c: char| !c.is_alphanumeric() && c != '_')
.any(|token| token == *forbidden)
{
offenders.push(format!("{relative}:{line_number}: {line}"));
}
}
}
}
}
assert!(
offenders.is_empty(),
"the crate must not expose secret plaintext; found:\n{}",
offenders.join("\n")
);
}
#[test]
fn the_redaction_marker_is_the_only_public_secret_constant() {
assert_eq!(active_infinity::interop::SECRET_MARKER, "***SECRET***");
}
#[test]
fn the_allowlist_entries_still_exist_and_are_argued() {
let interop =
std::fs::read_to_string(Path::new(env!("CARGO_MANIFEST_DIR")).join("src/interop.rs"))
.expect("source file");
for (name, reason) in ALLOWED {
assert!(
interop.contains(&format!("pub fn {name}")),
"{name} is allowlisted but no longer exists; remove the entry"
);
assert!(
reason.len() > 20,
"{name} needs a real justification for the allowlist"
);
}
}
#[test]
fn the_allowlisted_label_helper_never_returns_secret_material() {
use active_infinity::{AnnotationKind, InfinityModule, Inode, SecretBytes};
let mut module = InfinityModule::new();
let secret = module.push(Inode::Secret(SecretBytes::from("hunter2-secret")));
let leaf = module.push(Inode::Int(7));
let root = module.push(Inode::Table {
fields: vec![("s".into(), secret), ("n".into(), leaf)],
});
module.set_root(Some(root));
module.bind("binding hunter2-secret", secret);
module.annotate(leaf, AnnotationKind::Intent("note".into()));
let paths = active_infinity::interop::secret_tainted_paths(&module);
assert!(!paths.is_empty(), "the tainted cone must be reported");
assert!(
paths.iter().any(|label| label.contains("binding")),
"the trap binding must appear in the tainted cone: {paths:?}"
);
for label in &paths {
assert!(
!label.contains("hunter2-secret"),
"the allowlisted helper leaked a secret copy: {label}"
);
}
}