continuedev / continuedev/continue
terminal-security: package-manager rule flags installs but not typosquat targets (e.g. `npm install lodahs`)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 36k
- Forks
- 5.4k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
@continuedev/terminal-security already gates package installs behind permission via isHighRiskPackageManager (it recognises npm/yarn/pnpm install/add/i). That rule answers "is this an install?" but not "what is being installed?". A command like npm install lodahs (one edit from lodash) is treated identically to npm install lodash: both land at allowedWithPermission, with no signal that the target name is a likely typosquat. Runner forms such as npx expres aren't covered by the package-manager list at all.
Typosquatting is one of the most common npm supply-chain attack vectors, and an AI agent driving the terminal is exactly the actor most likely to fat-finger or hallucinate a package name. The evaluator is the right seam, because it is the choke point that decides whether a terminal command auto-runs.
Gap (reproducible, offline)
npm install lodahs— no distinction from a legitimate install; a reviewer sees no "this looks like a typosquat of lodash" signal.npx expres—npx/bunxaren't in the package-manager list, so the typosquat target gets no dedicated treatment.pnpm dlx expres,yarn add lodahs,bun add lodahs— same gap across managers and runners.
Proposal
Add a sibling, pure/offline checker in the same seam that detects npm-ecosystem installs (and npx/bunx/dlx/exec runner targets) of a name exactly one edit away from a curated set of popular packages, and wire it into the existing isHighRiskCommand aggregator so a hit escalates the policy to allowedWithPermission (most-restrictive-wins). It never hard-denies; it only asks the human.
Design:
- Pure/offline/deterministic. No network, no filesystem, no new runtime dependencies.
- Gate: Optimal String Alignment (restricted Damerau-Levenshtein) distance == 1 and the matched popular name length > 4 (short names like
vueproduce too many false positives). - Hardening to avoid false positives: sub-command splitting on
;/&&/||/|/&/newlines, env-assignment + wrapper prefixes (sudo,env FOO=bar), path-prefix on the binary, leading global options before the subcommand, value-taking install flags (sonpm install --prefix axio lodashdoes not flagaxio, which is a--prefixvalue, not a package), quote stripping, and@scope/pkg@versionnormalization.
I have a working implementation + vitest suite ready (45 new cases including the --prefix axio false-positive guard; the package's full suite stays green at 269 passing; tsc --noEmit clean) and proposed the same check upstream in Goose: aaif-goose/goose#9642. Would the maintainers be open to it living next to the existing isHighRisk* checks in evaluateTerminalCommandSecurity.ts? Happy to open the PR.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in evaluateTerminalCommandSecurity.ts by reading the existing isHighRiskPackageManager and isHighRiskCommand checks. Run the package's Vitest suite and tsc --noEmit, then verify the listed npm-ecosystem install and runner cases, including the --prefix axio false-positive guard. Done means the offline checker is integrated, escalates matches to allowedWithPermission, and the full suite remains green.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, devtools, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100