Repository: zizmorcore/zizmor (Rust)

Issue:
[BUG]: "API misuse" panic when using env context in `with` option
### Pre-submission checks

- [X] I am **not** filing a feature request. These should be filed via the feature request form instead.
- [X] I have looked through the [open issues](https://github.com/woodruffw/zizmor/issues?q=is%3Aissue+is%3Aopen+) for a duplicate report.

### Expected behavior

No crash.

### Actual behavior

Panic: "API misuse: can't call env_is_static on a uses: step"

### Reproduction steps

Ran 1.0.1 release (installed from crate) on this minimal workflow file:

```yaml
name: Test
on:
  issue_comment:
    types: [created]
jobs:
  stop:
    runs-on: ubuntu-latest
    env:
      COMMENT_ID: '1234'
    steps:
      - uses: actions/github-script@v7
        with:
          script: console.log("${{ env.COMMENT_ID }}")
```

### Logs

```plain text
2025-01-10T18:29:07.600718Z DEBUG zizmor::state: using cache directory: "(redacted)"
2025-01-10T18:29:07.601333Z DEBUG zizmor::config: no config discovered; loading default
2025-01-10T18:29:07.601340Z DEBUG zizmor::config: loaded config: Config { rules: {} }
2025-01-10T18:29:07.601350Z  WARN zizmor: skipping impostor-commit: can't run without a GitHub API token
2025-01-10T18:29:07.601355Z  WARN zizmor: skipping ref-confusion: can't run without a GitHub API token
2025-01-10T18:29:07.601359Z  WARN zizmor: skipping known-vulnerable-actions: can't run without a GitHub API token
[00:00:00] ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ crash.yml
  ↳ ⠁ audit{input=Workflow(file:///(redacted)/.github/workflows/crash.yml)}
Well, this is embarrassing.

zizmor had a problem and crashed. To help us diagnose the problem you can send us a crash report.

We have generated a report file at "/tmp/report-d69984a3-db30-420b-8efe-8dcfaf950536.toml". Submit an issue or email with the subject of "zizmor Crash Report" and include the report as an attachment.

- Homepage: https://github.com/woodruffw/zizmor
- Authors: William Woodruff <william@yossarian.net>

We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.

Thank you kindly!
```


### Additional context

Report file:

```toml
"name" = "zizmor"
"operating_system" = "Ubuntu 20.4.0 (focal) [64-bit]"
"crate_version" = "1.0.1"
"explanation" = """
Panic occurred in file '(redacted)/rust/1.80.1/registry/src/index.crates.io-6f17d22bba15001f/zizmor-1.0.1/src/models.rs' at line 445
"""
"cause" = "API misuse: can't call env_is_static on a uses: step"
"method" = "Panic"
"backtrace" = """
   0:     0x55b82251e7a6 - rust_begin_unwind
   1:     0x55b82216f8f2 - core::panicking::panic_fmt::ha02418e5cd774672
   2:     0x55b8226e82c1 - <zizmor::audit::template_injection::TemplateInjection as zizmor::audit::Audit>::audit_step::hd08f123136695883
   3:     0x55b8226ea672 - zizmor::audit::Audit::audit_normal_job::h52c34660162943ad
   4:     0x55b8226eadbd - zizmor::audit::Audit::audit_workflow::h59346f3f34bbc816
   5:     0x55b8226f09af - zizmor::audit::Audit::audit::hf549cdc7d3c6f34c
   6:     0x55b8225f3c59 - zizmor::run::h352aa5283b40acc2
   7:     0x55b8225e4968 - zizmor::main::ha4629a9fcae4548d
   8:     0x55b822699e03 - std::sys_common::backtrace::__rust_begin_short_backtrace::h8852b976b62d62ed
   9:     0x55b8225e476f - main
  10:     0x7f05624e9083 - __libc_start_main
  11:     0x55b8221957ae - _start
  12:                0x0 - <unresolved>
"""
```



Discussion:
Thanks @ZoogieZork! This looks like a bad assumption in the env expansion code; taking a look now.
Ah, this was overly conservative: there's no `env:` on a `uses:` step, but that doesn't matter since we can just skip it while still collecting the parent environment blocks.

Thanks a ton for providing a small repro case -- that made it _very_ easy to pin this down!
This will be fixed with #420.
Thanks again! Let me know if this is a blocker and I can perform a release; otherwise this will be rolled into the next release I do whenever I do it.
Not a blocker; thanks for the quick response!



Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 663c5cb3e..663e9863b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,6 +31,8 @@ jobs:
 
     - uses: Swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2
 
+    - uses: astral-sh/setup-uv@887a942a15af3a7626099df99e897a18d9e5ab3a # v5.1.0
+
     - name: Test
       run: cargo test
 
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 33be9514a..95958ae21 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -18,6 +18,8 @@ of `zizmor`.
 
 * The [template-injection] audit no longer consider `github.server_url`
   dangerous (#412)
+* The [template-injection] audit no longer crashes when evaluating
+  the static-ness of an environment for a `uses:` step (#420)
 
 ## v1.0.1
 
diff --git a/src/models.rs b/src/models.rs
index bfb4dca35..f19311421 100644
--- a/src/models.rs
+++ b/src/models.rs
@@ -444,9 +444,9 @@ impl StepCommon for Step<'_> {
         let mut envs = vec![];
 
         match &self.body {
-            workflow::job::StepBody::Uses { .. } => {
-                panic!("API misuse: can't call env_is_static on a uses: step")
-            }
+            // `uses:` does not have an `env:` but its parent
+            // job and workflow might, so we skip instead of failing.
+            workflow::job::StepBody::Uses { .. } => (),
             workflow::job::StepBody::Run {
                 run: _,
                 working_directory: _,


Test patch:
diff --git a/tests/snapshot.rs b/tests/snapshot.rs
index e96606c42..4060b2487 100644
--- a/tests/snapshot.rs
+++ b/tests/snapshot.rs
@@ -273,6 +273,12 @@ fn template_injection() -> Result<()> {
         ))
         .run()?);
 
+    insta::assert_snapshot!(zizmor()
+        .workflow(workflow_under_test(
+            "template-injection/issue-418-repro.yml"
+        ))
+        .run()?);
+
     Ok(())
 }
 
diff --git a/tests/snapshots/snapshot__template_injection-7.snap b/tests/snapshots/snapshot__template_injection-7.snap
new file mode 100644
index 000000000..4c02f07ca
--- /dev/null
+++ b/tests/snapshots/snapshot__template_injection-7.snap
@@ -0,0 +1,6 @@
+---
+source: tests/snapshot.rs
+expression: "zizmor().workflow(workflow_under_test(\"template-injection/issue-418-repro.yml\")).run()?"
+snapshot_kind: text
+---
+No findings to report. Good job! (1 suppressed)
diff --git a/tests/test-data/template-injection/issue-418-repro.yml b/tests/test-data/template-injection/issue-418-repro.yml
new file mode 100644
index 000000000..934ea1ed3
--- /dev/null
+++ b/tests/test-data/template-injection/issue-418-repro.yml
@@ -0,0 +1,15 @@
+# reproduction case for https://github.com/woodruffw/zizmor/issues/418
+
+name: Test
+on:
+  issue_comment:
+    types: [created]
+jobs:
+  stop:
+    runs-on: ubuntu-latest
+    env:
+      COMMENT_ID: "1234"
+    steps:
+      - uses: actions/github-script@v7
+        with:
+          script: console.log("${{ env.COMMENT_ID }}")