1 | A utility to fetch or build patched Node binaries used by [pkg](https://github.com/vercel/pkg) to generate executables. This repo hosts prebuilt binaries in [Releases](https://github.com/vercel/pkg-fetch/releases).
|
2 |
|
3 | ## Binary Compatibility
|
4 |
|
5 | | Node | Platform | Architectures | Minimum OS version |
|
6 | | --------------------------------------------------------------------------------- | ----------- | ------------------------- | --------------------------------------------------------------------------------- |
|
7 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | alpine | x64, arm64 | 3.7.3, other distros with musl libc >= 1.1.18 |
|
8 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linux | x64 | Enterprise Linux 7, Ubuntu 14.04, Debian jessie, other distros with glibc >= 2.17 |
|
9 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linux | arm64 | Enterprise Linux 8, Ubuntu 18.04, Debian buster, other distros with glibc >= 2.27 |
|
10 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linuxstatic | x64, arm64 | Any distro with Linux Kernel >= 2.6.32 (>= 3.10 strongly recommended) |
|
11 | | 16, 18 | linuxstatic | armv7<sup>[2](#fn2)</sup> | Any distro with Linux Kernel >= 2.6.32 (>= 3.10 strongly recommended) |
|
12 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | macos | x64 | 10.13 |
|
13 | | 14, 16, 18 | macos | arm64<sup>[3](#fn3)</sup> | 11.0 |
|
14 | | 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | win | x64 | 8.1 |
|
15 | | 14, 16, 18 | win | arm64 | 10 |
|
16 |
|
17 | <em id="fn1">[1]</em>: end-of-life, may be removed in the next major release.
|
18 |
|
19 | <em id="fn2">[2]</em>: best-effort basis, not semver-protected.
|
20 |
|
21 | <em id="fn3">[3]</em>: [mandatory code signing](https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-universal-apps-release-notes) is enforced by Apple.
|
22 |
|
23 | ## Security
|
24 |
|
25 | We do not expect this project to have vulnerabilities of its own. Nonetheless, as this project distributes prebuilt Node.js binaries,
|
26 |
|
27 | **Node.js security vulnerabilities affect binaries distributed by this project, as well.**
|
28 |
|
29 | Like most of you, this project does not have access to advance/private disclosures of Node.js security vulnerabilities. We can only closely monitor the **public** security advisories from the Node.js team. It takes time to build and release a new set of binaries, once a new Node.js version has been released.
|
30 |
|
31 | **It is possible for this project to fall victim to a supply chain attack.**
|
32 |
|
33 | This project deploys multiple defense measures to ensure that the safe binaries are delivered to users:
|
34 |
|
35 | - Binaries are compiled by [Github Actions](https://github.com/vercel/pkg-fetch/actions)
|
36 | - Workflows and build logs are transparent and auditable.
|
37 | - Artifacts are the source of truth. Even repository/organization administrators can't tamper them.
|
38 | - Hashes of binaries are hardcoded in [source](https://github.com/vercel/pkg-fetch/blob/HEAD/lib/expected.ts)
|
39 | - Origins of the binaries are documented.
|
40 | - Changes to the binaries are logged by VCS (Git) and are publicly visible.
|
41 | - `pkg-fetch` rejects the binary if it does not match the hardcoded hash.
|
42 | - GPG-signed hashes are available in [Releases](https://github.com/vercel/pkg-fetch/releases)
|
43 | - Easy to spot a compromise.
|
44 | - `pkg-fetch` package on npm is strictly permission-controlled
|
45 | - Only authorized Vercel employees can push new revisions to npm.
|
46 |
|
47 | ## Contributing Updates to Patches
|
48 |
|
49 | ### Example workflow for applying patches to a new version of Node.js (18.13.0)
|
50 |
|
51 | 1. Clone Node.js as a sibling to your current `pkg-fetch` clone
|
52 |
|
53 | - `git clone https://github.com/nodejs/node.git`
|
54 | - `cd node`
|
55 |
|
56 | 2. Checkout the tag you wish to generate a patch for
|
57 |
|
58 | - `git checkout v18.13.0`
|
59 |
|
60 | 3. Attempt to apply the closest patch (e.g. applying the existing patch for
|
61 | 18.12.1 when trying to generate a new patch for 18.13.0)
|
62 |
|
63 | - `git apply ..\pkg-fetch\patches\node.v18.12.1.cpp.patch --reject`
|
64 |
|
65 | 4. If no rejects, great! you are ready to make your new patch file.
|
66 |
|
67 | - `git add -A`
|
68 | - `git diff --staged --src-prefix=node/ --dst-prefix=node/ > ..\pkg-fetch\patches\node.v18.13.0.cpp.patch`
|
69 |
|
70 | 5. If rejects exist, resolve them yourself, and ensure all changes are saved,
|
71 | and repeat step 4 to export the patch file
|
72 |
|
73 | #### Resolving Rejects
|
74 |
|
75 | Usually when a patch is rejected, it's because the context around the changes
|
76 | was refactored slightly since the last patched version. This is not usually
|
77 | complicated to resolve, but requires a human to interpret the changes since the
|
78 | last version `pkg` was patched against, compared with the version you wish to
|
79 | create a patch for.
|
80 |
|
81 | One method is to pull up the diff for the file where the rejects apply for the
|
82 | changes between the last tag (e.g. v18.12.1 to use the previous example) and the
|
83 | tag you want a patch for (e.g. v18.13.0 to use the previous example). Alongside
|
84 | this, have the `.rej` file and go through each rejected hunk by hunk and use
|
85 | your best judgement to determine how it should apply against the new tag.
|
86 |
|
87 | Save you results, and export the overall git diff with the commands from the
|
88 | example above.
|
89 |
|
90 | ### Checking that patches apply cleanly
|
91 |
|
92 | The expectation is that a patch applies cleanly, with no delta or offsets from
|
93 | the source repo.
|
94 |
|
95 | When making a change to a patch file, it is possible to apply that patch without
|
96 | building by running
|
97 |
|
98 | `yarn applyPatches --node-range node18`
|
99 |
|
100 | where the `--node-range` can be specified to apply patches for the version of
|
101 | node for which you are updating patches. If unspecified, the latest node version
|
102 | in [patches.json](./patches/patches.json) will be used.
|
103 |
|
104 | Ultimately, the patch should result in fully functional node binary, but the
|
105 | `applyPatches` script can be used to quickly iterate just the application of
|
106 | the patches you are updating without needing to wait for the full build to
|
107 | complete.
|
108 |
|
109 | ## Building a Binary Locally
|
110 |
|
111 | You can use the `yarn start` script to build the binary locally, which is helpful
|
112 | when updating patches to ensure functionality before pushing patch updates for
|
113 | review.
|
114 |
|
115 | For example:
|
116 |
|
117 | `yarn start --node-range node18 --arch x64 --output dist`
|