AI Security Review
scanned 4d ago · by lpm-firewall-aiThe package intentionally installs AI-agent skill files by symlink during postinstall. This is package-aligned and documented, with no confirmed hidden exfiltration or payload behavior.
Static reason
High-risk behavior combination matched malicious policy.
Trigger
npm/yarn install postinstall; optional user-invoked linear.mjs commands
Impact
Adds package-provided skills to local agent skill directories; optional Linear commands act with the user's API key when invoked.
Mechanism
documented symlink installation of bundled skills plus optional Linear GraphQL CLI
Rationale
Source inspection confirms an install-time agent control-surface mutation, but it is the declared function of this agent-skills package and is documented with ownership checks that avoid clobbering user files. The Linear credential and network behavior is runtime, user-invoked, and targets the expected Linear API.
Evidence
package.jsonscripts/link-skills.mjsREADME.mdplugins/linear/skills/linear/bin/linear.mjsplugins/linear/skills/linear/SKILL.md.claude/skills/<skill> symlinks.agents/skills/<skill> symlinks.claude/commands/<command>.md symlinks~/.config/linctl/workspace.json
Network endpoints1
api.linear.app/graphql
Decision evidence
public snapshotAI called this Clean at 88.0% confidence as Benign with medium false-positive risk.
Evidence for block
- package.json runs postinstall node scripts/link-skills.mjs.
- scripts/link-skills.mjs symlinks package skills into .claude/skills and .agents/skills in the consuming project.
- plugins/linear/skills/linear/bin/linear.mjs reads LINEAR_API_KEY and posts user-invoked GraphQL requests to Linear.
Evidence against
- README.md documents the npm install symlink behavior for Claude Code and Codex.
- scripts/link-skills.mjs only links discovered SKILL.md directories and avoids clobbering real user-authored paths.
- scripts/link-skills.mjs stale cleanup removes only symlinks whose real target is inside this package.
- No install-time network access, credential harvesting, eval, child_process, native loading, or destructive payload found.
- linear.mjs network/API-key use is a user-invoked Linear CLI feature aligned with the linear skill.
Behavioral surface
EnvironmentVarsFilesystemNetwork
HighEntropyStringsUrlStrings
NoLicense
Source & flagged code
3 flagged · loading sourcepackage.jsonView file
•scripts.postinstall = node scripts/link-skills.mjs
High
Install Time Lifecycle Scripts
Package defines install-time lifecycle scripts.
package.jsonView on unpkgplugins/linear/skills/linear/bin/linear.mjsView file
11// Recommended: add `export LINEAR_API_KEY=lin_api_xxx` to ~/.zshenv (zsh) or
L12: // ~/.bashrc (bash) so it's available in every shell — including the
L13: // non-interactive ones spawned by Claude Code.
...
L23: import { createInterface } from "node:readline/promises";
L24: import { stdin as input, stdout as output } from "node:process";
L25:
L26: const API_URL = "https://api.linear.app/graphql";
L27: const API_KEY = process.env.LINEAR_API_KEY;
L28: const WORKSPACE_FILE =
L29: process.env.LINCTL_WORKSPACE_FILE ||
L30: join(homedir(), ".config", "linctl", "workspace.json");
L31:
Medium
Install Persistence
Source writes installer persistence such as shell profile or service configuration.
plugins/linear/skills/linear/bin/linear.mjsView on unpkg · L11scripts/link-skills.mjsView file
5Install-time AI-agent control hijack evidence:
L5: //
L6: // skills -> .claude/skills/<name> (Claude Code; a dir with SKILL.md)
L7: // skills -> .agents/skills/<name> (Codex; same SKILL.md format)
L8: // commands -> .claude/commands/<rel>.md (Claude Code only; a .md under commands/)
L9: //
...
L28: const UNLINK = process.argv.includes('--unlink')
L29: const SKIP_DIRS = new Set(['node_modules', '.git', '.claude'])
L30:
...
L44: // or the workspace root in a monorepo, which is exactly where the shared
L45: // .claude directory should live. Fall back to climbing out of node_modules.
L46: function resolveProjectRoot() {
...
L181: // Nothing to link: only tidy up previously-created links (if the dir exists),
Payload evidence from plugins/contribute-skill/skills/contribute-skill/SKILL.md:
L9: You are turning something learned in this session into a PR against
L10: https://github.com/gallop-systems/agent-skills, the public repo behind the
L11: installed skills.
Critical
Ai Agent Control Hijack
Install-time source drops package-supplied AI-agent/MCP control files or instructions.
scripts/link-skills.mjsView on unpkg · L5Findings
1 Critical1 High4 Medium5 Low
CriticalAi Agent Control Hijackscripts/link-skills.mjs
HighInstall Time Lifecycle Scriptspackage.json
MediumNetwork
MediumEnvironment Vars
MediumInstall Persistenceplugins/linear/skills/linear/bin/linear.mjs
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings
LowNo License