feat: add dependabot-cooldown configuration (#1377)
Some checks are pending
CI / Lint (push) Waiting to run
CI / Test (push) Waiting to run
CI / Test site build (push) Waiting to run
CI / All tests pass (push) Blocked by required conditions
zizmor wheel builds for PyPI 🐍 / Build Linux wheels (manylinux) (push) Waiting to run
zizmor wheel builds for PyPI 🐍 / Build Linux wheels (musllinux) (push) Waiting to run
zizmor wheel builds for PyPI 🐍 / Build Windows wheels (push) Waiting to run
zizmor wheel builds for PyPI 🐍 / Build macOS wheels (push) Waiting to run
zizmor wheel builds for PyPI 🐍 / Build source distribution (push) Waiting to run
zizmor wheel builds for PyPI 🐍 / Release (push) Blocked by required conditions
Deploy zizmor documentation site 🌐 / Deploy zizmor documentation to GitHub Pages 🌐 (push) Waiting to run
GitHub Actions Security Analysis with zizmor 🌈 / Run zizmor 🌈 (push) Waiting to run

This commit is contained in:
William Woodruff 2025-11-27 23:28:10 -05:00 committed by GitHub
parent 5a19cf3a38
commit 98bddd53e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 154 additions and 25 deletions

View file

@ -85,7 +85,7 @@ impl Audit for DependabotCooldown {
async fn audit_dependabot<'doc>(
&self,
dependabot: &'doc crate::models::dependabot::Dependabot,
_config: &crate::config::Config,
config: &crate::config::Config,
) -> Result<Vec<crate::finding::Finding<'doc>>, AuditError> {
let mut findings = vec![];
@ -111,24 +111,24 @@ impl Audit for DependabotCooldown {
.fix(Self::create_add_default_days_fix(update))
.build(dependabot)?,
),
// We currently (arbitrarily) consider cooldowns under 7 days
// to be insufficient.
//
// TODO(ww): This should probably be configurable.
Some(default_days) if default_days < 7 => findings.push(
Self::finding()
.add_location(
update
.location()
.with_keys(["cooldown".into(), "default-days".into()])
.primary()
.annotated("insufficient default-days configured"),
)
.confidence(Confidence::Medium)
.severity(Severity::Low)
.fix(Self::create_increase_default_days_fix(update))
.build(dependabot)?,
),
Some(default_days)
if default_days < config.dependabot_cooldown_config.days.get() as u64 =>
{
findings.push(
Self::finding()
.add_location(
update
.location()
.with_keys(["cooldown".into(), "default-days".into()])
.primary()
.annotated("insufficient default-days configured"),
)
.confidence(Confidence::Medium)
.severity(Severity::Low)
.fix(Self::create_increase_default_days_fix(update))
.build(dependabot)?,
)
}
Some(_) => {}
},
None => findings.push(

View file

@ -11,7 +11,10 @@ use thiserror::Error;
use crate::{
App, CollectionOptions,
audit::{AuditCore, forbidden_uses::ForbiddenUses, unpinned_uses::UnpinnedUses},
audit::{
AuditCore, dependabot_cooldown::DependabotCooldown, forbidden_uses::ForbiddenUses,
unpinned_uses::UnpinnedUses,
},
finding::Finding,
github::{Client, ClientError},
models::uses::RepositoryUsesPattern,
@ -151,6 +154,20 @@ impl RawConfig {
}
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) struct DependabotCooldownConfig {
pub(crate) days: NonZeroUsize,
}
impl Default for DependabotCooldownConfig {
fn default() -> Self {
Self {
days: NonZeroUsize::new(7).expect("impossible"),
}
}
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "kebab-case", untagged)]
pub(crate) enum ForbiddenUsesConfig {
@ -344,6 +361,7 @@ impl TryFrom<UnpinnedUsesConfig> for UnpinnedUsesPolicies {
#[derive(Clone, Debug, Default)]
pub(crate) struct Config {
raw: RawConfig,
pub(crate) dependabot_cooldown_config: DependabotCooldownConfig,
pub(crate) forbidden_uses_config: Option<ForbiddenUsesConfig>,
pub(crate) unpinned_uses_policies: UnpinnedUsesPolicies,
}
@ -353,6 +371,10 @@ impl Config {
fn load(contents: &str) -> Result<Self, ConfigErrorInner> {
let raw = RawConfig::load(contents)?;
let dependabot_cooldown_config = raw
.rule_config(DependabotCooldown::ident())?
.unwrap_or_default();
let forbidden_uses_config = raw.rule_config(ForbiddenUses::ident())?;
let unpinned_uses_policies = {
@ -367,6 +389,7 @@ impl Config {
Ok(Self {
raw,
dependabot_cooldown_config,
forbidden_uses_config,
unpinned_uses_policies,
})

View file

@ -1421,6 +1421,82 @@ fn dependabot_cooldown() -> Result<()> {
1 findings (1 fixable): 0 informational, 1 low, 0 medium, 0 high
");
// dependabot-cooldown audit config is invalid.
insta::assert_snapshot!(
zizmor()
.expects_failure(true)
.input(input_under_test("neutral.yml"))
.config(input_under_test("dependabot-cooldown/configs/invalid-cooldown-not-number.yml"))
.output(OutputMode::Stderr)
.run()?,
@r#"
🌈 zizmor v@@VERSION@@
fatal: no audit was performed
error: configuration error in @@CONFIG@@
|
= help: check the configuration for the 'dependabot-cooldown' rule
= help: see: https://docs.zizmor.sh/audits/#dependabot-cooldown-configuration
Caused by:
0: configuration error in @@CONFIG@@
1: invalid syntax for audit `dependabot-cooldown`
2: invalid type: string "lol", expected a nonzero usize
"#
);
insta::assert_snapshot!(
zizmor()
.expects_failure(true)
.input(input_under_test("neutral.yml"))
.config(input_under_test("dependabot-cooldown/configs/invalid-cooldown-zero-days.yml"))
.output(OutputMode::Stderr)
.run()?,
@r"
🌈 zizmor v@@VERSION@@
fatal: no audit was performed
error: configuration error in @@CONFIG@@
|
= help: check the configuration for the 'dependabot-cooldown' rule
= help: see: https://docs.zizmor.sh/audits/#dependabot-cooldown-configuration
Caused by:
0: configuration error in @@CONFIG@@
1: invalid syntax for audit `dependabot-cooldown`
2: invalid value: integer `0`, expected a nonzero usize
"
);
insta::assert_snapshot!(
zizmor()
.expects_failure(true)
.input(input_under_test("neutral.yml"))
.config(input_under_test("dependabot-cooldown/configs/invalid-cooldown-negative-days.yml"))
.output(OutputMode::Stderr)
.run()?,
@r"
🌈 zizmor v@@VERSION@@
fatal: no audit was performed
error: configuration error in @@CONFIG@@
|
= help: check the configuration for the 'dependabot-cooldown' rule
= help: see: https://docs.zizmor.sh/audits/#dependabot-cooldown-configuration
Caused by:
0: configuration error in @@CONFIG@@
1: invalid syntax for audit `dependabot-cooldown`
2: invalid value: integer `-1`, expected a nonzero usize
"
);
// A very short cooldown, but permitted by config.
insta::assert_snapshot!(
zizmor()
.input(input_under_test("dependabot-cooldown/default-days-too-short/dependabot.yml"))
.config(input_under_test("dependabot-cooldown/configs/cooldown-one-day.yml"))
.run()?,
@"No findings to report. Good job!"
);
Ok(())
}

View file

@ -0,0 +1,4 @@
rules:
dependabot-cooldown:
config:
days: 1

View file

@ -0,0 +1,4 @@
rules:
dependabot-cooldown:
config:
days: -1

View file

@ -0,0 +1,4 @@
rules:
dependabot-cooldown:
config:
days: lol

View file

@ -0,0 +1,4 @@
rules:
dependabot-cooldown:
config:
days: 0