UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

68 lines (67 loc) • 3.56 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /** * `EDITOR`/`VISUAL`/`PAGER` are flagged by `isDangerousEnvKey` for a * documented RCE vector (many tools invoke them to launch an editor/pager), * but env-key-rules.ts's own module doc calls out their "high FP rate" in * the same breath — an installed bundle's env file can supply a value, but * nothing in akm's own env-injection path ever *invokes* EDITOR/VISUAL/PAGER * with that value, so the RCE vector these three describe cannot fire from * an injected env the way LD_PRELOAD or GIT_SSH_COMMAND can. Blocking a * third-party install over them protects nothing while making "the operator * legitimately wants to set their editor" the common case that eats the * refusal. Kept as a name-level literal set (not an import of * `commands/lint/env-key-rules.ts`) so this module stays the pure leaf its * own doc comment promises — no new import edges into the rest of the tree. */ const INTERACTIVE_TOOL_ENV_KEYS = new Set(["EDITOR", "VISUAL", "PAGER"]); /** * Decide whether injecting an env with the given dangerous keys is allowed, * warned, or blocked. Third-party (registry-installed) stashes hard-block a * genuine RCE-class key; first-party stashes warn. The interactive-tool * group (see {@link INTERACTIVE_TOOL_ENV_KEYS}) only ever warns, since akm's * own env-injection path never invokes those keys as a command. An explicit * `--allow-dangerous-env-keys` (threaded through by the caller, same override * `decideDangerousKeyInstall`'s `"warn-allow"` already honors for rule 2) * downgrades a remaining block to a warning too — the operator is not racing * themselves. See rule 1 above. * * @param dangerousKeys The subset of injected keys flagged as process-hijacking * (already filtered by the caller via `isDangerousEnvKey`). * @param thirdParty `true` when the env's source is a third-party stash — i.e. * its origin carries a `registryId`. * @param allowDangerousEnvKeys `true` when the operator passed `--allow-dangerous-env-keys` (or * its equivalent) for this injection. Defaults to `false`. */ export function decideDangerousEnvInjection(input) { if (input.dangerousKeys.length === 0) return "allow"; if (!input.thirdParty) return "warn"; if (input.allowDangerousEnvKeys) return "warn"; const onlyInteractiveTool = input.dangerousKeys.every((key) => INTERACTIVE_TOOL_ENV_KEYS.has(key)); return onlyInteractiveTool ? "warn" : "block"; } /** * Decide the baseline install stance for a freshly-installed stash's * dangerous-key scan. The interactive confirm / rollback UX is applied by the * caller on top of the `"gate"` stance — this predicate only fixes the policy. * See rule 2 above. */ export function decideDangerousKeyInstall(input) { if (!input.findingsPresent) return "allow"; return input.allowDangerousEnvKeys ? "warn-allow" : "gate"; } // ── Rule 3: write activation (search-source.ts, installations.ts) ──────────── /** * Whether a resolved source is write-activated. Only the primary stash and * sources explicitly marked `writable: true` are writable; registry-cached * (installed, read-only) sources are never written in place because * `akm update` overwrites them. See rule 3 above. */ export function isSourceWriteActivated(source) { return source.writable === true; }