| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use crate::config::BuildConfig; |
| use crate::group::Group; |
| use anyhow::Result; |
| |
| fn group_vet_criteria(group: Group, shipped: Option<bool>) -> Vec<AuditCriteria> { |
| use AuditCriteria::*; |
| // No third-party crates from crates.io are allowed to implement crypto today. |
| // We only accept crypto implementation from BoringSSL, which we bring in |
| // through DEPS. If this should ever change we will need to add a |
| // configuration option in gnrt_config.toml to allow a crate to |
| // implement crypto. |
| match (shipped, group) { |
| // Safe crates can be used on adversarial inputs without a sandbox. They can not cause |
| // security bugs in this case, and must satisfy the Rule of Two. |
| // |
| // "rule-of-two-safe-to-deploy" destructures into a combination of |
| // * "safe-to-deploy", and |
| // * "ub-risk-1". |
| // |
| // We currently consider ub-risk-2 as satisfying the Rule of Two, though there seems to be |
| // some spot in between risk 1 and 2 that fits better and this could be improved. |
| (Some(true), Group::Safe) | (None, Group::Safe) => { |
| vec![CryptoSafe, SafeToDeploy, UbRisk2] |
| } |
| // Sandbox crates are used in a sandbox, so we have a weaker tolerance. There may be a bunch |
| // of ASM code in there for example. Adversarial inputs may have a way to break things, |
| // though we certainly try to avoid it. |
| // |
| // This type of crate is not well described in the UB risk guidelines for now, so we use |
| // "ub-risk-3" for this category. |
| (Some(true), Group::Sandbox) | (None, Group::Sandbox) => { |
| vec![CryptoSafe, SafeToDeploy, UbRisk3] |
| } |
| // Code in tests is not run on user machines and does not interact with adversarial inputs. |
| // Thus it does not need to be safe-to-deploy, but it needs to not be malicious against |
| // developers and CI bots which is covered by "safe-to-run". |
| (_, Group::Test) => vec![CryptoSafe, SafeToRun], |
| // Crates that contribute to the shipped binary but are not themselves shipped (code |
| // generators for example) do not get deployed themselves and do not interact with |
| // adversarial inputs. Thus they need to be "safe-to-run" by developers and CI only. |
| (Some(false), _) => vec![CryptoSafe, SafeToRun], |
| } |
| } |
| |
| #[derive(serde::Serialize)] |
| pub struct VetConfigToml { |
| policies: Vec<Policy>, |
| } |
| |
| #[derive(serde::Serialize)] |
| pub struct Policy { |
| crate_name: String, |
| criteria: Vec<AuditCriteria>, |
| } |
| |
| /// Audit criteria used by Chromium for `cargo vet` audits. This enum |
| /// represents and replicates the criteria that can be found in |
| /// https://github.com/google/rust-crate-audits/blob/main/audits.toml (e.g. `UbRisk2` corresponds |
| /// to the `[criteria.ub-risk-2]` entry in that `audits.toml` file. |
| /// Corresponding auditing standards are described in |
| /// https://github.com/google/rust-crate-audits/blob/main/auditing_standards.md |
| #[derive(serde::Serialize)] |
| #[serde(rename_all = "kebab-case")] |
| pub enum AuditCriteria { |
| CryptoSafe, |
| SafeToDeploy, |
| SafeToRun, |
| #[serde(rename = "ub-risk-2")] |
| UbRisk2, |
| #[serde(rename = "ub-risk-3")] |
| UbRisk3, |
| } |
| |
| /// Generate the config.toml for `cargo vet` with policies that match the groups |
| /// specified for each crate through gnrt_config.toml. |
| pub fn create_vet_config<'a>( |
| packages: impl IntoIterator<Item = &'a cargo_metadata::Package>, |
| config: &BuildConfig, |
| mut find_group: impl FnMut(&'a cargo_metadata::PackageId) -> Group, |
| mut find_shipped: impl FnMut(&'a cargo_metadata::PackageId) -> Option<bool>, |
| ) -> Result<VetConfigToml> { |
| let mut vet_config_toml = VetConfigToml { policies: Vec::new() }; |
| for package in packages { |
| let group = find_group(&package.id); |
| let shipped = find_shipped(&package.id); |
| |
| let mut crate_name = package.name.clone(); |
| crate_name.push(':'); |
| crate_name.push_str(&package.version.to_string()); |
| |
| let criteria = if config.resolve.remove_crates.contains(&package.name) { |
| vec![] |
| } else { |
| group_vet_criteria(group, shipped) |
| }; |
| |
| vet_config_toml.policies.push(Policy { crate_name, criteria }); |
| } |
| |
| vet_config_toml.policies.sort_unstable_by(|a, b| a.crate_name.cmp(&b.crate_name)); |
| Ok(vet_config_toml) |
| } |