The default `cache:` key for dependencies is a massive security risk. It's shared across branches and pipelines by default. A compromised PR can poison your main branch builds.
You must lock it down.
Use `CI_COMMIT_REF_SLUG` or a hash of your lockfile. Never use `cache: key: "$CI_COMMIT_REF_SLUG"` alone for npm/pip/yarn—it's not branch-safe enough. Hash the actual dependency file.
Example for npm:
```yaml
cache:
key:
files:
- package-lock.json
prefix: $CI_COMMIT_REF_SLUG
paths:
- node_modules/
```
Critical configs most posts ignore:
* `policy: pull-push` for the main branch, `policy: pull` for feature branches. Stops PRs from writing.
* Set `interruptible: true` on cache jobs. Prevents corrupt caches.
* Use separate caches for build outputs and dependencies. Never mix them.
Performance numbers (medium monorepo):
- Default shared cache: ~45s download, risk of poisoning.
- Lockfile-hashed per branch: ~45s download, zero cross-branch risk.
- No cache: ~210s install every time.
The trade-off is storage cost for security. Worth it.
Least privilege is not a suggestion.