Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: add path validation options to restore action#1761

Open
jasongin wants to merge 2 commits into
actions:mainfrom
jasongin:jasongin/cache-path-validation
Open

feat: add path validation options to restore action#1761
jasongin wants to merge 2 commits into
actions:mainfrom
jasongin:jasongin/cache-path-validation

Conversation

@jasongin
Copy link
Copy Markdown

@jasongin jasongin commented May 20, 2026

feat: path validation for restored caches

Wires the new path validation from @actions/cache into the action so workflows are protected against some forms of cache poisoning that plant archive entries (or symlink/hardlink targets) resolving outside the declared path inputs — e.g. ../../etc/..., absolute paths, UNC paths, or symlinks pointing into the runner's workspace.

The actions/cache action defaults to strict-paths: warn for now, so existing workflows get logging automatically without any risk of change to cache extraction. Switching to error opts into pre-extraction rejection of poisoned archives. We should plan to change the default to error in a future major-version update to the action.

New inputs (on both cache and cache/restore)

Input Values Default Behavior
strict-paths off / warn / error warn (eventually error) Selects validator mode. off = no path validation. warn = pre-scan, log a workflow warning, extract anyway. error = pre-scan, reject without extracting.
fail-on-cache-invalid bool false Only relevant when strict-paths: error. true → fail the step. false → treat the rejected cache as a cache miss (no cache-hit output, downstream if: checks behave identically to a normal miss).

Implementation

  • src/utils/actionUtils.ts — getPathValidationInput() parses and normalizes the input (case-insensitive, typo-safe fallback to warn).
  • src/restoreImpl.ts — forwards pathValidation in the DownloadOptions object passed to cache.restoreCache(...), and wraps the call in a try/catch:
    • Errors are detected by err.name === "CacheIntegrityError" + .code read off the error object (intentionally not instanceof, so the check survives the CJS/ESM stub seam between Jest and the bundled runtime).
    • If fail-on-cache-invalid: true → rethrow as a decorated error.
    • Otherwise → logWarning and return; cache-hit is deliberately left unset so the discard is indistinguishable from a normal cache miss.
  • src/constants.ts — two new Inputs enum entries.
  • src/utils/testUtils.ts — setInputs plumbed for the new inputs.
  • action.yml, restore/action.yml, README.md, restore/README.md, RELEASES.md — documented.

Dependency / version

  • @actions/cache: ^5.0.5^6.1.0 (introduces the validation surface; brings in tar@^7.5.15).
  • Action version: 5.0.4 → 5.1.0 (additive — no behavior change for any cache that doesn't contain off-root entries).

Tests

  • tests/actionUtils.test.ts — 9 cases covering getPathValidationInput (defaults, case folding, unknown-value fallback, env-var resolution).
  • tests/restoreImpl.test.ts — 9 new cases covering: forwarding the option to the toolkit for each mode, integrity-error → cache-miss default, integrity-error + fail-on-cache-invalid → rethrow, non-integrity errors propagate unchanged, parse-error and missing-.code variants, and the assertion that cache-hit is never set when an integrity error is rethrown.
  • tests/restore.test.ts, tests/restoreOnly.test.ts — updated to assert the option is forwarded, with getPathValidationInput spied via jest.requireActual (the default auto-mock returns undefined, which would silently pass thanks to deep-equality quirks).
  • @actions/cache@6 is ESM-only and Jest's CJS resolver can't load it directly. Production builds are fine (bundled by @vercel/ncc, which handles ESM deps), but tests need a CJS-compatible surface, so the PR adds tests/mocks/actions-cache.ts — a CJS stub wired up via moduleNameMapper in jest.config.js. All types are re-exported from the real @actions/cache package via import type, and every runtime value is annotated typeof Cache.X, so any signature drift in the real package fails the build.

E2E workflow

Added .github/workflows/path-validation-e2e.yml — a matrix that saves a legitimate cache, saves a poisoned one via the toolkit's internal APIs, and exercises all three strict-paths values across Ubuntu / macOS / Windows runners. Trigger is workflow_dispatch only, since the 39-job matrix is too expensive to run on every PR.

Bundled dist

All four ncc bundles (restore, save, restore-only, save-only) regenerated against the new toolkit. Diff is large but mechanical.

Depends on

@actions/[email protected] from actions/toolkit#2414

  • ⚠️ Builds of this PR will fail until that PR is merged and the package is published.

Follow-ups (not in this PR)

  • Flip strict-paths default from warn to error in a future major version.
  • Publish strict-paths: error adoption guide for high-trust workflows.

@jasongin jasongin requested a review from a team as a code owner May 20, 2026 20:14
Copilot AI review requested due to automatic review settings May 20, 2026 20:14
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds client-side path validation wiring for cache restores, exposing new inputs to control validation strictness and how integrity failures are handled, alongside a toolkit upgrade and expanded test coverage.

Changes:

  • Add new inputs strict-paths and fail-on-cache-invalid, forward them into @actions/cache.restoreCache, and handle CacheIntegrityError.
  • Upgrade @actions/cache dependency and adjust Jest to work with the toolkit’s ESM-only packaging via a CJS stub.
  • Add/extend unit tests plus an E2E workflow and a detailed test plan for path validation.
Show a summary per file
File Description
tsconfig.json Excludes __tests__ from TS compilation.
src/utils/testUtils.ts Adds test helpers for new inputs.
src/utils/actionUtils.ts Adds input parsing for strict-paths.
src/restoreImpl.ts Forwards validation mode to toolkit and handles integrity errors.
src/constants.ts Adds new input constants for the action.
restore/action.yml Documents new inputs for the restore-only action.
restore/README.md Documents new inputs and behavior.
package.json Bumps action version and upgrades @actions/cache.
jest.config.js Redirects @actions/cache imports to a local CJS stub for tests.
docs/path-validation-test-plan.md Adds a test plan and local development notes for path validation.
action.yml Documents new inputs for the main action.
tests/restoreOnly.test.ts Updates restore-only tests to expect pathValidation.
tests/restoreImpl.test.ts Adds/updates tests for pathValidation wiring and integrity handling.
tests/restore.test.ts Updates restore tests to expect pathValidation.
tests/e2e/save-poisoned-cache.mjs Adds helper to upload a “poisoned” cache during E2E runs.
tests/actionUtils.test.ts Adds tests for getPathValidationInput().
tests/mocks/actions-cache.ts Adds a CJS-compatible stub surface for @actions/cache in Jest.
RELEASES.md Adds 5.1.0 release notes for the new feature set.
README.md Documents new inputs and their security implications.
.github/workflows/path-validation-e2e.yml Adds a manual E2E workflow matrix for path validation behavior.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 18/25 changed files
  • Comments generated: 7

Comment thread src/restoreImpl.ts
Comment thread src/restoreImpl.ts
Comment thread src/utils/actionUtils.ts Outdated
Comment thread src/utils/actionUtils.ts Outdated
Comment thread src/restoreImpl.ts
Comment thread docs/path-validation-test-plan.md Outdated
Comment thread .github/workflows/path-validation-e2e.yml Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants