Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions modulefirewall/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ const (
DefaultApprovedWhenEmpty = "ALL"
)

var bundledMalwareTrustSeeds = []string{"npm", "npx", "yarn", "yarnpkg", "corepack", "pnpm"}
// DefaultTrustedPackageManagers is the empty-TrustedModules seed:
// deny every module except supported package managers.
var DefaultTrustedPackageManagers = []string{
"npm", "npx", "yarn", "yarnpkg", "corepack", "pnpm", "vlt",
}

var bundledMalwareTrustSeeds = DefaultTrustedPackageManagers

// ExplicitModuleGrant is true only for an explicit local grant.
// Empty lists, ALL, NOT ALL, HTTPS URLs, and bundled package-manager names do not count.
Expand Down Expand Up @@ -54,12 +60,15 @@ func ExplicitModuleGrant(pkg PackageSpec, rules []string) bool {
}

// NormalizeTrustedModules applies the empty TrustedModules default:
// deny every module except bundled package managers, so npm/yarn/corepack
// deny every module except bundled package managers, so npm/yarn/corepack/vlt
// can re-sign after an upgrade.
func NormalizeTrustedModules(entries []string) []string {
normalized := NormalizeList(entries, "")
if len(normalized) == 0 {
return []string{"NOT ALL", "npm", "npx", "yarn", "yarnpkg", "corepack", "pnpm"}
out := make([]string, 1+len(DefaultTrustedPackageManagers))
out[0] = "NOT ALL"
copy(out[1:], DefaultTrustedPackageManagers)
return out
}
return normalized
}
Expand Down
7 changes: 6 additions & 1 deletion modulefirewall/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

func TestNormalizeTrustedModules_DefaultTrustsNpm(t *testing.T) {
got := NormalizeTrustedModules(nil)
want := []string{"NOT ALL", "npm", "npx", "yarn", "yarnpkg", "corepack", "pnpm"}
want := []string{"NOT ALL", "npm", "npx", "yarn", "yarnpkg", "corepack", "pnpm", "vlt"}
if len(got) != len(want) {
t.Fatalf("got %#v", got)
}
Expand Down Expand Up @@ -37,6 +37,11 @@ func TestNormalizeTrustedModules_DefaultTrustsNpm(t *testing.T) {
if err != nil || !ok {
t.Fatalf("corepack default trust = %v err=%v", ok, err)
}
vlt, _ := ParsePackageToken("vlt")
ok, err = IsPackageTrustedLocal(vlt, nil)
if err != nil || !ok {
t.Fatalf("vlt default trust = %v err=%v", ok, err)
}
other, _ := ParsePackageToken("eslint")
ok, err = IsPackageTrustedLocal(other, nil)
if err != nil || ok {
Expand Down
4 changes: 4 additions & 0 deletions modulefirewall/trust_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ func TestExplicitModuleGrant(t *testing.T) {
if ExplicitModuleGrant(pkg, []string{"NOT ALL", "npm", "npx"}) {
t.Fatal("bundled seeds")
}
vlt := PackageSpec{Name: "vlt", Raw: "vlt"}
if ExplicitModuleGrant(vlt, NormalizeTrustedModules(nil)) {
t.Fatal("vlt default seed")
}
if ExplicitModuleGrant(pkg, []string{"https://policy.example/fw"}) {
t.Fatal("url")
}
Expand Down
2 changes: 1 addition & 1 deletion settings/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type Settings struct {
Aliases []string `cfg:"aliases" reg:"Aliases" default:"" help:"Comma-delimited list of version aliases in the format alias=version." hidden:"true"`
AllowedSigners []string `cfg:"allowed_signers" reg:"AllowedSigners" help:"Comma-delimited signer organization names (O=) allowed after Authenticode chain verification. Use to restrict vendors (for example OpenJS Foundation vs NodeSource)." hidden:"true"`
AllowedThumbprints []string `cfg:"allowed_thumbprints" reg:"AllowedThumbprints" help:"Optional comma-delimited SHA-1 Authenticode leaf thumbprints (hex). When set, node.exe must match one pin after org allowlist. Empty disables pinning." hidden:"true"`
TrustedModules []string `cfg:"trusted_modules" reg:"TrustedModules" help:"Trust firewall: modules allowed to auto-reshim after self-update. NOT/! negation; empty defaults to NOT ALL plus npm, npx, yarn, yarnpkg, corepack, and pnpm. May include an HTTPS policy URL; local entries are checked first and only untrusted modules are POSTed to the URL." hidden:"true"`
TrustedModules []string `cfg:"trusted_modules" reg:"TrustedModules" help:"Trust firewall: modules allowed to auto-reshim after self-update. NOT/! negation; empty defaults to NOT ALL plus npm, npx, yarn, yarnpkg, corepack, pnpm, and vlt. May include an HTTPS policy URL; local entries are checked first and only untrusted modules are POSTed to the URL." hidden:"true"`
UntrustedModuleHandlerAction string `cfg:"untrusted_module_handler_action" reg:"UntrustedModuleHandlerAction" default:"prompt" enum:"deny,prompt,allow" help:"Action when a global module changes without TrustedModules hit: prompt (default), allow (auto-reshim + quiet toast), or deny." hidden:"false"`
ApprovedModules []string `cfg:"approved_modules" reg:"ApprovedModules" help:"Module firewall (certified): allow list for local installs. Empty defaults to ALL. May be a single HTTPS policy URL." hidden:"true"`
ApprovedGlobalModules []string `cfg:"approved_global_modules" reg:"ApprovedGlobalModules" help:"Module firewall (certified): allow list for global installs. Empty defaults to ALL. May be a single HTTPS policy URL." hidden:"true"`
Expand Down
5 changes: 3 additions & 2 deletions verifycache/script_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ const scriptCacheBucket = "scripts"
var ErrScriptCacheMiss = errors.New("delegated script cache entry missing")

// SignVersionScripts records TPM-signed hashes for top-level .cmd/.bat launchers,
// package-manager JS entrypoints (npm-cli.js / npx-cli.js), and Authenticode
// verify-cache entries for top-level .exe helpers.
// package-manager JS entrypoints (npm-cli.js / npx-cli.js), Authenticode
// verify-cache entries for top-level .exe helpers, and Yarn Classic / pnpm
// global bin launchers outside the version directory.
func SignVersionScripts(versionDir string) error {
dataRoot, err := dataRootFromVersionDir(versionDir)
if err != nil {
Expand Down
Loading