Skip to content

Commit

Permalink
feat: composite action support (#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
woodruffw authored Dec 25, 2024
1 parent d1c9004 commit c28d44c
Show file tree
Hide file tree
Showing 31 changed files with 1,002 additions and 316 deletions.
75 changes: 75 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ clap-verbosity-flag = { version = "3.0.2", features = [
"tracing",
], default-features = false }
etcetera = "0.8.0"
flate2 = "1.0.35"
github-actions-models = "0.17.0"
http-cache-reqwest = "0.15.0"
human-panic = "2.0.1"
Expand All @@ -44,6 +45,7 @@ serde_json = "1.0.134"
serde_yaml = "0.9.34"
# TODO remove pending https://github.com/tree-sitter/tree-sitter/pull/4034
streaming-iterator = "0.1.9"
tar = "0.4.43"
terminal-link = "0.1.0"
tokio = { version = "1.42.0", features = ["rt-multi-thread"] }
tracing = "0.1.41"
Expand Down
5 changes: 3 additions & 2 deletions docs/audits.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ Use [encrypted secrets] instead of hardcoded credentials.

| Type | Examples | Introduced in | Works offline | Enabled by default |
|----------|-----------------------|---------------|----------------|--------------------|
| Workflow | [impostor-commit.yml] | v0.1.0 |||
| Workflow, Action | [impostor-commit.yml] | v0.1.0 |||

[impostor-commit.yml]: https://github.com/woodruffw/gha-hazmat/blob/main/.github/workflows/impostor-commit.yml

Expand Down Expand Up @@ -361,6 +361,7 @@ the action if one is available, or remove the action's usage entirely.
|----------|---------------------|---------------|----------------|--------------------|
| Workflow | [ref-confusion.yml] | v0.1.0 |||


[ref-confusion.yml]: https://github.com/woodruffw/gha-hazmat/blob/main/.github/workflows/ref-confusion.yml

Detects actions that are pinned to confusable symbolic refs (i.e. branches
Expand Down Expand Up @@ -431,7 +432,7 @@ there are steps you can take to minimize their risk:

| Type | Examples | Introduced in | Works offline | Enabled by default |
|----------|--------------------------|---------------|----------------|--------------------|
| Workflow | [template-injection.yml] | v0.1.0 |||
| Workflow, Action | [template-injection.yml] | v0.1.0 |||

[template-injection.yml]: https://github.com/woodruffw/gha-hazmat/blob/main/.github/workflows/template-injection.yml

Expand Down
6 changes: 5 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ where `filename.yml` is the base filename of the workflow, and `line` and
location to ignore. If one or both are absent, then the rule applies to the
entire file or entire line.

By example, here is a configuration file with two different audit ignore
!!! important

Composite action findings cannot be ignored via `zizmor.yml` currently.

For example, here is a configuration file with two different audit ignore
rule groups:

```yaml title="zizmor.yml"
Expand Down
51 changes: 33 additions & 18 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,47 @@ You should see something like this:

Here are some different ways you can run `zizmor` locally:

=== "On one or more files"
=== "On one or more workflows"

You can run `zizmor` on one or more workflows as explicit inputs:
You can run `zizmor` on one or more workflows or composite actions as
explicit inputs:

```bash
zizmor ci.yml tests.yml lint.yml
zizmor ci.yml tests.yml lint.yml action.yml
```

These can be in any directory as well:

```
zizmor ./subdir/ci.yml ../sibling/tests.yml
zizmor ./subdir/ci.yml ../sibling/tests.yml ./action/action.yml
```

=== "On one or more directories"
=== "On one or more local repositories"

If you have multiple workflows in a single directory, `zizmor` will
discover them:
!!! tip

```bash
# somewhere/ contains ci.yml and tests.yml
zizmor somewhere/
```
Composite action support was added in v1.0.0.

!!! tip

Pass `--collect=workflows-only` to disable collecting composite actions.

Moreover, if the specified directory contains a `.github/workflows`
subdirectory, `zizmor` will discover workflows there:
When given one or more local directories, `zizmor` will treat each as a
GitHub repository and attempt to discover workflows defined under the
`.github/workflows` subdirectory for each. `zizmor` will also walk each
directory to find composite action definitions (`action.yml` in any
subdirectory).

```bash
# my-local-repo/ contains .github/workflows/{ci,tests}.yml
zizmor my-local-repo/
# repo-a/ contains .github/workflows/{ci,tests}.yml
# as well as custom-action/action.yml
zizmor repo-a/

# or with multiple directories
zizmor repo-a/ ../../repo-b/

# collect only workflows, not composite actions
zizmor --collect=workflows-only
```

=== "On one or more remote repositories"
Expand All @@ -55,11 +66,15 @@ Here are some different ways you can run `zizmor` locally:
Private repositories can also be audited remotely, as long
as your GitHub API token has sufficient permissions.

`zizmor` can also fetch workflows directly from GitHub, if given a
GitHub API token via `GH_TOKEN` or `--gh-token`:
!!! tip

Pass `--collect=workflows-only` to disable collecting composite actions.

`zizmor` can also fetch workflows and actions directly from GitHub, if
given a GitHub API token via `GH_TOKEN` or `--gh-token`:

```bash
# audit all workflows in woodruffw/zizmor
# audit all workflows and composite actions in woodruffw/zizmor
# assumes you have `gh` installed
zizmor --gh-token=$(gh auth token) woodruffw/zizmor
```
Expand Down
2 changes: 2 additions & 0 deletions docs/snippets/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Options:
Filter all results below this confidence [possible values: unknown, low, medium, high]
--cache-dir <CACHE_DIR>
The directory to use for HTTP caching. By default, a host-appropriate user-caching directory will be used
--collect <COLLECT>
Control which kinds of inputs are collected for auditing [default: all] [possible values: all, workflows-only, actions-only]
-h, --help
Print help (see more with '--help')
-V, --version
Expand Down
70 changes: 68 additions & 2 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,72 @@ description: Usage recipes for running zizmor locally and in CI/CD.

# Usage Recipes

## Input collection

Before auditing, `zizmor` performs an input collection phase.

There are three input sources that `zizmor` knows about:

1. Individual workflow and composite action files, e.g. `foo.yml` and
`my-action/action.yml`;
2. "Local" GitHub repositories in the form of a directory, e.g. `my-repo/`;
3. "Remote" GitHub repositories in the form of a "slug", e.g.
`pypa/sampleproject`.

!!! tip

By default, a remote repository will be audited from the `HEAD`
of the default branch. To control this, you can append a `git`
reference to the slug:

```bash
# audit at HEAD on the default branch
zizmor example/example

# audit at branch or tag `v1`
zizmor example/example@v1

# audit at a specific SHA
zizmor example/example@abababab...
```

!!! tip

Remote auditing requires Internet access and a GitHub API token.
See [Operating Modes](#operating-modes) for more information.

`zizmor` can audit multiple inputs in the same run, and different input
sources can be mixed and matched:

```bash
# audit a single local workflow, an entire local repository, and
# a remote repository all in the same run
zizmor ../example.yml ../other-repo/ example/example
```

When auditing local and/or remote repositories, `zizmor` will collect both
workflows (e.g. `.github/workflows/ci.yml`) **and** action definitions
(e.g. `custom-action/foo.yml`) by default. To disable one or the other,
you can use the `--collect=...` option.

```bash
# collect everything (the default)
zizmor --collect=all example/example

# collect only workflows
zizmor --collect=workflows-only example/example

# collect only actions
zizmor --collect=actions-only example/example
```

!!! tip

`--collect=...` only controls input collection from repository input
sources. In other words, `zizmor --collect=actions-only workflow.yml`
*will* audit `workflow.yml`, since it was passed explicitly and not
collected indirectly.

## Operating Modes

Some of `zizmor`'s audits require access to GitHub's API.
Expand Down Expand Up @@ -98,8 +164,8 @@ sensitive `zizmor`'s analyses are:

This persona is ideal for finding things that are a good idea
to clean up or resolve, but are likely not immediately actionable
security findings (or are actionable, but indicate a intentional
security decision by the workflow author).
security findings (or are actionable, but suggest a intentional
security decision by the workflow/action author).

For example, using the pedantic persona will flag the following
with an `unpinned-uses` finding, since it uses a symbolic reference
Expand Down
4 changes: 2 additions & 2 deletions src/audit/artipacked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use github_actions_models::{
};
use itertools::Itertools;

use super::{audit_meta, WorkflowAudit};
use super::{audit_meta, Audit};
use crate::{
finding::{Confidence, Finding, Persona, Severity},
state::AuditState,
Expand Down Expand Up @@ -44,7 +44,7 @@ impl Artipacked {
}
}

impl WorkflowAudit for Artipacked {
impl Audit for Artipacked {
fn new(_state: AuditState) -> Result<Self> {
Ok(Self)
}
Expand Down
4 changes: 2 additions & 2 deletions src/audit/cache_poisoning.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::audit::{audit_meta, WorkflowAudit};
use crate::audit::{audit_meta, Audit};
use crate::finding::{Confidence, Finding, Severity};
use crate::models::{Job, Step, Steps, Uses};
use crate::state::AuditState;
Expand Down Expand Up @@ -517,7 +517,7 @@ impl CachePoisoning {
}
}

impl WorkflowAudit for CachePoisoning {
impl Audit for CachePoisoning {
fn new(_: AuditState) -> anyhow::Result<Self>
where
Self: Sized,
Expand Down
Loading

0 comments on commit c28d44c

Please sign in to comment.