docs: add SCOPE.md and write down the contribution policy

Several open PRs could not be decided because CONTRIBUTING.md had nothing to
point at: no scope, no self-promotion or affiliation rules, no PR-size
guidance. Declining on an unwritten rule is unfair to contributors, so the
rules go in first.

SCOPE.md (new)
  What a skill is, and what this repository is not: runtimes, engines,
  products and applications belong in their own repositories. Offensive and
  dual-use content is explicitly in scope - the line is defensive framing and
  authorization, not subject matter.

CONTRIBUTING.md
  - one skill per pull request, and why batching stalls good work
  - overlap: while the description backlog is worked down, a new skill that
    overlaps an existing one will usually be asked to extend it instead
  - self-promotion and vendor links: commercial tools are fine, including
    ones with no free tier, but cost must be stated in Prerequisites and
    links must go to documentation rather than signup funnels
  - affiliation disclosure, with the consequence stated: the PR goes on hold
    until it is disclosed, and nothing is closed over it
  - AI-assisted contributions are allowed and must be disclosed; a human must
    have run the commands and takes responsibility
  - review and response, including a 14-day stale window that closes nothing
    permanently
  - subdomain list corrected from 24 entries to the 34 canonical values the
    validator actually accepts, with the 12 accepted aliases named

README.md
  Removed the claim that every PR is reviewed within 48 hours. The oldest
  open PR has been waiting since April. Replaced the stale "most in need"
  counts, which named domains with 2 and 5 skills that actually have 6 and 10.

tools/README.md
  Corrected to match the code: eight required frontmatter fields, not five,
  and PyYAML is now a dependency.
