skills / security / tutorial
tutorial

How to spot a malicious skill or repo

A skill or repo can look green — thousands of installs, a reputable author, a friendly description — and still hand your machine, your files, and your API keys to code you never read. Here’s how to look before you trust.

The core idea: description ≠ capability

The description is marketing. The capability surface is what the code and its scripts can actually do. Your whole job is to close the gap between the two. A “frontend design” skill that quietly phones home and spawns a permission-bypassed sub-agent isn’t lying in its description — it’s just not telling you the dangerous 90%.

Rule zero: read before you install. Never run npm install or let an agent execute a skill you haven’t read — install/lifecycle scripts run before you get a chance to look.

10 red flags (and how to check each)

01 · INSTALL-TIME EXECUTION

Lifecycle scripts that run on install

Look for: postinstall / preinstall / prepare in package.json; build.rs; setup.py hooks. These run automatically the moment you install — no click required.

grep -n '"\(pre\|post\)install"\|"prepare"' package.json

Verdict: a postinstall that downloads a binary is normal for CLIs — but only if it fetches from a pinned, trusted host and verifies a checksum/signature before making it executable. No checksum = elevated risk.

02 · NETWORK-FETCH-THEN-EXECUTE

Downloads code, then runs it

Look for: curl … | sh, https.get(...) then chmod +x, npx <remote>, auto-update paths.

Ask: Which host? Hardcoded or attacker-influenceable? Any integrity check? A redirect that’s followed blindly can turn a trusted URL into an untrusted payload.

03 · SECRET-READING + A NETWORK SINK

The exfiltration shape

Look for: reads of ~/.ssh, ~/.aws, .env, keychains, browser cookie stores — combined with any outbound request. Either alone is a yellow flag; both together is the classic data-theft pattern.

grep -rn '\.ssh\|\.aws\|\.env\|id_rsa\|process\.env' scripts/ src/
04 · OBFUSCATION

Code that hides what it does

Look for: base64/atob/hex/fromCharCode decode followed by eval/exec; minified files that aren’t a vendored library. Legitimate tools don’t need to hide their logic. Treat opacity as intent.

05 · GITHUB ACTIONS: UNTRUSTED CODE + SECRETS

CI that runs a stranger’s PR with your secrets

Look for (in .github/workflows/): pull_request_target that checks out the PR head, third-party actions pinned by tag (mutable) not SHA, and ${{ github.event.* }} interpolated into a run: block (script injection).

06 · PERSISTENCE

Installs hooks, cron, or shell edits

Look for: writes to .claude/settings*.json, .cursor/, crontab, authorized_keys, ~/.zshrc. A hook that runs after every edit is a foothold — sometimes legitimate (a linter), sometimes not.

07 · PROMPT INJECTION IN THE INSTRUCTIONS

Text that tells the agent to misbehave

Look for (in SKILL.md / AGENTS.md / README): “ignore previous instructions”, “don’t tell the user”, “run without asking”, requests to escalate permissions or bypass sandboxes. The opposite — a skill that warns against injection — is a trust signal.

08 · COMMITTED SECRETS

Keys the author left in the repo

Look for: AKIA… (AWS), ghp_… (GitHub), sk-… (OpenAI), -----BEGIN … PRIVATE KEY-----, real .env values. Sloppy with their own secrets → sloppy with yours. (Tools: gitleaks, trufflehog.)

09 · DEPENDENCY HYGIENE

Typosquats and unpinned supply chain

Look for: a missing lockfile, deps pinned to latest, packages named one letter off a popular one (reqeusts, lodahs), or git+http deps pointing at arbitrary URLs.

10 · DESTRUCTIVE OPS WITHOUT GUARDRAILS

rm -rf, force-push, DROP

Look for: rm -rf on paths built from variables, git push --force, DROP TABLE, --delete in sync scripts. Scoped to the tool’s own temp dir = fine. Reaching into your data = not.

Capability, not character

Be fair. A reputable author lowers the odds of malicious intent — but it does not lower the capability of the code. Score what the code can do; name separately what it likely means. That’s why our scale gives both the browser tool with an unchecked binary download and the design skill that bypasses sandboxes a 4/8 — “adopt with a specific mitigation,” not “burn the author.”

Don’t do this by hand every time

Point an agent at the target and let the auditors run the whole checklist with file:line evidence:

Both are read-only: they never execute the target, never run npm install, never fetch a download URL. Clone into a throwaway dir, read, score.