> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pipefort.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CICD-SEC-4 — Caching enabled in a publishing workflow

> A build cache restored in a workflow that also publishes can carry a poisoned entry into the released artifact.

| Field      | Value                                                                                                                                        |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Category   | `CICD-SEC-4`                                                                                                                                 |
| Severity   | **MEDIUM**                                                                                                                                   |
| Confidence | MEDIUM                                                                                                                                       |
| OWASP      | [CICD-SEC-4: Poisoned Pipeline Execution](https://owasp.org/www-project-top-10-ci-cd-security-risks/CICD-SEC-04-Poisoned-Pipeline-Execution) |
| Auto-fix   | ✗                                                                                                                                            |

## What the check does

Flags dependency caching — `actions/cache`, or a `setup-*` action's `cache:`
option — in a workflow that **also publishes** a release-shaped artifact
(release upload, container push, `npm/cargo/gem publish`, GoReleaser, …).

This is broader than [SLSA-BUILD-L3 cache poisoning](/rules/slsa-build-l3-cache-poisoning),
which only covers a `pull_request_target` cache key built from PR-controlled
input.

## Why it matters

GitHub Actions caches are shared across a repository's workflows and branches.
A lower-trust workflow (for example one triggered by a fork's pull request) can
write a cache entry that a later, higher-trust publishing run restores — and the
poisoned content flows straight into the released artifact. Because the cache is
keyed by content the attacker can influence, this is a supply-chain path that
SHA-pinning your actions does not close.

## Safe alternative

Keep the publishing path from restoring a mutable cache:

```yaml theme={null}
- uses: actions/cache@<sha>
  with:
    path: ~/.cache
    key: build-${{ hashFiles('**/lock') }}
    lookup-only: true        # ← restore for hit/miss metrics only, never populate the build
```

Or drop the cache entirely on release builds, and scope caching to the
non-publishing CI workflow.
