tailscale / tailscale/github-action

sha256sum input is ignored on the use-cache hit path

Open
#313 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
938
Forks
137
PR merge metrics
No merged PRs in 30d

Description

What happened

The sha256sum input is silently ignored when a cached install is restored. Only the fresh-install path verifies the checksum, so pinning sha256sum and enabling use-cache at the same time gives weaker guarantees than the configuration suggests.

Details

In installTailscale() (src/main.ts:341), a cache hit installs and returns before any verification:

if (config.useCache && cacheKey) {
  const cacheHit = await cache.restoreCache([toolPath], cacheKey);
  if (cacheHit) {
    core.info(`Found Tailscale ${config.resolvedVersion} in cache: ${toolPath}`);
    if (runnerOS === runnerWindows) {
      await installTailscaleWindows(config, toolPath, true);
    } else {
      await installCachedBinaries(toolPath, runnerOS);
    }
    return;   // <- returns here; no checksum comparison above this point
  }
}
// Install fresh if not cached

config.sha256Sum is only ever read afterwards, in installTailscaleLinux() (src/main.ts:416-438) and installTailscaleWindows() (src/main.ts:509-523) — both reachable only after that return. So on a cache hit, a user-supplied sha256sum has no effect at all.

Since @actions/cache is a remote cache writable by workflows in the repo, a poisoned or corrupted entry is installed without verification, and the binary then receives the tailnet credentials.

Why this matters

sha256sum is the only way to avoid trusting pkgs.tailscale.com to attest its own artifact — without it, the action fetches the .tgz.sha256 from the same host that serves the .tgz (src/main.ts:416-425), so a compromised CDN could serve a matching bad pair. Users who supply the input specifically to move that trust anchor into their own repo currently must also set use-cache: false to get the verification they asked for, which costs them the caching benefit entirely. The two features aren't composable today.

It's also a bit of a footgun: the config reads as "pinned and verified," and nothing in the log indicates the pin was skipped on a cache hit.

Expected

A supplied sha256sum is honored on every install path. Concretely, on a cache hit, hash the restored artifact and compare against config.sha256Sum, treating a mismatch as a cache miss (fall through to a fresh, verified download) rather than failing the run. calculateFileSha256() (src/main.ts:394) already exists for this. That would make use-cache: true + sha256sum safe to combine.

Workaround

Set use-cache: false whenever sha256sum is supplied, which is what we do.

Version

tailscale/github-action@v4

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/main.ts at installTailscale(), the cache-hit return, and calculateFileSha256() around line 394; compare these with the checksum handling in installTailscaleLinux() and installTailscaleWindows(). Verify that a matching cached artifact proceeds, while a checksum mismatch falls through to a fresh verified download, and confirm the existing installation behavior remains intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
github-actions, typescript
Domain
devops, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.