# Gatekeeper

> This skill should be used before installing a skill, plugin, or MCP server from someone else — when the user says "is this skill safe", "check this before I install it", "audit this skill", "vet this plugin", "should I trust this", "scan this for malicious code", or pastes a GitHub link to a skill they are about to add. Reports what a skill actually touches next to what it claims to do, so the gap is visible before it runs with your permissions.

- Skill: `lkc-studio/gatekeeper` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add lkc-studio/gatekeeper`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lkc-studio/gatekeeper/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: lkc-studio (https://skillmd.com/u/lkc-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/lkc-studio/gatekeeper

---


# Gatekeeper: look before you install

Installing a skill is not like installing a library. A skill loads a stranger's
instructions into the agent's context *and* ships scripts that run with the
user's own permissions. The `SKILL.md` can tell the agent what to do; the
scripts can do anything the user can.

The catalogs make this a supply chain. Collections advertise hundreds of skills;
one compromised entry is enough. This skill checks one before it is trusted.

## What it cannot do — read this first

> **A clean report is not a safety guarantee, and this tool is not a sandbox.**

It reduces risk; it does not remove it. Three honest limits, stated up front
because a false sense of safety is more dangerous than none:

1. **It is triage, not proof.** It surfaces evidence for a human to weigh. It
   does not certify anything.
2. **Prose findings are adversarial.** A determined attacker rewords things to
   dodge keyword matching. This catches the careless and the opportunistic, not
   a targeted attack written to beat it.
3. **The real defences are elsewhere.** Don't install what you haven't read; run
   untrusted skills in a container; keep permissions narrow. Gatekeeper is the
   first filter, not the last.

**One more, learned the hard way:** a security scanner's own source contains
every threat pattern it searches for, so it matches itself and any *other*
security tool. Gatekeeper excludes itself by identity (not by suppressing rules),
but when scanning another scanner, expect its pattern definitions to trip these
rules — read those findings as pattern *definitions*, not behaviour.

## The one idea that makes it work

The same evidence means opposite things depending on the skill's purpose.

- A `curl` in an API-testing skill is its job. In a Markdown formatter it is a
  red flag.
- Reading `~/.ssh` in an SSH-key manager is expected. In a CSV tidier it is theft.

So a scanner that judges patterns in isolation is useless — it either buries the
user in false positives or waves the dangerous case through. The question is
never "does it do X", it is:

> **Does what it does exceed what it claims to do?**

That comparison is the work, and it is the part a person (or agent) must do. The
tool's job is to lay the two side by side.

## Step 1: get the evidence

```bash
scripts/gatekeeper.py ~/.claude/skills/the-skill      # one skill
scripts/gatekeeper.py --all ~/.claude/skills          # every installed skill
scripts/gatekeeper.py --json path/to/skill            # for further processing
```

Standard library only. It reads files and runs regexes — it never executes the
skill, so it is safe to point at something untrusted.

It prints the skill's own declared purpose, then what it found, grouped by
category with file and line. Three verdicts:

| Verdict | Meaning | Exit |
| --- | --- | --- |
| `PASS` | nothing notable | 0 |
| `REVIEW` | findings to weigh against the claim | 1 |
| `REFUSE` | a combination with no benign reading | 2 |

Only mechanical, hard-to-argue combinations auto-`REFUSE` (reads credentials
**and** reaches the network; obfuscation **wrapping** either). Everything at the
instruction level is `REVIEW` — because the scanner genuinely cannot tell an
attack from a skill that *documents* one, and guessing wrong in either direction
destroys its usefulness.

## Step 2: weigh each finding against the claim

This is the judgement the tool sets up but does not make. For every finding:

1. **Read the declared purpose** printed at the top.
2. **Ask if the finding is consistent with it.** A deploy skill that reads
   `~/.aws/credentials` — plausible. A "poem generator" that does — stop.
3. **Follow the worst combinations first.** Credentials + network is the classic
   exfiltration pair. Obfuscation is rarely innocent. Anything writing to
   `.claude/settings.json` can widen its own permissions.

The categories it reports:

| Category | Why it matters |
| --- | --- |
| reads credentials | keys, tokens, cookies — rarely needed unless it is an auth tool |
| sends data out | network egress — the exit route for anything it read |
| hides what it does | base64/eval/hex — legitimate tools are readable |
| installs itself | shell rc, cron, git hooks — outlives the task |
| changes permissions | edits `.claude/settings.json` / MCP config — can free itself |
| destroys data | recursive/forced deletes, force-push, history wipe |
| instruction-level | text aimed at the agent: overrides, secrecy, "run on every turn", permission grabs |

## Step 3: decide, and record why

- **REFUSE** — do not install. The exfiltration pattern has no good explanation.
- **REVIEW** — read the flagged lines in full. If each has an innocent reading
  consistent with the purpose, proceed; if one does not, treat it as REFUSE.
- **PASS** — lowest risk, still not a guarantee. For anything that will run with
  real permissions, skim the scripts yourself regardless.

Report the verdict, the findings that decided it, and — for a REVIEW that was
cleared — why each flag was benign. "Cleared after reading" with a reason is a
decision; a silent pass is not.

## When the skill is on GitHub, not yet installed

Clone it somewhere disposable and scan there. Do **not** install first.

```bash
git clone --depth 1 https://github.com/owner/skill /tmp/inspect-me
scripts/gatekeeper.py /tmp/inspect-me
```

Cloning runs nothing. Installing into `~/.claude/skills` makes it live. Keep that
order.

## Resources

- **`scripts/gatekeeper.py`** — the scanner. Categories, combination logic, and
  the three verdicts. `--all` for a directory, `--json` for pipelines, `-v` for
  every hit untruncated.
- **`references/threats.md`** — each category expanded: what a real attack looks
  like, why the benign version is common, and how to tell them apart. Plus the
  limits of static scanning and what genuine isolation requires.

Related: this is the install-time companion to the rest of the **evidence**
plugin — the same refusal to accept "it's probably fine" without looking.

