registry  /  harveyz-skill  /  0.23.0

harveyz-skill@0.23.0

Skill manager for Claude Code, Cursor, and Codex

AI Security Review

scanned 2h ago · by lpm-firewall-ai

LPM treats this as warn-only first-party agent extension lifecycle risk. No confirmed malicious install-time attack surface. The package is an agent skill/tool manager that can explicitly install skills and hooks into Claude/Codex/Cursor-style directories when the user runs its CLI.

Static reason
One or more suspicious static signals were detected.; previous stored version diff introduced dangerous source
Trigger
User runs hskill install, hskill hooks install, hskill update, or related uninstall commands.
Impact
Can modify user or project agent configuration and shell startup files with user-invoked commands; no unconsented lifecycle mutation or exfiltration found.
Mechanism
explicit CLI-managed agent extension and shell tool installation
Rationale
This is not malicious under the install-control policy because broad agent control-surface writes are not performed during npm install and are exposed as explicit user-command setup. The remaining risk is guarded agent extension lifecycle behavior, so warn rather than block.
Evidence
package.jsonbin/cli.jslib/installer.jslib/targets.jshooks/check-similar-branch/check-similar-branch.sh~/.claude/settings.json~/.claude/hooks/*.sh.claude/settings.json.claude/hooks/*.sh~/.codex/hooks.json~/.codex/hooks/*.sh.codex/hooks.json.codex/hooks/*.sh~/.zshrc~/.local/bin/<tool>~/.hskill/tools/*

Decision evidence

public snapshot
AI called this Suspicious at 87.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • bin/cli.js exposes user-invoked hskill hooks install for claude/codex hook registration.
  • lib/installer.js writes ~/.claude/settings.json or project .claude/settings.json hook entries.
  • lib/installer.js writes ~/.codex/hooks.json and copies hook scripts into ~/.codex/hooks or project .codex/hooks.
  • lib/installer.js can append package tool snippets to ~/.zshrc after TTY confirmation.
  • bin/cli.js update runs npm install -g harveyz-skill@latest only when user invokes hskill update.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle hooks.
  • bin/cli.js is a CLI bin entrypoint; risky actions are subcommands or interactive selections, not import/install-time execution.
  • No credential harvesting or external exfiltration endpoint found in inspected hot paths.
  • Hook script hooks/check-similar-branch/check-similar-branch.sh checks git branch creation and calls local claude CLI; no exfiltration seen.
  • Scanner blob/test findings are fixtures or __init__.py files, not active install payloads.
Behavioral surface
Source
ChildProcessEnvironmentVarsFilesystemShell
Supply chain
HighEntropyStrings
ManifestNo manifest risk signals triggered.
scanned 6 file(s), 108 KB of source

Source & flagged code

9 flagged · loading source
bin/cli.jsView file
matchType = previous_version_dangerous_delta matchedPackage = harveyz-skill@0.22.1 matchedIdentity = npm:aGFydmV5ei1za2lsbA:0.22.1 similarity = 0.833 summary = stored previous version shares package body but lacks this dangerous source file
Critical
Previous Version Dangerous Delta

This package version adds a dangerous source file absent from the previous stored version; route for source-aware review.

bin/cli.jsView on unpkg
3import chalk from 'chalk' L4: import { execSync, spawnSync } from 'child_process' L5: import { existsSync, writeFileSync, unlinkSync } from 'fs'
High
Child Process

Package source references child process execution.

bin/cli.jsView on unpkg · L3
161try { L162: execSync('npm install -g harveyz-skill@latest', { stdio: 'inherit' }) L163: console.log(chalk.green(' ✔ hskill updated'))
High
Runtime Package Install

Package source invokes a package manager install command at runtime.

bin/cli.jsView on unpkg · L161
lib/installer.jsView file
56// Version-aware upgrade logic (mirrors skill behavior) L57: const home = os.homedir() L58: const dataDir = path.join(home, '.hskill', 'tools') ... L75: // Outdated: prompt in TTY, skip in non-TTY L76: if (!process.stdout.isTTY) { L77: skipped.push({ name: toolName, reason: 'outdated', installed: installedVersion, available: sourceVersion }) ... L185: L186: const zshrcPath = path.join(os.homedir(), '.zshrc') L187: const marker = `# >>> ${toolName}` ... L336: try { L337: data = JSON.parse(await fs.readFile(hooksJsonPath, 'utf-8')) L338: } catch { /* file doesn't exist yet */ }
Medium
Install Persistence

Source writes installer persistence such as shell profile or service configuration.

lib/installer.jsView on unpkg · L56
tools/sync-agent/sync_agent/syncthing.pyView file
path = tools/sync-agent/sync_agent/syncthing.py kind = build_helper sizeBytes = 3130 magicHex = [redacted]
Medium
Ships Build Helper

Package ships non-JavaScript build or shell helper files.

tools/sync-agent/sync_agent/syncthing.pyView on unpkg
skills/writing/forge-doc/tests/fixtures/full-test-rb.docxView file
path = skills/writing/forge-doc/tests/fixtures/full-test-rb.docx kind = compressed_blob sizeBytes = 131425 magicHex = [redacted]
Medium
Ships Compressed Blob

Package ships compressed or archive-like blobs.

skills/writing/forge-doc/tests/fixtures/full-test-rb.docxView on unpkg
path = skills/writing/forge-doc/tests/fixtures/full-test-rb.docx kind = nested_archive_needs_inspection sizeBytes = 131425 magicHex = [redacted]
Low
Nested Archive Needs Inspection

Package ships a nested archive or MCP bundle that was inventoried but not recursively analyzed.

skills/writing/forge-doc/tests/fixtures/full-test-rb.docxView on unpkg
skills/writing/forge-doc/tests/fixtures/full-test-thesis.pdfView file
path = skills/writing/forge-doc/tests/fixtures/full-test-thesis.pdf kind = high_entropy_blob sizeBytes = 798172 magicHex = [redacted]
High
Ships High Entropy Blob

Package ships high-entropy non-source blobs.

skills/writing/forge-doc/tests/fixtures/full-test-thesis.pdfView on unpkg
tools/sync-agent/tests/__init__.pyView file
path = tools/sync-agent/tests/__init__.py kind = payload_in_excluded_dir sizeBytes = 0
High
Payload In Excluded Dir

Package hides binary, compressed, or executable-looking payloads in test/fixture/hidden paths.

tools/sync-agent/tests/__init__.pyView on unpkg

Findings

1 Critical5 High5 Medium4 Low
CriticalPrevious Version Dangerous Deltabin/cli.js
HighChild Processbin/cli.js
HighShell
HighRuntime Package Installbin/cli.js
HighShips High Entropy Blobskills/writing/forge-doc/tests/fixtures/full-test-thesis.pdf
HighPayload In Excluded Dirtools/sync-agent/tests/__init__.py
MediumEnvironment Vars
MediumInstall Persistencelib/installer.js
MediumShips Build Helpertools/sync-agent/sync_agent/syncthing.py
MediumShips Compressed Blobskills/writing/forge-doc/tests/fixtures/full-test-rb.docx
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowNested Archive Needs Inspectionskills/writing/forge-doc/tests/fixtures/full-test-rb.docx