Volta extends resolution in getNodeVersionFromFile has no cycle detection, recursing until stack overflow
I maintainer di solito rispondono entro 8 giorni
@v-gowridurgad ci sta già lavorando.
Dal 11/9/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Summary
getNodeVersionFromFile follows Volta extends recursively with no cycle detection, so a self-referential or mutually-referential volta.extends chain causes unbounded recursion and crashes the action with a stack overflow instead of a clear error.
Location
- File:
src/util.ts - Function:
getNodeVersionFromFile(versionFilePath: string) - Code path:
if (manifest.volta?.extends) {
const extendedFilePath = path.resolve(
path.dirname(versionFilePath),
manifest.volta.extends
);
core.info('Resolving node version from ' + extendedFilePath);
return getNodeVersionFromFile(extendedFilePath);
}
No visited-path set or depth limit is threaded through the recursion.
Problem
Volta workspaces support {"volta": {"extends": "./base/package.json"}}. If the target (transitively) points back to a file already on the resolution stack — e.g. package.json with "extends": "./package.json" (typo), or a.json → b.json → a.json — the function recurses forever until V8 throws RangeError: Maximum call stack size exceeded. The user gets an opaque stack-overflow failure rather than a diagnostic naming the cycle.
Trigger / Reproduction
Based on static analysis (no workflow run performed):
- Set
node-version-fileto apackage.jsoncontaining:
or a two-file cycle{"volta": {"extends": "./package.json"}}a.json↔b.jsonviavolta.extends. - Run the action.
getNodeVersionFromFileresolvesextends, re-enters itself with the same path, and never terminates normally.
Note: this is a static-analysis finding; I did not execute a workflow against a cyclic fixture.
Expected Behavior
Cyclic volta.extends should fail fast with a clear error naming the files in the cycle (e.g. Detected cyclic volta.extends: a.json -> b.json -> a.json), consistent with how missing files already throw The specified node version file at: ... does not exist.
Actual Behavior
Unbounded recursion until stack exhaustion, producing an unactionable RangeError with no mention of the offending extends chain.
Impact
- A one-character typo in
volta.extendsturns a configuration mistake into an opaque action crash, costing debugging time. - No data-loss risk, but the failure mode hides the actual cause (cycle) behind a generic engine error.
Suggested Direction
- Thread a
seen: Set<string>(resolved absolute paths) throughgetNodeVersionFromFile, checking before recursing and throwing a descriptive cycle error. Alternatively cap recursion depth with the same diagnostic. Either preserves current behavior for acyclic chains.
Evidence
- Source via API:
src/util.tsVolta-extends branch shows direct unconditional recursion with no guard; neighboring branches (missing file, non-JSON/TOML fallthrough) all have explicit handling, highlighting the gap. - Duplicate check: issue search for
volta extends cycle recursionreturnstotal_count: 0, and the open-issue list contains no extends-cycle report (nearest is.nvmrccomment parsing) — no apparent duplicate.
What happened
Unbounded recursion on cyclic Volta extends as detailed above.
Expected behavior
Fast, descriptive cycle error instead of stack overflow.
Steps to reproduce
Point node-version-file at a self- or mutually-referential Volta extends fixture and observe getNodeVersionFromFile re-enter indefinitely (static path; runtime stack overflow implied).
reproducible code
// package.json
{"volta": {"extends": "./package.json"}}
- uses: actions/setup-node@v4
with:
node-version-file: package.json
manifest.yaml
N/A
Versions
- actions/setup-node: current
main(verified via API,src/util.ts) - Node: N/A (static analysis finding)
Classification
- FACT: Volta
extendsrecursion has no visited-set or depth cap (verified in source via API). - INFERENCE: cyclic fixtures therefore recurse until stack exhaustion.
- HYPOTHESIS: a visited-path guard produces a clear error with no change to valid chains.
- Lingua principale
- TypeScript
- Stelle
- 5k
- Fork
- 1.7k
- Merge medio
- 13g 7h
- PR unite (30g)
- 5
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Nessuna guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di actions/setup-node
-
feature request
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
actions/setup-node#1531 · 1 commento · 4 reazioni ·
I maintainer di solito rispondono entro 8 giorni
-
feature request
Difficoltà 5/5 Più di una settimana Idoneità per principianti 30/100
actions/setup-node#1634 · 1 commento ·
I maintainer di solito rispondono entro 8 giorni
-
`npm config get cache` fails with `EBADDEVENGINES` when requiring newer npm versions in `devEngines`Apertafeature request
Difficoltà 4/5 3-5 giorni Idoneità per principianti 52/100
actions/setup-node#1553 · 14 commenti · 2 reazioni ·
I maintainer di solito rispondono entro 8 giorni
-
feature request
Difficoltà 3/5 1-2 giorni Idoneità per principianti 38/100
actions/setup-node#1428 · 1 commento · 3 reazioni ·
I maintainer di solito rispondono entro 8 giorni
-
feature request
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
actions/setup-node#1422 · 4 commenti ·
I maintainer di solito rispondono entro 8 giorni
Tutte le issue di actions/setup-node
Issue simili
-
Show the error reference on the error pageForse già presa Una pull request collegata a questa issue è aperta o già unita. Apertaenhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
tomjn/coilbox-hub#454 ·
I maintainer di solito rispondono entro 1 giorno
-
Scheduler button hover stateApertafrontend
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
icssc/peterportal-client#1224 · 1 commento ·
-
enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
-
api: spanner
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
googleapis/google-cloud-node#9513 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 92/100
I maintainer di solito rispondono entro 1 giorno