Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions src/assail/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,25 @@ pub fn load_user_classifications(project_root: &Path) -> Vec<UserClassification>
.join("assail-classifications.a2ml"),
project_root.join(".panic-attack-classifications.a2ml"),
];
// User-classification a2ml files are hand-edited audit registries. A
// legitimate one rarely exceeds a few dozen KiB. Capping at 4 MiB
// stops a malicious or accidental input from exhausting memory during
// a multi-thousand-repo mass-panic sweep.
use std::io::Read;
const CLASSIFICATIONS_FILE_READ_LIMIT: u64 = 4 * 1024 * 1024;

let mut content = String::new();
for p in &candidate_paths {
if let Ok(c) = fs::read_to_string(p) {
content = c;
break;
if let Ok(mut f) = fs::File::open(p) {
let mut buf = String::new();
if (&mut f)
.take(CLASSIFICATIONS_FILE_READ_LIMIT)
.read_to_string(&mut buf)
.is_ok()
{
content = buf;
break;
}
}
}
if content.is_empty() {
Expand Down
15 changes: 13 additions & 2 deletions src/assemblyline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,20 @@ impl FingerprintCache {
Ok(())
}

/// Load fingerprint cache from a standalone cache JSON file
/// Load fingerprint cache from a standalone cache JSON file.
///
/// Bounded at 256 MiB — fingerprint caches grow with the size of the
/// estate being scanned, but even an aggressive multi-thousand-repo
/// rollup should land well under this cap. A larger file is almost
/// certainly corrupted or hostile.
pub fn load_cache_file(path: &Path) -> Result<Self> {
let content = fs::read_to_string(path)?;
use std::io::Read;
const CACHE_FILE_READ_LIMIT: u64 = 256 * 1024 * 1024;

let mut content = String::new();
fs::File::open(path)?
.take(CACHE_FILE_READ_LIMIT)
.read_to_string(&mut content)?;
let cache: Self = serde_json::from_str(&content)?;
Ok(cache)
}
Expand Down
15 changes: 13 additions & 2 deletions src/attestation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,19 @@ pub enum VerifyResult {
/// with a list of failure reasons otherwise.
pub fn verify_attestation_file(path: &std::path::Path) -> anyhow::Result<VerifyResult> {
use sha2::{Digest, Sha256};

let content = std::fs::read_to_string(path)
use std::io::Read;

// Attestation envelopes are JSON. They embed three hashes plus a small
// signature; legitimate envelopes are well under 1 MiB. Capping at
// 16 MiB stops a malicious or accidental input from exhausting memory
// before verification can even begin.
const ATTESTATION_FILE_READ_LIMIT: u64 = 16 * 1024 * 1024;

let mut content = String::new();
std::fs::File::open(path)
.map_err(|e| anyhow::anyhow!("opening {}: {}", path.display(), e))?
.take(ATTESTATION_FILE_READ_LIMIT)
.read_to_string(&mut content)
.map_err(|e| anyhow::anyhow!("reading {}: {}", path.display(), e))?;

let envelope: A2mlEnvelope = serde_json::from_str(&content)
Expand Down
Loading