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
685 changes: 352 additions & 333 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ members = ["crates/*", "src-tauri"]

[workspace.package]
edition = "2021"
rust-version = "1.80"
rust-version = "1.90"
license = "PolyForm-Noncommercial-1.0.0"
authors = ["CrabNebula Ltd. <hello@crabnebula.dev>"]
repository = "https://github.com/crabnebula-dev/achilles"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Electron apps it audits actually looks like.

## Quickstart

Requirements: Rust 1.80+. macOS 12+, Windows 10+, or a Linux desktop. The GUI
Requirements: Rust 1.90+. macOS 12+, Windows 10+, or a Linux desktop. The GUI
needs nothing else to run.

```sh
Expand Down
10 changes: 8 additions & 2 deletions crates/achilles-wasm/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,12 @@ impl pkg::Sink for TreeSink<'_> {
Ok(())
}

fn file(&mut self, path: &std::path::Path, data: Vec<u8>, mode: u32) -> Result<(), pkg::PkgError> {
fn file(
&mut self,
path: &std::path::Path,
data: Vec<u8>,
mode: u32,
) -> Result<(), pkg::PkgError> {
self.0.insert_file_with_mode(path.to_path_buf(), data, mode);
Ok(())
}
Expand All @@ -291,7 +296,8 @@ impl pkg::Sink for TreeSink<'_> {
path: &std::path::Path,
target: &std::path::Path,
) -> Result<(), pkg::PkgError> {
self.0.insert_symlink(path.to_path_buf(), target.to_path_buf());
self.0
.insert_symlink(path.to_path_buf(), target.to_path_buf());
Ok(())
}
}
Expand Down
10 changes: 8 additions & 2 deletions crates/achilles-wasm/tests/upload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ fn treats_a_picked_bundle_as_the_app() {
#[test]
fn finds_a_bundle_nested_below_the_picked_root() {
let base = tempdir("find-nested");
write(&base.join("Apps/Signal.app/Contents/Info.plist"), b"<plist/>");
write(
&base.join("Apps/Signal.app/Contents/Info.plist"),
b"<plist/>",
);

let app = find_app(&base, Platform::Macos).expect("nested bundle should be found");
assert_eq!(app.root, base.join("Apps/Signal.app"));
Expand Down Expand Up @@ -287,7 +290,10 @@ fn payload_search_prefers_the_application_over_the_usr_bin_launcher() {
write(&base.join("usr/bin/foo"), &elf(2048));
write(&base.join("opt/Foo/foo"), &elf(200_000));
write(&base.join("opt/Foo/libffmpeg.so"), &elf(400_000));
write(&base.join("usr/share/applications/foo.desktop"), b"[Desktop Entry]");
write(
&base.join("usr/share/applications/foo.desktop"),
b"[Desktop Entry]",
);

let app = find_app_in_payload(&base).expect("app should be found");
assert_eq!(app.root, base.join("opt/Foo"));
Expand Down
21 changes: 17 additions & 4 deletions crates/binmeta/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ pub fn inspect(path: &Path) -> Result<BinaryMeta, Error> {
}
}


// --- Mach-O -------------------------------------------------------------

fn mach_arch(macho: &goblin::mach::MachO) -> Arch {
Expand Down Expand Up @@ -186,7 +185,12 @@ fn mach_arch(macho: &goblin::mach::MachO) -> Arch {
})
.collect();
// `libs[0]` is a "self" placeholder for the binary itself, not a dependency.
let names: Vec<&str> = macho.libs.iter().copied().filter(|l| *l != "self").collect();
let names: Vec<&str> = macho
.libs
.iter()
.copied()
.filter(|l| *l != "self")
.collect();
let linked_libraries = if names.len() == versions.len() {
names
.iter()
Expand Down Expand Up @@ -286,7 +290,11 @@ fn elf_arch(elf: &goblin::elf::Elf) -> Arch {
|| d.info.flags_1 & goblin::elf::dynamic::DF_1_NOW != 0
})
.unwrap_or(false);
flags.push(if bind_now { "full-RELRO".into() } else { "partial-RELRO".into() });
flags.push(if bind_now {
"full-RELRO".into()
} else {
"partial-RELRO".into()
});
}

let sections = elf
Expand Down Expand Up @@ -381,7 +389,12 @@ fn pe_arch(pe: &goblin::pe::PE) -> Arch {

Arch {
arch,
kind: if pe.is_lib { "shared-library" } else { "executable" }.into(),
kind: if pe.is_lib {
"shared-library"
} else {
"executable"
}
.into(),
bits: if pe.is_64 { 64 } else { 32 },
endianness: "little".into(),
entry: Some(format!("0x{:x}", pe.entry)),
Expand Down
76 changes: 43 additions & 33 deletions crates/cbom/src/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ pub(crate) fn build(app: AppRef, evidence: &[CryptoEvidence]) -> CryptoInventory
let prov = ev.provenance();
let loc = ev.location();
match ev {
CryptoEvidence::Protocol { family, version, .. } => {
CryptoEvidence::Protocol {
family, version, ..
} => {
let c = normalize::protocol(*family, version.as_deref());
protocols.insert(upsert(&mut assets, &c, prov, loc));
}
Expand Down Expand Up @@ -113,46 +115,54 @@ pub(crate) fn build(app: AppRef, evidence: &[CryptoEvidence]) -> CryptoInventory
} => {
// A certificate asset plus links to its sig + key algorithms.
let mut algo_refs = Vec::new();
if let Some(s) = signature_algorithm.as_deref().and_then(normalize::named_algorithm) {
if let Some(s) = signature_algorithm
.as_deref()
.and_then(normalize::named_algorithm)
{
algo_refs.push(upsert(&mut assets, &s, prov, loc));
}
if let Some(k) = public_key_algorithm.as_deref().and_then(normalize::named_algorithm) {
if let Some(k) = public_key_algorithm
.as_deref()
.and_then(normalize::named_algorithm)
{
algo_refs.push(upsert(&mut assets, &k, prov, loc));
}
let cert_ref = format!(
"crypto/certificate/{}",
slug(subject.as_deref().or(issuer.as_deref()).unwrap_or("cert"))
);
let a = assets.entry(cert_ref.clone()).or_insert_with(|| CryptoAsset {
bom_ref: cert_ref.clone(),
asset_type: AssetType::Certificate,
name: subject.clone().unwrap_or_else(|| "certificate".into()),
oid: None,
primitive: None,
parameter: None,
crypto_functions: vec![],
assessment: if *self_signed {
QuantumAssessment::Weak
} else {
QuantumAssessment::NotApplicable
},
nist_level: 0,
deprecated: false,
provenance: BTreeSet::new(),
occurrences: 0,
locations: BTreeSet::new(),
protocol: None,
certificate: Some(CertSummary {
subject: subject.clone(),
issuer: issuer.clone(),
not_before: *not_before,
not_after: *not_after,
self_signed: *self_signed,
signature_algorithm: signature_algorithm.clone(),
public_key_algorithm: public_key_algorithm.clone(),
}),
library_version: None,
});
let a = assets
.entry(cert_ref.clone())
.or_insert_with(|| CryptoAsset {
bom_ref: cert_ref.clone(),
asset_type: AssetType::Certificate,
name: subject.clone().unwrap_or_else(|| "certificate".into()),
oid: None,
primitive: None,
parameter: None,
crypto_functions: vec![],
assessment: if *self_signed {
QuantumAssessment::Weak
} else {
QuantumAssessment::NotApplicable
},
nist_level: 0,
deprecated: false,
provenance: BTreeSet::new(),
occurrences: 0,
locations: BTreeSet::new(),
protocol: None,
certificate: Some(CertSummary {
subject: subject.clone(),
issuer: issuer.clone(),
not_before: *not_before,
not_after: *not_after,
self_signed: *self_signed,
signature_algorithm: signature_algorithm.clone(),
public_key_algorithm: public_key_algorithm.clone(),
}),
library_version: None,
});
a.occurrences += 1;
a.provenance.insert(prov);
if let Some(l) = loc {
Expand Down
7 changes: 5 additions & 2 deletions crates/cbom/src/cyclonedx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ fn protocol_component(a: &CryptoAsset) -> Value {
props["version"] = json!(v);
}
if !info.cipher_suites.is_empty() {
props["cipherSuites"] =
json!(info.cipher_suites.iter().map(|n| json!({ "name": n })).collect::<Vec<_>>());
props["cipherSuites"] = json!(info
.cipher_suites
.iter()
.map(|n| json!({ "name": n }))
.collect::<Vec<_>>());
}
}
json!({
Expand Down
Loading
Loading