|
1 | | -# npm-no-scripts |
| 1 | +# npm-no-scripts GitHub Action |
| 2 | + |
| 3 | +This action checks all installed NPM dependencies for lifecycle scripts (like |
| 4 | +`postinstall`) that would be run on installation. If any such script is found, |
| 5 | +the action fails with a list of offenders. |
| 6 | + |
| 7 | +## Inputs |
| 8 | + |
| 9 | +| Input Name | Description | Required | Default | |
| 10 | +| -------------- | --------------------------------------------------- | -------- | ------- | |
| 11 | +| `ignore` | List of packages to ignore (JSON) | No | `""` | |
| 12 | +| `ignoreNative` | Whether to ignore the default node-gyp install step | No | `false` | |
| 13 | + |
| 14 | +#### `ignore` |
| 15 | + |
| 16 | +You can specify dependencies you would like to ignore when scanning for |
| 17 | +lifecycle scripts (ideally because you manually vetted them and consider them to |
| 18 | +be secure). This can be helpful if you have dependencies that need a |
| 19 | +`postinstall` script to be run. |
| 20 | + |
| 21 | +This parameter expects a JSON array of package names or an object as string. |
| 22 | + |
| 23 | +```json |
| 24 | +"PKGNAME": { |
| 25 | + "version": VERSION_LIST, |
| 26 | + "script": SCRIPT_LIST, |
| 27 | + "native": IGNORE_NATIVE, |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +- `PKGNAME`: the name of the package to ignore |
| 32 | +- `VERSION_LIST`: a version string or array of version strings (combined via |
| 33 | + logical or) in the semver format. Only packages that match this version will |
| 34 | + be ignored. NPM rules apply (e.g. `^1.2.3` also matches `1.2.5` and `1.3.0` |
| 35 | + but not `1.2.2` or `2.0.0`, use `=1.2.3` for fixed versions). |
| 36 | +- `SCRIPT_LIST`: a string or array of strings of specific scripts to ignore. |
| 37 | + Possible values are `prepare`, `preinstall`, `install`, and `postinstall` |
| 38 | +- `IGNORE_NATIVE`: when `true`, ignore implicit runs of `node-gyp` for packages |
| 39 | + that generate native bindings |
| 40 | + |
| 41 | +If `"script"` is present without `"version"`, the specified script(s) will be |
| 42 | +ignored in all versions. If only `"version"` is present, everything will be |
| 43 | +ignored for the specified version. |
| 44 | + |
| 45 | +_Example: Ignore `esbuild`_ |
| 46 | + |
| 47 | +```yaml |
| 48 | +- name: Validate step |
| 49 | + uses: cryptool-org/npm-no-scripts@v1 |
| 50 | + with: |
| 51 | + ignore: | |
| 52 | + ["esbuild"] |
| 53 | +``` |
| 54 | +
|
| 55 | +or |
| 56 | +
|
| 57 | +```yaml |
| 58 | +- name: Validate step |
| 59 | + uses: cryptool-org/npm-no-scripts@v1 |
| 60 | + with: |
| 61 | + ignore: | |
| 62 | + {"esbuild": true} |
| 63 | +``` |
| 64 | +
|
| 65 | +_Example: Ignore only `postinstall` script for `esbuild`_ |
| 66 | + |
| 67 | +```yaml |
| 68 | +- name: Validate step |
| 69 | + uses: cryptool-org/npm-no-scripts@v1 |
| 70 | + with: |
| 71 | + ignore: | |
| 72 | + { |
| 73 | + "esbuild": { |
| 74 | + "script": "postinstall" |
| 75 | + } |
| 76 | + } |
| 77 | +``` |
| 78 | + |
| 79 | +_Example: Ignore all scripts in version '0.22.3' of `esbuild`_ |
| 80 | + |
| 81 | +```yaml |
| 82 | +- name: Validate step |
| 83 | + uses: cryptool-org/npm-no-scripts@v1 |
| 84 | + with: |
| 85 | + ignore: | |
| 86 | + { |
| 87 | + "esbuild": { |
| 88 | + "version": "=0.22.3" |
| 89 | + } |
| 90 | + } |
| 91 | +``` |
| 92 | + |
| 93 | +_Example: Ignore `preinstall` script in version '0.22.3' and patch releases of |
| 94 | +`esbuild`_ |
| 95 | + |
| 96 | +```yaml |
| 97 | +- name: Validate step |
| 98 | + uses: cryptool-org/npm-no-scripts@v1 |
| 99 | + with: |
| 100 | + ignore: | |
| 101 | + { |
| 102 | + "esbuild": { |
| 103 | + "version": "~0.22.3", |
| 104 | + "script": "preinstall" |
| 105 | + } |
| 106 | + } |
| 107 | +``` |
| 108 | + |
| 109 | +## Outputs |
| 110 | + |
| 111 | +This action does not produce outputs. It will only succeed if no lifecycle |
| 112 | +script is found. |
| 113 | + |
| 114 | +## Usage |
| 115 | + |
| 116 | +1. Install your dependencies _without_ running any potential scripts: |
| 117 | + |
| 118 | +```yaml |
| 119 | +- name: Install dependencies |
| 120 | + run: npm ci --ignore-scripts |
| 121 | +``` |
| 122 | + |
| 123 | +2. Run this action to verify no scripts would have been run: |
| 124 | + |
| 125 | +```yaml |
| 126 | +- name: Validate step |
| 127 | + uses: cryptool-org/npm-no-scripts@v1 |
| 128 | +``` |
| 129 | + |
| 130 | +3. (optional) Run all scripts (in your package and the ignored ones): |
| 131 | + |
| 132 | +```yaml |
| 133 | +- name: Configure dependencies |
| 134 | + run: npm rebuild |
| 135 | +``` |
| 136 | + |
| 137 | +## Security Notes |
| 138 | + |
| 139 | +To limit trivial supply-chain attacks, _never_ run untrusted scripts. Use |
| 140 | +`npm clean-install --ignore-scripts` when installing the dependencies. This will |
| 141 | +use the lockfile with pinned versions and not execute any lifecycle scripts. |
| 142 | + |
| 143 | +If any of your dependencies needs such a script (like `postinstall`) to function |
| 144 | +properly, you can explicitly run them using `npm rebuild <PACKAGE>`. |
| 145 | + |
| 146 | +Please note that `--ignore-scripts` wont execute any of your own scripts defined |
| 147 | +in `package.json` either. You either have to run them manually with |
| 148 | +`npm run <SCRIPTNAME>` or -- only if you are certain no malicious scripts exist |
| 149 | +in your dependencies -- with `npm rebuild`. |
| 150 | + |
| 151 | +## License |
| 152 | + |
| 153 | +This GitHub Action is available under the [MIT License](LICENSE) |
0 commit comments