mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-06-26 19:54:37 +03:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 673da1f3b0 | |||
| 1f5cb12ac0 | |||
| f3a472b105 | |||
| 4e165f9a8d | |||
| 768ca51c8d | |||
| 5f5edbb30b | |||
| 40869a8c1c |
@@ -6,14 +6,14 @@
|
|||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"description": "817 cybersecurity skills for AI agents mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF, and the MITRE Fight Fraud Framework (F3).",
|
"description": "817 cybersecurity skills for AI agents mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF, and the MITRE Fight Fraud Framework (F3).",
|
||||||
"version": "1.2.0"
|
"version": "1.3.0"
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
"name": "cybersecurity-skills",
|
"name": "cybersecurity-skills",
|
||||||
"source": "./",
|
"source": "./",
|
||||||
"description": "817 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more. Mapped to 6 frameworks.",
|
"description": "817 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more. Mapped to 6 frameworks.",
|
||||||
"version": "1.2.0",
|
"version": "1.3.0",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "mukul975"
|
"name": "mukul975"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "cybersecurity-skills",
|
"name": "cybersecurity-skills",
|
||||||
"description": "817 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more.",
|
"description": "817 cybersecurity skills covering web security, pentesting, DFIR, threat intelligence, cloud security, malware analysis, and more.",
|
||||||
"version": "1.2.0"
|
"version": "1.3.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,57 +15,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Validate SKILL.md frontmatter with Python
|
# Single source of truth: tools/validate-skill.py validates required
|
||||||
run: |
|
# frontmatter fields, kebab-case name, description length, subdomain, and
|
||||||
python3 << 'EOF'
|
# tag count. (Previously this step duplicated a weaker inline parser.)
|
||||||
import os
|
- name: Validate SKILL.md frontmatter
|
||||||
import re
|
run: python3 tools/validate-skill.py --all
|
||||||
import sys
|
|
||||||
|
|
||||||
REQUIRED_FIELDS = ['name', 'description', 'domain', 'subdomain', 'tags', 'version', 'author', 'license']
|
|
||||||
errors = []
|
|
||||||
checked = 0
|
|
||||||
|
|
||||||
for root, dirs, files in os.walk('skills'):
|
|
||||||
for file in files:
|
|
||||||
if file == 'SKILL.md':
|
|
||||||
path = os.path.join(root, file)
|
|
||||||
checked += 1
|
|
||||||
with open(path, 'r', encoding='utf-8') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
# Check frontmatter exists
|
|
||||||
fm_match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
|
||||||
if not fm_match:
|
|
||||||
errors.append(f"{path}: Missing YAML frontmatter")
|
|
||||||
continue
|
|
||||||
|
|
||||||
fm = fm_match.group(1)
|
|
||||||
|
|
||||||
# Check required fields
|
|
||||||
for field in REQUIRED_FIELDS:
|
|
||||||
if not re.search(rf'^{field}:', fm, re.MULTILINE):
|
|
||||||
errors.append(f"{path}: Missing required field '{field}'")
|
|
||||||
|
|
||||||
# Check name format (kebab-case)
|
|
||||||
name_match = re.search(r'^name:\s*(.+)$', fm, re.MULTILINE)
|
|
||||||
if name_match:
|
|
||||||
name = name_match.group(1).strip().strip('"')
|
|
||||||
if not re.match(r'^[a-z0-9-]+$', name):
|
|
||||||
errors.append(f"{path}: Name '{name}' must be kebab-case")
|
|
||||||
if len(name) > 64:
|
|
||||||
errors.append(f"{path}: Name '{name}' exceeds 64 characters")
|
|
||||||
|
|
||||||
print(f"Checked {checked} SKILL.md files")
|
|
||||||
|
|
||||||
if errors:
|
|
||||||
print(f"\n{len(errors)} validation error(s):")
|
|
||||||
for e in errors:
|
|
||||||
print(f" ❌ {e}")
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
print(f"✅ All {checked} skills valid")
|
|
||||||
EOF
|
|
||||||
|
|
||||||
- name: Check for duplicate skill names
|
- name: Check for duplicate skill names
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
---
|
---
|
||||||
|
|
||||||
> ⚠️ **Community Project** — This is an independent, community-created project. Not affiliated with Anthropic PBC.
|
> ⚠️ **Community Project** — This is an independent, community-created project. Not affiliated with Anthropic PBC.
|
||||||
|
>
|
||||||
|
> 🔐 **Authorized & lawful use only.** This library includes offensive and dual-use techniques (e.g. red-team C2, phishing simulation, exploitation) intended for **authorized penetration testing, security research, defense, and education**. Only use them against systems you own or have **explicit written permission** to test, and comply with all applicable laws and rules of engagement. You are solely responsible for how you use these skills. See [SECURITY.md](SECURITY.md) and [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
## Give any AI agent the security skills of a senior analyst
|
## Give any AI agent the security skills of a senior analyst
|
||||||
|
|
||||||
|
|||||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@
|
|||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install in-toto securesystemslib[crypto]
|
pip install in-toto 'securesystemslib[crypto]'
|
||||||
```
|
```
|
||||||
|
|
||||||
## CLI Commands
|
## CLI Commands
|
||||||
|
|||||||
+19
-3
@@ -10,7 +10,10 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
import glob
|
import glob
|
||||||
|
|
||||||
REQUIRED_FIELDS = ["name", "description", "domain", "subdomain", "tags"]
|
# Kept in sync with the CI workflow (.github/workflows/validate-skills.yml),
|
||||||
|
# which now delegates to this script so there is a single source of truth.
|
||||||
|
REQUIRED_FIELDS = ["name", "description", "domain", "subdomain", "tags",
|
||||||
|
"version", "author", "license"]
|
||||||
|
|
||||||
# Canonical subdomain → set of accepted aliases (including canonical itself).
|
# Canonical subdomain → set of accepted aliases (including canonical itself).
|
||||||
# When a skill uses an alias, the validator accepts it but the canonical form
|
# When a skill uses an alias, the validator accepts it but the canonical form
|
||||||
@@ -50,7 +53,7 @@ _SUBDOMAIN_ALIASES = {
|
|||||||
"blockchain-security": {"blockchain-security"},
|
"blockchain-security": {"blockchain-security"},
|
||||||
"data-protection": {"data-protection"},
|
"data-protection": {"data-protection"},
|
||||||
"deception-technology": {"deception-technology"},
|
"deception-technology": {"deception-technology"},
|
||||||
"firmware-analysis": {"firmware-analysis", "firmware-security"},
|
"hardware-firmware-security": {"hardware-firmware-security", "firmware-analysis", "firmware-security"},
|
||||||
"privacy-compliance": {"privacy-compliance"},
|
"privacy-compliance": {"privacy-compliance"},
|
||||||
"purple-team": {"purple-team"},
|
"purple-team": {"purple-team"},
|
||||||
"supply-chain-security": {"supply-chain-security"},
|
"supply-chain-security": {"supply-chain-security"},
|
||||||
@@ -132,6 +135,14 @@ def parse_frontmatter(text):
|
|||||||
data[current_key] = list(list_values) # copy so future mutations don't leak
|
data[current_key] = list(list_values) # copy so future mutations don't leak
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Only TOP-LEVEL keys (column 0) define frontmatter fields. An indented
|
||||||
|
# ``key: value`` line belongs to a nested structure (e.g. a framework
|
||||||
|
# mapping object that has its own ``name:``/``id:``) and must NOT be
|
||||||
|
# treated as a top-level field — otherwise a nested ``name:`` clobbers
|
||||||
|
# the skill's real ``name``.
|
||||||
|
if line[:1].isspace():
|
||||||
|
continue
|
||||||
|
|
||||||
# Handle inline list: tags: [a, b, c]
|
# Handle inline list: tags: [a, b, c]
|
||||||
m = re.match(r"^(\w[\w_-]*):\s*\[(.+)\]\s*$", stripped)
|
m = re.match(r"^(\w[\w_-]*):\s*\[(.+)\]\s*$", stripped)
|
||||||
if m:
|
if m:
|
||||||
@@ -252,7 +263,12 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if sys.argv[1] == "--all":
|
if sys.argv[1] == "--all":
|
||||||
skill_dirs = sorted(glob.glob("skills/*/"))
|
# Skip .bak backup directories — they are stale copies without a SKILL.md.
|
||||||
|
# glob may return OS-native separators, so normalize before checking.
|
||||||
|
skill_dirs = sorted(
|
||||||
|
d for d in glob.glob("skills/*/")
|
||||||
|
if not d.rstrip("/\\").endswith(".bak")
|
||||||
|
)
|
||||||
if not skill_dirs:
|
if not skill_dirs:
|
||||||
print("ERROR: No skill directories found. Run from the repository root.")
|
print("ERROR: No skill directories found. Run from the repository root.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
Reference in New Issue
Block a user