|
| 1 | +--- |
| 2 | +id: yr5s3c8k |
| 3 | +title: .yarnrc.yml Security |
| 4 | +description: Harden your Webiny project against supply chain attacks using Yarn security settings. |
| 5 | +--- |
| 6 | + |
| 7 | +import { Alert } from "@/components/Alert"; |
| 8 | + |
| 9 | +<Alert type="success" title="WHAT YOU'LL LEARN"> |
| 10 | + |
| 11 | +- why you should harden your Webiny project against supply chain attacks |
| 12 | +- which Yarn security settings to add to your `.yarnrc.yml` |
| 13 | +- what each setting does and how to customize it |
| 14 | +- how to troubleshoot installation failures caused by these settings |
| 15 | + |
| 16 | +</Alert> |
| 17 | + |
| 18 | +## Overview |
| 19 | + |
| 20 | +Every Webiny project uses Yarn as its package manager and has a `.yarnrc.yml` configuration file in the project root. Yarn supports several security settings that you can add to this file to protect your project against supply chain attacks - malicious code that enters your application through compromised or deceptive npm packages. |
| 21 | + |
| 22 | +This page explains the settings Webiny recommends and how to add them to your project. |
| 23 | + |
| 24 | +## Recommended Settings |
| 25 | + |
| 26 | +Add the following settings to the `.yarnrc.yml` file in your project root: |
| 27 | + |
| 28 | +```yaml .yarnrc.yml |
| 29 | +enableScripts: false |
| 30 | + |
| 31 | +npmMinimalAgeGate: 3d |
| 32 | +npmPreapprovedPackages: |
| 33 | + - "@webiny/*" |
| 34 | + - "wts-client" |
| 35 | + |
| 36 | +approvedGitRepositories: |
| 37 | + - "https://github.com/webiny/webiny-upgrades-v6" |
| 38 | +``` |
| 39 | +
|
| 40 | +The sections below explain what each setting does and how to adjust it for your needs. |
| 41 | +
|
| 42 | +## Lifecycle Scripts |
| 43 | +
|
| 44 | +```yaml .yarnrc.yml |
| 45 | +enableScripts: false |
| 46 | +``` |
| 47 | +
|
| 48 | +When `enableScripts` is set to `false`, Yarn skips all package lifecycle scripts - `postinstall`, `preinstall`, `install`, and similar hooks defined in a dependency's `package.json`. This is the single most effective defense against malicious packages, since the majority of supply chain attacks rely on lifecycle scripts to execute arbitrary code during installation. |
| 49 | + |
| 50 | +<Alert type="warning" title="When a dependency requires scripts"> |
| 51 | + |
| 52 | +Some legitimate packages (native modules, packages that compile binaries) rely on `postinstall` scripts. If you add such a dependency and it does not work after installation, you may need to explicitly allow scripts for that package. See [Allowing Scripts for Specific Packages](#allowing-scripts-for-specific-packages) below. |
| 53 | + |
| 54 | +</Alert> |
| 55 | + |
| 56 | +### Allowing Scripts for Specific Packages |
| 57 | + |
| 58 | +Rather than setting `enableScripts` back to `true` globally, allow scripts only for the packages that need them by adding a `packageExtensions` entry: |
| 59 | + |
| 60 | +```yaml .yarnrc.yml |
| 61 | +enableScripts: false |
| 62 | +
|
| 63 | +packageExtensions: |
| 64 | + "some-native-package@*": |
| 65 | + scripts: |
| 66 | + postinstall: "node ./build.js" |
| 67 | +``` |
| 68 | + |
| 69 | +## Package Age Gate |
| 70 | + |
| 71 | +```yaml .yarnrc.yml |
| 72 | +npmMinimalAgeGate: 3d |
| 73 | +``` |
| 74 | + |
| 75 | +The `npmMinimalAgeGate` setting tells Yarn to reject any package version that was published to the npm registry less than the specified duration ago. This creates a time buffer that helps protect against: |
| 76 | + |
| 77 | +- **Typosquatting** - malicious packages with names similar to popular ones |
| 78 | +- **Account takeover** - compromised maintainer accounts pushing malicious updates |
| 79 | +- **Star-jacking** - newly published malicious packages designed to look trustworthy |
| 80 | + |
| 81 | +With a value of `3d`, you cannot install a package version that was published less than three days ago. This gives the community and automated scanners time to flag malicious releases before they reach your project. |
| 82 | + |
| 83 | +### Preapproved Packages |
| 84 | + |
| 85 | +```yaml .yarnrc.yml |
| 86 | +npmPreapprovedPackages: |
| 87 | + - "@webiny/*" |
| 88 | + - "wts-client" |
| 89 | +``` |
| 90 | + |
| 91 | +Packages listed under `npmPreapprovedPackages` are exempt from the age gate. The `@webiny/*` glob pattern covers all Webiny packages, which are published by the Webiny team and need to be installable immediately after release. |
| 92 | + |
| 93 | +If you publish your own packages or work with a trusted vendor whose packages you need immediately after release, add them to the list: |
| 94 | + |
| 95 | +```yaml .yarnrc.yml |
| 96 | +npmPreapprovedPackages: |
| 97 | + - "@webiny/*" |
| 98 | + - "wts-client" |
| 99 | + - "@your-org/*" |
| 100 | +``` |
| 101 | + |
| 102 | +### Adjusting the Age Gate Duration |
| 103 | + |
| 104 | +You can increase or decrease the duration to match your risk tolerance: |
| 105 | + |
| 106 | +```yaml .yarnrc.yml |
| 107 | +# More conservative - wait a full week |
| 108 | +npmMinimalAgeGate: 7d |
| 109 | +
|
| 110 | +# Less conservative - wait one day |
| 111 | +npmMinimalAgeGate: 1d |
| 112 | +``` |
| 113 | + |
| 114 | +A longer duration provides more protection but delays access to new releases. A shorter duration gives faster access but reduces the window for malicious packages to be caught. |
| 115 | + |
| 116 | +## Approved Git Repositories |
| 117 | + |
| 118 | +```yaml .yarnrc.yml |
| 119 | +approvedGitRepositories: |
| 120 | + - "https://github.com/webiny/webiny-upgrades-v6" |
| 121 | +``` |
| 122 | + |
| 123 | +The `approvedGitRepositories` setting restricts which Git repositories Yarn is allowed to use as a dependency source. Any `git+https://...` or `github:...` dependency that does not match an entry in this list is rejected. |
| 124 | + |
| 125 | +Webiny uses this to allow the upgrade repository - the mechanism for applying Webiny version upgrades - while blocking all other Git-based dependencies by default. |
| 126 | + |
| 127 | +### Adding a Git Repository |
| 128 | + |
| 129 | +If your project needs a dependency from a Git repository, add its URL to the list: |
| 130 | + |
| 131 | +```yaml .yarnrc.yml |
| 132 | +approvedGitRepositories: |
| 133 | + - "https://github.com/webiny/webiny-upgrades-v6" |
| 134 | + - "https://github.com/your-org/your-private-package" |
| 135 | +``` |
| 136 | + |
| 137 | +## Troubleshooting |
| 138 | + |
| 139 | +### "Package was published less than X ago" |
| 140 | + |
| 141 | +The age gate blocked a package version. You have three options: |
| 142 | + |
| 143 | +- **Wait** - try again after the age gate duration has passed |
| 144 | +- **Preapprove** - add the package to `npmPreapprovedPackages` if you trust the publisher |
| 145 | +- **Lower the gate** - reduce `npmMinimalAgeGate` (not recommended unless you understand the risk) |
| 146 | + |
| 147 | +### "Lifecycle scripts are disabled" |
| 148 | + |
| 149 | +A package tried to run a script during installation but `enableScripts: false` blocked it. If the package needs scripts to function correctly, allow them for that specific package rather than enabling scripts globally. |
| 150 | + |
| 151 | +### "Git repository is not approved" |
| 152 | + |
| 153 | +A dependency points to a Git repository that is not in `approvedGitRepositories`. Add the repository URL to the list if you trust it. |
0 commit comments