github / github/vscode-github-actions
Commit-pinned actions can be reported as unresolved even when action.yml exists
- Lingua principale
- TypeScript
- Stelle
- 660
- Fork
- 213
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Descrizione
## Summary
The GitHub Actions extension can report commit-pinned actions as unresolved even when the action repository, ref, and `action.yml` are valid and publicly reachable.
This affects workflows that pin actions by full commit SHA for supply-chain hardening. The workflow is valid and GitHub Actions can run it, but the VS Code Problems panel reports:
```text
Unable to resolve action `actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd`, repository or version not found
Unable to resolve action `step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5`, repository or version not found
```
This is related in symptom to #143, but the failure mode is different: this is not a network timeout and not a missing tag. These are full commit SHA refs whose `action.yml` resolves successfully via GitHub.
## Environment
- Extension: `github.vscode-github-actions` `0.31.5`
- VS Code: `1.120.0`, Windows x64
- Also reproduced in Google Antigravity `1.107.0`, which uses the same extension version (`github.vscode-github-actions@0.31.5`)
- OS: Windows
## Reproduction
Create or open a workflow containing commit-pinned actions, for example:
```yaml
steps:
- name: Harden the runner
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
```
Open the workflow in VS Code with the GitHub Actions extension enabled.
## Actual behavior
The Problems panel shows errors like:
```text
Unable to resolve action `step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5`, repository or version not found
Unable to resolve action `actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd`, repository or version not found
```
## Expected behavior
The extension should resolve action metadata for full SHA refs the same way it does for tags/branches, as long as `action.yml` or `action.yaml` exists at that ref.
At minimum, it should not emit `repository or version not found` when the repo/ref/action metadata file can be fetched successfully.
## Evidence that the refs are valid
The tags resolve to the same commits:
```console
$ git ls-remote --tags https://github.com/actions/checkout.git refs/tags/v6.0.2
de0fac2e4500dabe0009e67214ff5f5447ce83dd refs/tags/v6.0.2
$ git ls-remote --tags https://github.com/step-security/harden-runner.git refs/tags/v2.19.3
ab7a9404c0f3da075243ca237b5fac12c98deaa5 refs/tags/v2.19.3
```
The GitHub Contents API also resolves `action.yml` at both refs:
```text
GET /repos/actions/checkout/contents/action.yml?ref=de0fac2e4500dabe0009e67214ff5f5447ce83dd -> 200
GET /repos/step-security/harden-runner/contents/action.yml?ref=ab7a9404c0f3da075243ca237b5fac12c98deaa5 -> 200
```
These workflows also run successfully in GitHub Actions, so this appears isolated to the extension/language-server validation path.
## Why this matters
Security tooling such as OpenSSF Scorecard rewards pinning GitHub Actions by immutable SHA. Replacing SHAs with tags quiets the editor diagnostic but weakens supply-chain hardening and can reintroduce `PinnedDependencies` findings.
So the practical workaround is either to ignore Problems panel noise or to weaken action pinning. Neither is ideal.
## Suspected cause
In the built extension bundle, the language server fetch path appears to call GitHub's Contents API for action metadata and returns `undefined` on failure:
```js
repos.getContent({ owner, repo, ref, path: "action.yml" })
// fallback to action.yaml on 404
```
Then validation emits:
```text
Unable to resolve action ``, repository or version not found
```
For full SHA refs, the action metadata is available, but the extension still reaches the unresolved path in some installations. I could not reproduce a failure with direct API calls using the same refs, which suggests the language server may be mishandling the ref, cache key, auth/API state, or a transient API error and collapsing it into a permanent `repository or version not found` diagnostic.
## Suggested fix
A robust fix would be:
1. Keep the existing Contents API lookup for `action.yml` and `action.yaml`.
2. When the ref looks like a full commit SHA (`/^[0-9a-f]{40}$/i`) and the Contents API path fails or returns no metadata, retry against the raw content URL before reporting a diagnostic:
```ts
async function fetchRawActionMetadata(action: ActionRef): Promise {
for (const filename of ["action.yml", "action.yaml"]) {
const path = action.path ? `${action.path}/${filename}` : filename;
const url = `https://raw.githubusercontent.com/${action.owner}/${action.name}/${action.ref}/${path}`;
const response = await fetch(url);
if (response.ok) return await response.text();
}
return undefined;
}
```
3. Only emit `repository or version not found` if both the Contents API and the raw fallback fail.
4. Ideally, distinguish network/auth/API errors from real repo/ref-not-found errors in the diagnostic message.
I tested this fallback locally by patching the bundled language-server files (`dist/server-node.js` and `dist/server-web.js`) to try `raw.githubusercontent.com/.../action.yml` and `action.yaml` before returning unresolved metadata. After reloading the editor, the SHA-pinned actions can be resolved without replacing SHAs with mutable tags.
## Additional notes
The extension should continue to validate inputs after metadata is fetched. The proposed fallback only changes the metadata retrieval path for valid immutable refs; it does not suppress validation generally.
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.