feat(security): gate public-registry plugin installs + sandbox the runner unit
Supply chain: resolvePackage() used to pass any punktfunk-plugin-* or foreign-scope name straight to bun add — a typo or a squatted look-alike on npmjs.org would install operator-privileged code. Only the @punktfunk scope (pinned to the Gitea registry by the bunfig scope map) resolves by default now; anything else throws with an explanation unless --allow-public-registry is passed, and even then installs print a loud warning. Removal never gates — uninstalling stays safe regardless of origin. systemd (user unit): free hardening for well-behaved plugins — NoNewPrivileges, PrivateTmp, ProtectSystem=strict with ReadWritePaths=%h (plugin state and download dirs under $HOME keep working), and RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6. Plugins writing outside $HOME, and distros that restrict unprivileged user namespaces for user units, are handled via a documented systemctl --user edit drop-in. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,9 @@
|
||||
//
|
||||
// With a subcommand it manages plugin packages (the host CLI forwards `punktfunk-host plugins …`
|
||||
// here):
|
||||
// add <name…> install first-party (playnite, rom-manager) or punktfunk-plugin-* packages
|
||||
// add <name…> install first-party plugins (playnite, rom-manager); anything resolving on
|
||||
// the PUBLIC npm registry (punktfunk-plugin-*, foreign scopes) additionally
|
||||
// needs --allow-public-registry
|
||||
// remove <name…> uninstall
|
||||
// list list installed plugin packages
|
||||
//
|
||||
@@ -44,7 +46,12 @@ const positionals = (): string[] => {
|
||||
return out;
|
||||
};
|
||||
|
||||
const pkgOpts = { dir: options.pluginsDir };
|
||||
const pkgOpts = {
|
||||
dir: options.pluginsDir,
|
||||
// Opt-in for names that resolve on the public npm registry (supply-chain gate in
|
||||
// plugins.ts::resolvePackage). Boolean flag, so positionals() skips it on its own.
|
||||
allowPublicRegistry: process.argv.includes("--allow-public-registry"),
|
||||
};
|
||||
|
||||
const runPkgOp = (
|
||||
op: (names: string[], o: typeof pkgOpts) => void,
|
||||
|
||||
Reference in New Issue
Block a user