mirror of
https://github.com/zizmorcore/zizmor.git
synced 2025-12-23 08:47:33 +00:00
feat: add --show-audit-urls=... for controlling URL rendering (#1391)
This commit is contained in:
parent
f203b457f6
commit
3b1951b71e
7 changed files with 140 additions and 10 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
env,
|
||||
io::{Write, stdout},
|
||||
process::ExitCode,
|
||||
};
|
||||
|
|
@ -116,6 +117,13 @@ struct App {
|
|||
#[arg(long, value_enum, default_value_t)]
|
||||
format: OutputFormat,
|
||||
|
||||
/// Whether to render audit URLs in the output, separately from any URLs
|
||||
/// embedded in OSC 8 links.
|
||||
///
|
||||
/// Only affects `--format=plain` (the default).
|
||||
#[arg(long, value_enum, default_value_t, env = "ZIZMOR_SHOW_AUDIT_URLS")]
|
||||
show_audit_urls: CliShowAuditUrls,
|
||||
|
||||
/// Control the use of color in output.
|
||||
#[arg(long, value_enum, value_name = "MODE")]
|
||||
color: Option<ColorMode>,
|
||||
|
|
@ -316,6 +324,41 @@ pub(crate) enum OutputFormat {
|
|||
Github,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Copy, Clone, ValueEnum)]
|
||||
pub(crate) enum CliShowAuditUrls {
|
||||
/// Render audit URLs in output automatically based on output format and runtime context.
|
||||
///
|
||||
/// For example, URLs will be shown if a CI runtime is detected.
|
||||
#[default]
|
||||
Auto,
|
||||
/// Always render audit URLs in output.
|
||||
Always,
|
||||
/// Never render audit URLs in output.
|
||||
Never,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum ShowAuditUrls {
|
||||
Always,
|
||||
Never,
|
||||
}
|
||||
|
||||
impl From<CliShowAuditUrls> for ShowAuditUrls {
|
||||
fn from(value: CliShowAuditUrls) -> Self {
|
||||
match value {
|
||||
CliShowAuditUrls::Auto => {
|
||||
if utils::is_ci() || !stdout().is_terminal() {
|
||||
ShowAuditUrls::Always
|
||||
} else {
|
||||
ShowAuditUrls::Never
|
||||
}
|
||||
}
|
||||
CliShowAuditUrls::Always => ShowAuditUrls::Always,
|
||||
CliShowAuditUrls::Never => ShowAuditUrls::Never,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, ValueEnum)]
|
||||
pub(crate) enum ColorMode {
|
||||
/// Use color output if the output supports it.
|
||||
|
|
@ -768,7 +811,12 @@ async fn run(app: &mut App) -> Result<ExitCode, Error> {
|
|||
}
|
||||
|
||||
match app.format {
|
||||
OutputFormat::Plain => output::plain::render_findings(®istry, &results, app.naches),
|
||||
OutputFormat::Plain => output::plain::render_findings(
|
||||
®istry,
|
||||
&results,
|
||||
&app.show_audit_urls.into(),
|
||||
app.naches,
|
||||
),
|
||||
OutputFormat::Json | OutputFormat::JsonV1 => {
|
||||
output::json::v1::output(stdout(), results.findings()).map_err(Error::Output)?
|
||||
}
|
||||
|
|
@ -811,7 +859,7 @@ async fn main() -> ExitCode {
|
|||
// which is then typically inaccessible from an already failed
|
||||
// CI job. In those cases, it's better to dump directly to stderr,
|
||||
// since that'll typically be captured by console logging.
|
||||
if std::env::var_os("CI").is_some() {
|
||||
if utils::is_ci() {
|
||||
std::panic::set_hook(Box::new(|info| {
|
||||
let trace = std::backtrace::Backtrace::force_capture();
|
||||
eprintln!("FATAL: zizmor crashed. This is a bug that should be reported.");
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use anstream::{eprintln, print, println};
|
|||
use owo_colors::OwoColorize;
|
||||
|
||||
use crate::{
|
||||
ShowAuditUrls,
|
||||
finding::{
|
||||
Finding, Severity,
|
||||
location::{Location, LocationKind},
|
||||
|
|
@ -94,10 +95,11 @@ pub(crate) fn finding_snippets<'doc>(
|
|||
pub(crate) fn render_findings(
|
||||
registry: &InputRegistry,
|
||||
findings: &FindingRegistry,
|
||||
show_urls_mode: &ShowAuditUrls,
|
||||
naches_mode: bool,
|
||||
) {
|
||||
for finding in findings.findings() {
|
||||
render_finding(registry, finding);
|
||||
render_finding(registry, finding, show_urls_mode);
|
||||
println!();
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +192,7 @@ pub(crate) fn render_findings(
|
|||
}
|
||||
}
|
||||
|
||||
fn render_finding(registry: &InputRegistry, finding: &Finding) {
|
||||
fn render_finding(registry: &InputRegistry, finding: &Finding, show_urls_mode: &ShowAuditUrls) {
|
||||
let title = Level::from(&finding.determinations.severity)
|
||||
.primary_title(finding.desc)
|
||||
.id(finding.ident)
|
||||
|
|
@ -213,6 +215,13 @@ fn render_finding(registry: &InputRegistry, finding: &Finding) {
|
|||
group = group.element(Level::NOTE.message("this finding has an auto-fix"));
|
||||
}
|
||||
|
||||
if matches!(show_urls_mode, ShowAuditUrls::Always) {
|
||||
group = group.element(Level::HELP.message(format!(
|
||||
"audit documentation → {url}",
|
||||
url = finding.url.green()
|
||||
)))
|
||||
}
|
||||
|
||||
// TODO: Evaluate alternative decor styles.
|
||||
let renderer = Renderer::styled();
|
||||
println!("{}", renderer.render(&[group]));
|
||||
|
|
|
|||
|
|
@ -703,6 +703,13 @@ pub(crate) mod once {
|
|||
pub(crate) use warn_once;
|
||||
}
|
||||
|
||||
/// Returns whether we are running in a CI environment.
|
||||
pub(crate) fn is_ci() -> bool {
|
||||
static IS_CI: LazyLock<bool> = LazyLock::new(|| std::env::var_os("CI").is_some());
|
||||
|
||||
*IS_CI
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use anyhow::Result;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ pub struct Zizmor {
|
|||
no_config: bool,
|
||||
output: OutputMode,
|
||||
expects_failure: bool,
|
||||
show_audit_urls: bool,
|
||||
}
|
||||
|
||||
impl Zizmor {
|
||||
|
|
@ -64,6 +65,7 @@ impl Zizmor {
|
|||
no_config: false,
|
||||
output: OutputMode::Stdout,
|
||||
expects_failure: false,
|
||||
show_audit_urls: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +127,11 @@ impl Zizmor {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn show_audit_urls(mut self, flag: bool) -> Self {
|
||||
self.show_audit_urls = flag;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn working_dir(mut self, dir: impl Into<String>) -> Self {
|
||||
self.cmd.current_dir(dir.into());
|
||||
self
|
||||
|
|
@ -165,6 +172,12 @@ impl Zizmor {
|
|||
self.cmd.arg("--no-progress");
|
||||
}
|
||||
|
||||
if self.show_audit_urls {
|
||||
self.cmd.arg("--show-audit-urls=always");
|
||||
} else {
|
||||
self.cmd.arg("--show-audit-urls=never");
|
||||
}
|
||||
|
||||
for input in &self.inputs {
|
||||
self.cmd.arg(input);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -595,3 +595,25 @@ fn test_github_output() -> Result<()> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Ensures that the `--show-audit-urls` flag works as expected.
|
||||
#[test]
|
||||
fn test_show_urls() -> Result<()> {
|
||||
let with_urls = zizmor()
|
||||
.offline(true)
|
||||
.show_audit_urls(true)
|
||||
.input(input_under_test("several-vulnerabilities.yml"))
|
||||
.run()?;
|
||||
|
||||
assert!(with_urls.contains("audit documentation → "));
|
||||
|
||||
let without_urls = zizmor()
|
||||
.offline(true)
|
||||
.show_audit_urls(false)
|
||||
.input(input_under_test("several-vulnerabilities.yml"))
|
||||
.run()?;
|
||||
|
||||
assert!(!without_urls.contains("audit documentation → "));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ Options:
|
|||
Don't show progress bars, even if the terminal supports them
|
||||
--format <FORMAT>
|
||||
The output format to emit. By default, cargo-style diagnostics will be emitted [default: plain] [possible values: plain, json, json-v1, sarif, github]
|
||||
--show-audit-urls <SHOW_AUDIT_URLS>
|
||||
Whether to render audit URLs in the output, separately from any URLs embedded in OSC 8 links [env: ZIZMOR_SHOW_AUDIT_URLS=] [default: auto] [possible values: auto, always, never]
|
||||
--color <MODE>
|
||||
Control the use of color in output [possible values: auto, always, never]
|
||||
-c, --config <CONFIG>
|
||||
|
|
|
|||
|
|
@ -206,16 +206,15 @@ By default, `zizmor` produces `cargo`-style diagnostic output.
|
|||
|
||||
```console
|
||||
error[template-injection]: code injection via template expansion
|
||||
--> ./tests/integration/test-data/template-injection/pr-425-backstop/action.yml:28:7
|
||||
--> ./tests/integration/test-data/template-injection/pr-425-backstop/action.yml:31:56
|
||||
|
|
||||
28 | - name: case4
|
||||
| ^^^^^^^^^^^ this step
|
||||
29 | uses: azure/powershell
|
||||
29 | uses: azure/powershell@whatever
|
||||
| ------------------------------- action accepts arbitrary code
|
||||
30 | with:
|
||||
31 | inlineScript: Get-AzVM -ResourceGroupName "${{ inputs.expandme }}"
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inputs.expandme may expand into attacker-controllable code
|
||||
| ------------ via this input ^^^^^^^^^^^^^^^ may expand into attacker-controllable code
|
||||
|
|
||||
= note: audit confidence → Low
|
||||
= note: audit confidence → High
|
||||
```
|
||||
|
||||
This output will be colorized by default when sent to a supporting terminal and
|
||||
|
|
@ -224,6 +223,36 @@ disable output colorization by setting `NO_COLOR=1` in their environment.
|
|||
|
||||
This format can also be explicitly selected with `--format=plain`.
|
||||
|
||||
#### Audit documentation links
|
||||
|
||||
By default, `zizmor` includes links to relevant documentation pages
|
||||
for each finding in its plain output format. These links are provided via
|
||||
[OSC 8](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)
|
||||
hyperlinks, which are supported by many modern terminal emulators.
|
||||
|
||||
For example, in the output above, `template-injection` within
|
||||
`error[template-injection]: ...` is a clickable link that takes you to
|
||||
the [template-injection](./audits#template-injection) audit documentation.
|
||||
|
||||
In addition to these OSC 8 links, `zizmor` also includes the full URL
|
||||
as part of each finding _if_ it detects a non-terminal output _or_
|
||||
a CI environment (e.g. GitHub Actions).
|
||||
|
||||
To make this behavior explicir, users can supply the `--show-audit-urls`
|
||||
option:
|
||||
|
||||
```bash
|
||||
# always show audit documentation URLs, even if output is to a terminal
|
||||
zizmor --show-audit-urls=always ...
|
||||
|
||||
# never show audit documentation URLs
|
||||
zizmor --show-audit-urls=never ...
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
`--show-audit-urls=...` is available in `v1.19.0` and later.
|
||||
|
||||
#### Color customization
|
||||
|
||||
When invoked from a terminal, `zizmor` will attempt to enrich its output
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue