diff --git a/.changeset/sentinel-eol-fix.md b/.changeset/sentinel-eol-fix.md new file mode 100644 index 00000000..fd9ccae9 --- /dev/null +++ b/.changeset/sentinel-eol-fix.md @@ -0,0 +1,5 @@ +--- +"node-version": patch +--- + +Security: Improved EOL detection for odd versions (e.g., 19, 21, 23) and legacy versions (<12) to ensure users are correctly warned about unsupported runtimes. diff --git a/src/index.test.ts b/src/index.test.ts index 5d386cbe..1286d265 100644 --- a/src/index.test.ts +++ b/src/index.test.ts @@ -307,11 +307,25 @@ describe("node-version", () => { expect(v.isEOL).toBe(true); }); + test("should check EOL for odd versions (e.g. 21)", () => { + vi.setSystemTime(new Date("2024-06-01")); + mockVersion.node = "21.0.0"; // EOL is 2024-04-10 + const v = getVersion(); + expect(v.isEOL).toBe(true); + }); + + test("should check EOL for very old versions (e.g. 10)", () => { + // 10 is not in the map, but < 12, so should be EOL + mockVersion.node = "10.0.0"; + const v = getVersion(); + expect(v.isEOL).toBe(true); + }); + test("should have current running node major in EOL_DATES if even", () => { const currentMajor = (realVersions.node || "").split(".")[0] || "0"; const isEven = Number(currentMajor) % 2 === 0; - if (isEven) { + if (isEven && Number(currentMajor) >= 12 && Number(currentMajor) <= 24) { expect(EOL_DATES).toHaveProperty(currentMajor); } }); diff --git a/src/index.ts b/src/index.ts index 625ca808..2fae6ff1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,11 +11,19 @@ export type { NodeVersion }; /** * End-of-Life dates for Node.js major versions. + * @see https://github.com/nodejs/Release */ export const EOL_DATES: Record = { + "12": "2022-04-30", + "14": "2023-04-30", + "16": "2023-09-11", + "17": "2022-06-01", "18": "2025-04-30", + "19": "2023-06-01", "20": "2026-04-30", + "21": "2024-04-10", "22": "2027-04-30", + "23": "2025-06-01", "24": "2028-04-30", }; @@ -24,8 +32,16 @@ export const EOL_DATES: Record = { */ const checkEOL = (major: string): boolean => { const eolDate = EOL_DATES[major]; - if (!eolDate) return false; - return new Date() > new Date(eolDate); + if (eolDate) { + return new Date() > new Date(eolDate); + } + // Fail-safe for very old versions not in the map + // If the major version is less than the smallest key in EOL_DATES, it is definitely EOL. + const numericMajor = Number(major); + if (!Number.isNaN(numericMajor) && numericMajor < 12) { + return true; + } + return false; }; /**