This commit is contained in:
Mahipal
2026-08-23 18:02:38 +02:00
parent d577ac953e
commit 6243c20d6d
4 changed files with 241 additions and 35 deletions
+150 -28
View File
@@ -1,5 +1,9 @@
# Contributing to Anthropic-Cybersecurity-Skills
Before you start, read [SCOPE.md](SCOPE.md). It defines what belongs in this catalogue and what does not, and it will save you building something I have to decline.
Most of the policy below is new. Until now this file said nothing about scope, overlap, disclosure or pull-request size, and the absence of those rules is why several well-made contributions ended up somewhere I could not merge them. That is my failure to document, not anyone's failure to read. **These rules apply to pull requests opened from here on.** Anything already open will be reviewed as it was filed.
## How to add a new skill
1. Create a new directory: `skills/your-skill-name/`
@@ -8,16 +12,18 @@
---
name: your-skill-name
description: >-
Clear description of what this skill does and when
an AI agent should activate it. Include keywords.
What the skill does, in one sentence naming the real tools and artefacts.
Use when THE TRIGGER CONDITION HOLDS. Keywords: tool, flag, artefact.
Do not use for THE ADJACENT TASK - use the-other-skill-name.
domain: cybersecurity
subdomain: [category]
subdomain: threat-hunting
tags: [tag1, tag2, tag3]
version: "1.0"
author: your-github-username
license: Apache-2.0
---
```
`subdomain` is a single value, not a list — `subdomain: [threat-hunting]` is a YAML list and will fail validation. `name` must equal the directory name. Frontmatter values may not contain `<` or `>`.
3. Write clear, step-by-step instructions in the Markdown body using these sections:
- ## When to Use
- ## Prerequisites
@@ -40,32 +46,148 @@
- [ ] Domain and subdomain are set correctly
- [ ] Tags include relevant tools, frameworks, and techniques
## Writing the description
The description is the only text an agent sees when it decides whether to load your skill. Everything else in the file is invisible at that moment. Four things have to be in it:
1. **What it does** — the procedure, the real tools, the real artefacts.
2. **When to fire** — an explicit `Use when …` clause.
3. **Keywords** — the flags, event IDs, file names and tool names someone would actually search for.
4. **When *not* to fire** — a `Do not use for …` clause that names the nearest neighbouring skill by slug.
A worked example, the current description of `scanning-docker-images-with-trivy`:
> Scans a Docker image with Trivy for vulnerabilities in OS packages and language dependencies, misconfiguration, exposed secrets, and licence violations, emitting SARIF, CycloneDX, or SPDX output. Use when scanning or gating a specific image, wiring an image scan into CI/CD, or checking an image during an incident investigation. Keywords: Trivy, image scan, --severity, --exit-code, SARIF, ignore file, .trivyignore. Do not use for cluster-wide scanning or non-image targets - use performing-container-security-scanning-with-trivy; when the toolchain is Grype use scanning-container-images-with-grype.
The linter enforces the mechanical parts: 1024 characters maximum, terminal punctuation, a trigger clause, a negative trigger, and a 500-line cap on the file. Roughly 980 pre-existing failures are grandfathered in `tools/lint-baseline.json` so the gate blocks new debt only. That baseline may shrink and may never grow, which means a new skill has to meet the standard even though many old ones do not yet.
## Before you open a pull request
Run the validators locally. All five run in CI on every push and pull request that touches `skills/` or `tools/` — which any skill PR does — and all five have to be green before I can merge. A PR that changes only documentation does not trigger them at all, so an empty checks list there is not a pass.
```bash
pip install pyyaml # the only external dependency
python tools/validate-skill.py skills/your-skill-name/ # frontmatter, this skill
python tools/lint-descriptions.py skills/your-skill-name/ # description quality, this skill
python tools/validate-agentskills.py --strict # conformance, whole repo
python tools/detect-collisions.py # near-duplicates, whole repo
python tools/generate-index.py # regenerate index.json
```
Three things that catch people out:
- **Two of those commands are repo-wide.** `validate-agentskills.py` and `detect-collisions.py` have no single-skill mode, so a failure they report may belong to a skill you never touched. Check the slug in the output before assuming it is yours.
- **`index.json` is generated, and the PR must carry the regenerated file.** It is refreshed automatically on `main`, but not on your branch, and the freshness gate runs at PR time. If you touched a description and did not commit the regenerated `index.json`, the build fails.
- **The collision gate is a ratchet, currently sitting exactly at its ceiling.** One new near-duplicate pair fails the build. The cap CI enforces lives in `.github/workflows/validate-skills.yml` and gets lowered as disambiguation lands — read it from there rather than memorising a number.
## One skill per pull request
Open one pull request per skill.
Each skill is reviewed for technical accuracy — whether the flags exist, whether the output format is real, whether the procedure works on the version you claim. That review does not batch. In a ten-skill pull request, one wrong procedure holds up nine good ones, and the whole thing tends to stall.
A PR that adds more than one skill directory will be asked to split. It is not a judgement on the work; it is the only way I can land the good parts quickly. The exception is a mechanical repo-wide change — a lint sweep, a metadata fix across many files — which is fine in one PR as long as the description says plainly what the change is and that nothing else varies.
## Overlap with an existing skill
The catalogue currently has 55 unreviewed near-duplicate description pairs, involving 94 of the 817 skills. Overlapping descriptions are not a cosmetic problem: when two descriptions look alike, the agent picks the wrong one, and both skills get less useful.
Until that backlog is worked down, **a new skill that overlaps an existing one will usually be asked to extend the existing skill instead.** Adding depth to `performing-firmware-extraction-with-binwalk` is worth more to this catalogue right now than a second firmware-extraction skill beside it. That redirect is about where the work lands, not about its quality — an extension PR carries the same authorship and gets the same credit.
Before you write a new skill:
1. Search `index.json` for the tool, the technique and the artefact.
2. Run `python tools/detect-collisions.py` and see whether your intended description lands near anything.
3. If something close exists, open an issue proposing the extension, or send a PR against the existing skill.
If the overlap is real but the skills genuinely need to stay separate — different operating system, different tool, different stage of the same investigation — say so in the PR and make both descriptions name the other explicitly. That is how the split is recorded, and it is what `tools/collision-allowlist.json` is for.
## Review and response
I review every pull request myself, and the queue is currently longer than I would like. Small, focused PRs move fastest.
If a PR gets a review request and then goes quiet for 14 days, I may close it as stale. That is housekeeping, not rejection: your branch and your work are untouched, and a single comment reopens the conversation whenever you are ready to pick it up.
## Disclosure
### Self-promotion and vendor links
No undisclosed self-links. If a skill, a reference file, a README entry or a script links to a product, service, repository or domain you are involved with, say so in the PR. A link that exists to send traffic somewhere rather than to help the reader complete the procedure will be removed.
Many skills legitimately cover commercial tools, including ones with no free tier at all. That is fine — the procedure is the point. What is required of vendor-specific content is:
- **Honesty about cost.** If the procedure needs a paid licence, an enterprise appliance or a sales conversation, say so in `## Prerequisites` rather than letting a reader find out at step six.
- **Documentation links, not marketing links.** Link the vendor's docs, API reference or CLI manual. No pricing pages, no signup funnels, no referral or campaign-tagged URLs.
- **No cross-selling.** A general procedure should not route the reader toward one vendor's product when the task does not require it.
The `## Tools & Resources` lists are a special case. They carry standards, RFCs and vendor-neutral documentation. If you want to add a commercial product to one, open an issue first naming what it does that no entry already in that list does. "It also does this" is not enough: there are 87 of these lists in the repository and every vendor in a given space has an equal claim on them, so without that bar they turn into directories.
This applies to me as well. Where the README links to something of mine, it should be labelled as mine.
### Affiliation
If you are affiliated with a product, service, vendor, project or domain referenced in your PR — you work there, contract for it, founded it, are paid by it, or maintain it — say so in the PR description. One line is enough.
Disclosure is not disqualifying. People who build a tool often write the most accurate procedure for it, and I would rather have that procedure with a disclosure than a vaguer one without. It is the non-disclosure that damages trust, because it turns every later reader into someone who has to guess. If it is unclear to me, I will ask; a plain answer settles it.
If an undisclosed connection surfaces during review, that is the entire consequence: the PR goes on hold until it is stated, and is then reviewed on its merits like anything else. Adding the disclosure when asked carries no penalty, and nothing is closed over it.
### AI-assisted contributions
AI assistance is allowed. This is a repository of skills for AI agents; banning it would be absurd.
What is required is disclosure and human responsibility:
- **Say so in the PR description.** One line is enough.
- **A human must have run the commands.** Not read them, not sanity-checked them — run them, on a real system, and seen the output that is now in the skill.
- **A human takes responsibility.** The `author` frontmatter field names a person or a team account, not a tool, and that account should be able to answer review questions about the procedure.
- **It still has to pass the validators**, like everything else.
The failure mode to guard against is a generated procedure that was never executed: flags that look plausible but do not exist, options borrowed from a different major version, output formats that were invented rather than observed. That kind of content is worse than no skill at all, because an agent will follow it confidently. Generated and verified is welcome; generated and unverified is not.
## Subdomains
Choose the most appropriate subdomain for your skill:
- web-application-security
- network-security
- penetration-testing
- red-teaming
- digital-forensics
- malware-analysis
- threat-intelligence
- cloud-security
- container-security
- identity-access-management
- cryptography
- vulnerability-management
- compliance-governance
- zero-trust-architecture
- ot-ics-security
- devsecops
- soc-operations
- incident-response
- phishing-defense
- ransomware-defense
- api-security
- mobile-security
- endpoint-security
- threat-hunting
Choose the most appropriate subdomain for your skill. `tools/validate-skill.py` is the source of truth; these 34 are the canonical values. A handful of older aliases are still accepted for existing skills and are listed beside their canonical form — the validator prints a warning for them, and new skills should use the canonical value.
- `ai-security`
- `api-security`
- `blockchain-security`
- `cloud-security`
- `compliance-governance` — also accepts `governance-risk-compliance`
- `container-security`
- `cryptography`
- `data-protection`
- `deception-technology`
- `devsecops`
- `digital-forensics`
- `endpoint-security`
- `hardware-firmware-security` — also accepts `firmware-analysis`, `firmware-security`
- `identity-access-management` — also accepts `identity-and-access-management`, `identity-security`
- `incident-response`
- `malware-analysis`
- `mobile-security`
- `network-security`
- `ot-ics-security` — also accepts `ot-security`
- `penetration-testing` — also accepts `offensive-security`
- `phishing-defense` — also accepts `social-engineering-defense`
- `privacy-compliance`
- `purple-team`
- `ransomware-defense`
- `red-teaming` — also accepts `red-team`
- `soc-operations` — also accepts `security-operations`
- `supply-chain-security`
- `threat-detection`
- `threat-hunting`
- `threat-intelligence`
- `vulnerability-management`
- `web-application-security` — also accepts `application-security`
- `wireless-security`
- `zero-trust-architecture` — also accepts `zero-trust`
If none of these fits, open an issue before you submit. Adding a subdomain means changing the validator, and that is a separate conversation from adding a skill.
The thinnest subdomains are the ones most worth contributing to: `data-protection` and `purple-team` have one skill each, and `blockchain-security`, `wireless-security` and `privacy-compliance` have two.
## Code of Conduct
This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md). By participating, you agree to uphold this code.
+4 -4
View File
@@ -383,15 +383,15 @@ Skills have continued to grow on `main` since v1.0.0 — the library now contain
This project grows through community contributions. Here is how to get involved:
**Add a new skill**Domains like Deception Technology (2 skills) and Compliance & Governance (5 skills) need the most help. Follow the template in [CONTRIBUTING.md](CONTRIBUTING.md) and submit a PR with the title `Add skill: your-skill-name`.
**Add a new skill**Read [SCOPE.md](SCOPE.md) first, then the template in [CONTRIBUTING.md](CONTRIBUTING.md). The thinnest domains are the ones most worth adding to: Data Protection and Purple Team have one skill each, and Blockchain Security, Wireless Security and Privacy Compliance have two. Submit one skill per PR, with the title `Add skill: your-skill-name`.
**Improve existing skills** — Add framework mappings, fix workflows, update tool references, or contribute scripts and templates.
**Improve existing skills** — Add framework mappings, fix workflows, update tool references, or contribute scripts and templates. Deepening a skill that already exists is worth as much to this library as adding a new one.
**Report issues** — Found an inaccurate procedure or broken script? [Open an issue](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues).
Every PR is reviewed for technical accuracy and agentskills.io standard compliance within 48 hours. Check [good first issues](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) for a starting point.
Every PR is reviewed for technical accuracy and agentskills.io standard compliance. I do that review myself, and the queue is currently longer than I would like — some pull requests have been open for months. I am working through them, and small, focused PRs move fastest. Check [good first issues](https://github.com/mukul975/Anthropic-Cybersecurity-Skills/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) for a starting point.
This project follows the [Contributor Covenant](https://www.contributor-covenant.org/). By participating, you agree to uphold this code.
This project follows the [Contributor Covenant](https://www.contributor-covenant.org/). By participating, you agree to uphold this code.
## 🙏 Thanks to our contributors
+82
View File
@@ -0,0 +1,82 @@
# Scope
This document defines what belongs in this repository and what does not.
It exists so the answer is available *before* the work is done rather than after it. Several of the pull requests I have had to decline were good work aimed at the wrong repository, and that is a documentation failure on my side, not a failure on the contributor's.
This repository is a catalogue. It holds cybersecurity procedures — 817 of them today — written so that an AI agent can read one and carry out a security task competently. Everything that ships here serves that one purpose. Work that does not serve it is out of scope regardless of how good it is, and is usually better off in its own repository, where it can be versioned, released and credited on its own terms.
## These rules apply going forward
This document is new. Until now the repository had no written scope, which is exactly why some contributors built things I then could not merge.
So: nothing here is applied retroactively as a reason to close a pull request that was already open when it landed. Every open PR will be worked through as it was filed, on its own merits, and where I decline one I will give the reason in the thread rather than pointing at a rule that did not exist when the work was done.
I should also say plainly that the review queue is longer than it should be — some pull requests have been waiting months. That is on me, not on the people who sent them, and raising the bar on new contributions does not excuse it. I am working through the backlog.
## What a skill is
A skill is one named security procedure that an agent can execute end to end.
On disk it is a single flat directory:
```
skills/your-skill-name/
├── SKILL.md # YAML frontmatter + the procedure
├── LICENSE
├── references/ # api-reference.md, standards.md, workflows.md
├── scripts/ # agent.py, process.py, or another real helper
└── assets/ # optional: template.md, filled-in checklists
```
The namespace is flat and global. `skills/` is not nested by category; the category lives in the `subdomain` frontmatter field, which must be one of the values accepted by `tools/validate-skill.py`. All 817 skills today carry `SKILL.md`, `references/` and `scripts/`; 816 carry a `LICENSE` and 421 also carry `assets/`. The most common supporting files are `references/api-reference.md` (810 skills) and `scripts/agent.py` (809).
A submission is a skill when all of the following hold.
**It is a procedure, not a subject.** By convention the directory name is a gerund phrase naming the task — `analyzing-…`, `detecting-…`, `implementing-…`, `hunting-…`, `performing-…` — and 807 of the 817 current names follow it. CI enforces kebab-case, not the gerund, so treat this as the house style rather than a gate. Background material about a topic belongs in a skill's `references/`, not in a directory of its own.
**It is atomic.** One procedure per skill. A body carrying three unrelated workflows is either three skills, or one skill and two reference files.
**It is executable.** Real commands, real flags, real tool names, real paths. No placeholders, no `TODO`, no prose standing in for a command nobody ran.
**Its description routes.** The description is the only text an agent sees when deciding whether to load the skill. It has to say what the skill does, when to fire, which keywords match, and what it is *not* for — naming the nearest neighbouring skill. The 33 container-security skills are the current reference for that standard.
**It is distinct.** It does not restate a skill that already exists. See *Overlap* in [CONTRIBUTING.md](CONTRIBUTING.md).
**It passes CI.** Five gates run on every push and pull request that touches `skills/` or `tools/`: frontmatter validation, agentskills.io conformance, `index.json` freshness, description linting, and a near-duplicate ratchet. A documentation-only PR does not trigger them, so do not read an empty checks list as a pass. CONTRIBUTING.md lists the commands to run them locally.
## Offensive and dual-use content is in scope
This library deliberately covers red-team tradecraft, exploitation, C2, phishing simulation and adversary emulation alongside defence. A defender's agent that has never seen the offensive procedure detects it badly.
Offensive skills are in scope on exactly the same terms as everything else, subject to the authorised-use notice in [README.md](README.md). Nothing in this document is a reason to decline a skill for being offensive. If I decline one, the reason will be scope, overlap or accuracy, and I will say which.
## Out of scope
**Runtimes, engines, orchestrators and agent frameworks.** Code that loads, serves, routes or executes skills — MCP servers, agent harnesses, skill-browser web UIs, "foundation" or "platform" layers that turn the catalogue into a product.
**Applications built on the catalogue.** A tool that consumes these skills is a good thing to build and I will happily link it from the README. It is not a directory in this repository.
**A second toolchain.** `tools/` already holds a frontmatter validator, an agentskills.io conformance checker, an index generator, a description linter and a collision detector — all sharing one PyYAML-backed loader, all wired into CI. A new independent validator competes with those rather than improving them. Extend the existing tool and the existing gate; a PR that makes `tools/lint-descriptions.py` stricter is far more welcome than a new linter beside it.
**Documents about how the project is run.** Roadmaps, work cadences, routines, release plans, launch material, status trackers. How I schedule my own maintenance is not something the catalogue needs to carry, and a document describing a cadence I have not agreed to would be wrong the day it merged. Propose process changes in an issue or a discussion instead.
**Editor, IDE and per-contributor configuration.** `.vscode/` settings, local linter configs and vendor extension settings encode one contributor's environment on everyone else. Agent instruction files are the single exception and they are maintainer-owned — `.github/copilot-instructions.md` exists and is maintained in place. Changes to that class of file should start as an issue, not as a new parallel file.
**Product-shaped skills.** A skill may absolutely be tool-specific: 247 of the 817 names carry a `-with-<tool>` qualifier, and `scanning-docker-images-with-trivy` is exactly right, because the flags, the output formats and the failure modes genuinely differ by tool. What does not belong is a directory whose *subject* is a product rather than a task — a feature tour, an onboarding walkthrough, or an integration write-up for one vendor's service. The test: if the vendor vanished tomorrow and nothing of the procedure survived, it was a product page. When a skill does name a commercial tool, the vendor-link rules in CONTRIBUTING.md apply.
**Bulk imports.** A pull request adding many skills at once cannot be reviewed for technical accuracy at the depth this catalogue needs, and one wrong procedure blocks all the others. One skill per pull request; see CONTRIBUTING.md.
## Why there is no engine in this repository
The catalogue is engine-neutral by construction. `skills/` contains content only; `tools/` contains validators and the index generator and nothing that executes a skill; `.claude-plugin/` contains manifests that let an existing engine mount the catalogue rather than an engine of its own. The bug-report template asks which agent you were running, offering Claude Code, GitHub Copilot and Codex CLI as examples, and the README targets 26+ platforms.
That neutrality is the asset. The moment a runtime lives in this repository, the content starts being shaped by what that runtime supports, the release cadence of the content gets tied to the release cadence of the code, and every consumer on a different platform inherits a dependency they did not ask for. I want the content here to stay separate from the engine that reads it, and I intend to keep this repository on that side of the line.
## Grey areas
Some things sit on the boundary — a large rewrite of an existing skill, a new subdomain, a reference file that is really a small tool, a documentation page that is not README and not CONTRIBUTING. Open an issue and ask before you build it. I would much rather answer a two-line issue than decline a finished pull request, and if the answer is yes, the issue becomes the record of why.
## Changing this document
This is a working document, not a settlement. If a rule here is wrong, or is blocking something the catalogue would clearly be better for having, open an issue arguing the case. Scope decisions are mine to make, but they should be arguable in the open.
+5 -3
View File
@@ -18,13 +18,15 @@ python tools/validate-skill.py --all
- SKILL.md exists in the skill directory
- Valid YAML frontmatter (between `---` markers)
- Required fields present: `name`, `description`, `domain`, `subdomain`, `tags`
- Required fields present: `name`, `description`, `domain`, `subdomain`, `tags`, `version`, `author`, `license`
- Name is kebab-case, 164 characters
- Description is at least 50 characters (no upper limit; multi-line folded scalars are valid)
- Description is at least 50 characters (agentskills.io caps it at 1024; `tools/validate-agentskills.py` enforces that)
- Domain is `cybersecurity`
- Subdomain is from the allowed list
- Tags is a list with at least 2 items
### Requirements
Python 3.8+ (stdlib only, no external dependencies)
Python 3.8+ and PyYAML (`pip install pyyaml`).
All frontmatter is parsed by `skill_frontmatter.py`, the single PyYAML-backed loader. It replaced three hand-rolled regex parsers that silently truncated multi-line descriptions to their first line — that bug shipped 604 of 817 descriptions broken in `index.json`. Do not reintroduce regex frontmatter parsing; CI fails the build if it detects any.