From 86908794bea7fd1d0c4eabd2e325f93e25ff8fed Mon Sep 17 00:00:00 2001 From: Md Shariar Shanaz Shuvon <83355567+shuvonsec@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:54:55 +0800 Subject: [PATCH] refactor: flatten skills to top-level directories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each skill is now its own directory at the repo root, so the whole catalogue is visible from the repository listing instead of being buried two levels down under skills/security//. 38 skills move: 8 axguard-* orchestration skills and 30 security domain skills. All moves are renames, so history follows. Domain grouping is not lost — ai, application, discovery, identity, infrastructure and operations survive in the domain: field of the registry, which moves from skills/index.yaml to skills-index.yaml at the root. install.sh and uninstall.sh now discover skills by globbing top-level directories that contain a SKILL.md. Both previously carried the list by hand, and uninstall.sh had drifted: it omitted the axguard-security skill and the axguard-contribute.md and axguard-privacy.md commands, so those were left behind on removal. Deriving both lists from the repo fixes that and stops it recurring. validate_skills.py identified domain skills by their skills/security/ path. That signal is gone, so it now treats any skill not named axguard-* as a domain skill — the same 30/8 split — and keeps enforcing version, domain, license, ## Purpose and ## Research Provenance on them. test_skills.py asserted exactly 30 entries matching path: skills/security/. It now asserts every skill on disk is registered in skills-index.yaml, which is a stronger check and layout-independent. --- DEV.md | 4 +- README.md | 18 ++++- .../SKILL.md | 0 .../SKILL.md | 0 .../api-security => api-security}/SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../axguard-audit => axguard-audit}/SKILL.md | 0 {skills/axguard-cso => axguard-cso}/SKILL.md | 0 .../SKILL.md | 2 +- .../references/sources.md | 0 .../references/vuln-classes.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 2 +- .../references/mcp-tools.md | 2 +- .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 docs/SECURITY-KNOWLEDGE-INVENTORY.md | 8 +- docs/SKILL-SCHEMA.md | 2 +- docs/data/research/ai-security-corpus.md | 2 +- docs/mcp-skill-roadmap.md | 4 +- docs/mcp-tools.md | 2 +- docs/mcp.md | 2 +- docs/plugin.md | 4 +- .../SKILL.md | 0 .../SKILL.md | 0 install.sh | 40 ++-------- .../jwt-security => jwt-security}/SKILL.md | 0 .../ai/mcp-security => mcp-security}/SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 0 references/README.md | 2 +- scripts/validate_skills.py | 29 ++++--- .../SKILL.md | 0 .../SKILL.md | 0 .../SKILL.md | 4 +- .../SKILL.md | 2 +- .../SKILL.md | 0 skills/index.yaml => skills-index.yaml | 76 +++++++++---------- .../sql-injection => sql-injection}/SKILL.md | 0 .../ssrf-analysis => ssrf-analysis}/SKILL.md | 0 .../ssti-analysis => ssti-analysis}/SKILL.md | 0 .../SKILL.md | 0 tests/test_mcp_skill.py | 4 +- tests/test_skills.py | 14 ++-- .../SKILL.md | 0 uninstall.sh | 30 +++----- .../SKILL.md | 0 .../xss-analysis => xss-analysis}/SKILL.md | 0 57 files changed, 121 insertions(+), 132 deletions(-) rename {skills/security/ai/ai-agent-security => ai-agent-security}/SKILL.md (100%) rename {skills/security/ai/ai-application-security => ai-application-security}/SKILL.md (100%) rename {skills/security/application/api-security => api-security}/SKILL.md (100%) rename {skills/security/discovery/attack-surface-mapping => attack-surface-mapping}/SKILL.md (100%) rename {skills/security/identity/authentication-analysis => authentication-analysis}/SKILL.md (100%) rename {skills/security/identity/authorization-analysis => authorization-analysis}/SKILL.md (100%) rename {skills/axguard-audit => axguard-audit}/SKILL.md (100%) rename {skills/axguard-cso => axguard-cso}/SKILL.md (100%) rename {skills/axguard-knowledge => axguard-knowledge}/SKILL.md (96%) rename {skills/axguard-knowledge => axguard-knowledge}/references/sources.md (100%) rename {skills/axguard-knowledge => axguard-knowledge}/references/vuln-classes.md (100%) rename {skills/axguard-preship => axguard-preship}/SKILL.md (100%) rename {skills/axguard-remediate => axguard-remediate}/SKILL.md (100%) rename {skills/axguard-report => axguard-report}/SKILL.md (100%) rename {skills/axguard-security => axguard-security}/SKILL.md (98%) rename {skills/axguard-security => axguard-security}/references/mcp-tools.md (94%) rename {skills/axguard-triage => axguard-triage}/SKILL.md (100%) rename {skills/security/infrastructure/cloud-security => cloud-security}/SKILL.md (100%) rename {skills/security/application/command-injection => command-injection}/SKILL.md (100%) rename {skills/security/infrastructure/configuration-security => configuration-security}/SKILL.md (100%) rename {skills/security/application/deserialization-security => deserialization-security}/SKILL.md (100%) rename {skills/security/application/file-upload-security => file-upload-security}/SKILL.md (100%) rename {skills/security/application/graphql-security => graphql-security}/SKILL.md (100%) rename {skills/security/identity/jwt-security => jwt-security}/SKILL.md (100%) rename {skills/security/ai/mcp-security => mcp-security}/SKILL.md (100%) rename {skills/security/identity/oauth-security => oauth-security}/SKILL.md (100%) rename {skills/security/application/path-traversal => path-traversal}/SKILL.md (100%) rename {skills/security/ai/prompt-injection => prompt-injection}/SKILL.md (100%) rename {skills/security/application/prototype-pollution => prototype-pollution}/SKILL.md (100%) rename {skills/security/infrastructure/secrets-detection => secrets-detection}/SKILL.md (100%) rename {skills/security/discovery/security-architecture-review => security-architecture-review}/SKILL.md (100%) rename {skills/security/operations/security-remediation => security-remediation}/SKILL.md (97%) rename {skills/security/operations/security-triage => security-triage}/SKILL.md (98%) rename {skills/security/identity/session-security => session-security}/SKILL.md (100%) rename skills/index.yaml => skills-index.yaml (65%) rename {skills/security/application/sql-injection => sql-injection}/SKILL.md (100%) rename {skills/security/application/ssrf-analysis => ssrf-analysis}/SKILL.md (100%) rename {skills/security/application/ssti-analysis => ssti-analysis}/SKILL.md (100%) rename {skills/security/infrastructure/supply-chain-security => supply-chain-security}/SKILL.md (100%) rename {skills/security/discovery/threat-modeling => threat-modeling}/SKILL.md (100%) rename {skills/security/application/websocket-security => websocket-security}/SKILL.md (100%) rename {skills/security/application/xss-analysis => xss-analysis}/SKILL.md (100%) diff --git a/DEV.md b/DEV.md index 9e32db3..61e5e87 100644 --- a/DEV.md +++ b/DEV.md @@ -123,8 +123,8 @@ Full schema and examples: [docs/adding-rules.md](docs/adding-rules.md) **Command** — `commands/axguard-.md` Front matter `description:` becomes the agent help text. Keep steps concrete: run which CLI, which paths, what to output. -**Skill** — `skills/axguard-/SKILL.md` (orchestration) or `skills/security///SKILL.md` (research-backed domain skill) -YAML front matter: `name`, `description`. Description must say *when* to load the skill. Domain skills follow [docs/SKILL-SCHEMA.md](docs/SKILL-SCHEMA.md) and must appear in [skills/index.yaml](skills/index.yaml). +**Skill** — a top-level directory with a `SKILL.md`: `axguard-/` (orchestration) or `/` (research-backed domain skill) +YAML front matter: `name`, `description`. Description must say *when* to load the skill. Domain skills follow [docs/SKILL-SCHEMA.md](docs/SKILL-SCHEMA.md) and must appear in [skills-index.yaml](skills-index.yaml). After adding files: diff --git a/README.md b/README.md index 0202b2a..3282670 100644 --- a/README.md +++ b/README.md @@ -469,19 +469,33 @@ Same `--agent` and `--global` / `--project` options as `install.sh`. To remove t ## Project structure +Each skill is its own top-level directory containing a `SKILL.md`, so the whole +catalogue is visible from the repo root. + ```text AXguard/ +├── axguard-audit/ # 8 orchestration skills, named axguard-* +├── axguard-cso/ +├── … +├── sql-injection/ # 30 security domain skills +├── prompt-injection/ +├── jwt-security/ +├── … +├── skills-index.yaml # skill registry — name, domain, path +├── commands/ # 31 slash commands ├── cli/ # axguard CLI entrypoint ├── engines/ # scanners, diagnostics, adapters ├── rules/ # detection rule packs (*.json) -├── skills/ # agent skills (8 orchestration + 30 security) -├── commands/ # 31 slash commands ├── fixtures/ # deliberately vulnerable test apps ├── tests/ # 438 tests ├── scripts/ # skill validation └── docs/ # developer and feature documentation ``` +Domain grouping (`ai`, `application`, `discovery`, `identity`, `infrastructure`, +`operations`) lives in the `domain:` field of `skills-index.yaml` rather than in +the directory tree. + ## Docs | Area | Docs | diff --git a/skills/security/ai/ai-agent-security/SKILL.md b/ai-agent-security/SKILL.md similarity index 100% rename from skills/security/ai/ai-agent-security/SKILL.md rename to ai-agent-security/SKILL.md diff --git a/skills/security/ai/ai-application-security/SKILL.md b/ai-application-security/SKILL.md similarity index 100% rename from skills/security/ai/ai-application-security/SKILL.md rename to ai-application-security/SKILL.md diff --git a/skills/security/application/api-security/SKILL.md b/api-security/SKILL.md similarity index 100% rename from skills/security/application/api-security/SKILL.md rename to api-security/SKILL.md diff --git a/skills/security/discovery/attack-surface-mapping/SKILL.md b/attack-surface-mapping/SKILL.md similarity index 100% rename from skills/security/discovery/attack-surface-mapping/SKILL.md rename to attack-surface-mapping/SKILL.md diff --git a/skills/security/identity/authentication-analysis/SKILL.md b/authentication-analysis/SKILL.md similarity index 100% rename from skills/security/identity/authentication-analysis/SKILL.md rename to authentication-analysis/SKILL.md diff --git a/skills/security/identity/authorization-analysis/SKILL.md b/authorization-analysis/SKILL.md similarity index 100% rename from skills/security/identity/authorization-analysis/SKILL.md rename to authorization-analysis/SKILL.md diff --git a/skills/axguard-audit/SKILL.md b/axguard-audit/SKILL.md similarity index 100% rename from skills/axguard-audit/SKILL.md rename to axguard-audit/SKILL.md diff --git a/skills/axguard-cso/SKILL.md b/axguard-cso/SKILL.md similarity index 100% rename from skills/axguard-cso/SKILL.md rename to axguard-cso/SKILL.md diff --git a/skills/axguard-knowledge/SKILL.md b/axguard-knowledge/SKILL.md similarity index 96% rename from skills/axguard-knowledge/SKILL.md rename to axguard-knowledge/SKILL.md index 0184728..a5a1efa 100644 --- a/skills/axguard-knowledge/SKILL.md +++ b/axguard-knowledge/SKILL.md @@ -44,7 +44,7 @@ Reference skill for **pre-ship static review**. Distills web and agent vuln clas ## Domain skills (deep reasoning) -For class depth beyond this digest, load research-backed skills under `skills/security/` (registry: `skills/index.yaml`): +For class depth beyond this digest, load the research-backed domain skills (registry: `skills-index.yaml`): | Need | Skill | |------|--------| diff --git a/skills/axguard-knowledge/references/sources.md b/axguard-knowledge/references/sources.md similarity index 100% rename from skills/axguard-knowledge/references/sources.md rename to axguard-knowledge/references/sources.md diff --git a/skills/axguard-knowledge/references/vuln-classes.md b/axguard-knowledge/references/vuln-classes.md similarity index 100% rename from skills/axguard-knowledge/references/vuln-classes.md rename to axguard-knowledge/references/vuln-classes.md diff --git a/skills/axguard-preship/SKILL.md b/axguard-preship/SKILL.md similarity index 100% rename from skills/axguard-preship/SKILL.md rename to axguard-preship/SKILL.md diff --git a/skills/axguard-remediate/SKILL.md b/axguard-remediate/SKILL.md similarity index 100% rename from skills/axguard-remediate/SKILL.md rename to axguard-remediate/SKILL.md diff --git a/skills/axguard-report/SKILL.md b/axguard-report/SKILL.md similarity index 100% rename from skills/axguard-report/SKILL.md rename to axguard-report/SKILL.md diff --git a/skills/axguard-security/SKILL.md b/axguard-security/SKILL.md similarity index 98% rename from skills/axguard-security/SKILL.md rename to axguard-security/SKILL.md index 1f2feb3..8926481 100644 --- a/skills/axguard-security/SKILL.md +++ b/axguard-security/SKILL.md @@ -9,7 +9,7 @@ This skill does **not** implement security analysis. It teaches when to use AXGu **Primary interface:** AXGuard MCP tools (prefer over ad-hoc scans). **Fallback:** if MCP is unavailable, `axguard scan .` / `axguard audit .` — then still apply the same verdict rules below. -Tool names: `references/mcp-tools.md` · catalog: [docs/mcp-tools.md](../../docs/mcp-tools.md). +Tool names: `references/mcp-tools.md` · catalog: [docs/mcp-tools.md](../docs/mcp-tools.md). ## When to call AXGuard diff --git a/skills/axguard-security/references/mcp-tools.md b/axguard-security/references/mcp-tools.md similarity index 94% rename from skills/axguard-security/references/mcp-tools.md rename to axguard-security/references/mcp-tools.md index 5893a7c..dba8208 100644 --- a/skills/axguard-security/references/mcp-tools.md +++ b/axguard-security/references/mcp-tools.md @@ -1,6 +1,6 @@ # MCP tools (names only) -Prefer these over inventing scanner chains. Full contracts: [docs/mcp-tools.md](../../../docs/mcp-tools.md). +Prefer these over inventing scanner chains. Full contracts: [docs/mcp-tools.md](../../docs/mcp-tools.md). | Tool | Role | |------|------| diff --git a/skills/axguard-triage/SKILL.md b/axguard-triage/SKILL.md similarity index 100% rename from skills/axguard-triage/SKILL.md rename to axguard-triage/SKILL.md diff --git a/skills/security/infrastructure/cloud-security/SKILL.md b/cloud-security/SKILL.md similarity index 100% rename from skills/security/infrastructure/cloud-security/SKILL.md rename to cloud-security/SKILL.md diff --git a/skills/security/application/command-injection/SKILL.md b/command-injection/SKILL.md similarity index 100% rename from skills/security/application/command-injection/SKILL.md rename to command-injection/SKILL.md diff --git a/skills/security/infrastructure/configuration-security/SKILL.md b/configuration-security/SKILL.md similarity index 100% rename from skills/security/infrastructure/configuration-security/SKILL.md rename to configuration-security/SKILL.md diff --git a/skills/security/application/deserialization-security/SKILL.md b/deserialization-security/SKILL.md similarity index 100% rename from skills/security/application/deserialization-security/SKILL.md rename to deserialization-security/SKILL.md diff --git a/docs/SECURITY-KNOWLEDGE-INVENTORY.md b/docs/SECURITY-KNOWLEDGE-INVENTORY.md index ddbb87d..7ce252a 100644 --- a/docs/SECURITY-KNOWLEDGE-INVENTORY.md +++ b/docs/SECURITY-KNOWLEDGE-INVENTORY.md @@ -4,7 +4,7 @@ Accessed: 2026-09-15 Repo: https://github.com/Awarexone/AXguard Status: **30 core domain skills landed** (plus 7 orchestration skills) -## Orchestration skills (`skills/axguard-*`) +## Orchestration skills (`axguard-*`) | Skill | Role | |---|---| @@ -16,7 +16,7 @@ Status: **30 core domain skills landed** (plus 7 orchestration skills) | `axguard-report` | Report authoring | | `axguard-knowledge` | Vuln-class digest → links to domain skills | -## Domain skills (`skills/security/`) — 30 core +## Domain skills — 30 core ### Discovery (3) `threat-modeling`, `attack-surface-mapping`, `security-architecture-review` @@ -36,7 +36,7 @@ Status: **30 core domain skills landed** (plus 7 orchestration skills) ### Operations (2) `security-triage`, `security-remediation` -Registry: [`skills/index.yaml`](../skills/index.yaml) +Registry: [`skills-index.yaml`](../skills-index.yaml) Schema: [`docs/SKILL-SCHEMA.md`](SKILL-SCHEMA.md) Validator: `python scripts/validate_skills.py` @@ -57,7 +57,7 @@ Validator: `python scripts/validate_skills.py` ## Design decisions -1. Keep `axguard-*` orchestration; add domain depth under `skills/security/`. +1. Keep `axguard-*` orchestration; add domain depth as new top-level skills. 2. Never invent framework IDs; leave arrays empty when UNVERIFIED (e.g. LLM Top 10 frontmatter). 3. Defensive / authorized pre-ship use only. 4. Install flattens domain skills by basename via `install_security_skills` in `install.sh`. diff --git a/docs/SKILL-SCHEMA.md b/docs/SKILL-SCHEMA.md index 65cb48e..aaa7838 100644 --- a/docs/SKILL-SCHEMA.md +++ b/docs/SKILL-SCHEMA.md @@ -1,6 +1,6 @@ # Skill frontmatter schema (AXGuard) -Every domain skill under `skills/security/` SHOULD use this YAML frontmatter. +Every domain skill — any top-level skill directory not named `axguard-*` — SHOULD use this YAML frontmatter. ```yaml --- diff --git a/docs/data/research/ai-security-corpus.md b/docs/data/research/ai-security-corpus.md index b19b506..54b4563 100644 --- a/docs/data/research/ai-security-corpus.md +++ b/docs/data/research/ai-security-corpus.md @@ -389,6 +389,6 @@ Keep AI rows in a separate corpus file until schema union is implemented; link w - Attack-path fixture: `fixtures/attack_paths_corpus/ai_mcp_tool_abuse.py` - Rules: `rules/agent.json`, `rules/advanced.json` -- Skills: `skills/security/ai/prompt-injection/SKILL.md`, `ai-agent-security/SKILL.md`, `mcp-security/SKILL.md` +- Skills: `prompt-injection/SKILL.md`, `ai-agent-security/SKILL.md`, `mcp-security/SKILL.md` - FP reason alignment: `docs/data/research/false-positive-corpus.md` - Architecture: `docs/architecture.md` (Phase 4 adversary, Phase 6 attack graph) diff --git a/docs/mcp-skill-roadmap.md b/docs/mcp-skill-roadmap.md index 892b5b3..5304908 100644 --- a/docs/mcp-skill-roadmap.md +++ b/docs/mcp-skill-roadmap.md @@ -1,7 +1,7 @@ # AXGuard MCP → Agent Skill Roadmap **Date:** 2026-09-17 -**Status:** Skill implemented — `skills/axguard-security/` (behavioral wrapper over MCP; no duplicated engines). +**Status:** Skill implemented — `axguard-security/` (behavioral wrapper over MCP; no duplicated engines). **Related:** [mcp-research.md](./mcp-research.md), [mcp-threat-model.md](./mcp-threat-model.md), [mcp.md](./mcp.md) --- @@ -29,7 +29,7 @@ name: axguard-security description: Analyze code for security vulnerabilities, investigate findings, verify fixes, and assess security risk before deployment. ``` -Path: `skills/axguard-security/SKILL.md` +Path: `axguard-security/SKILL.md` The skill instructs: diff --git a/docs/mcp-tools.md b/docs/mcp-tools.md index af1b0d8..7a47f7e 100644 --- a/docs/mcp-tools.md +++ b/docs/mcp-tools.md @@ -77,7 +77,7 @@ Does **not** modify source, execute exploits, or treat predictive risk as a veri Verdicts remain AXGuard-owned (`VERIFIED` · `LIKELY` · `UNVERIFIED` · `FALSE_POSITIVE` · `REQUIRES_REVIEW`). Agents must not “declare vulnerable” without this evidence path. -**Agent Skill:** prefer MCP tools via `skills/axguard-security` rather than inventing scan chains. +**Agent Skill:** prefer MCP tools via `axguard-security` rather than inventing scan chains. --- diff --git a/docs/mcp.md b/docs/mcp.md index ff97638..a1175d2 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -89,7 +89,7 @@ The behavioral layer above MCP (no duplicated scanners): ```text AI Coding Agent ↓ -AXGuard Agent Skill (`skills/axguard-security`) +AXGuard Agent Skill (`axguard-security`) ↓ AXGuard MCP ↓ diff --git a/docs/plugin.md b/docs/plugin.md index 949415a..c34123a 100644 --- a/docs/plugin.md +++ b/docs/plugin.md @@ -25,8 +25,8 @@ Manifest: `.claude-plugin/plugin.json` ## Layout expectations ```text -skills/axguard-audit/SKILL.md -skills/axguard-cso/SKILL.md +axguard-audit/SKILL.md +axguard-cso/SKILL.md … commands/axguard-audit.md commands/axguard-scan.md diff --git a/skills/security/application/file-upload-security/SKILL.md b/file-upload-security/SKILL.md similarity index 100% rename from skills/security/application/file-upload-security/SKILL.md rename to file-upload-security/SKILL.md diff --git a/skills/security/application/graphql-security/SKILL.md b/graphql-security/SKILL.md similarity index 100% rename from skills/security/application/graphql-security/SKILL.md rename to graphql-security/SKILL.md diff --git a/install.sh b/install.sh index ee518dd..068e4a6 100755 --- a/install.sh +++ b/install.sh @@ -35,26 +35,7 @@ done ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" -copy_tree_items() { - local src_glob="$1" - local dest_dir="$2" - local label="$3" - mkdir -p "$dest_dir" - local item name - for item in $src_glob; do - [ -e "$item" ] || continue - # Skip the security/ namespace directory itself; nested skills installed separately - [ "$(basename "$item")" = "security" ] && continue - [ "$(basename "$item")" = "index.yaml" ] && continue - name="$(basename "$item")" - rm -rf "$dest_dir/$name" - mkdir -p "$dest_dir/$name" - cp -R "$item"/. "$dest_dir/$name/" - echo "installed $label: $name → $dest_dir/$name" - done -} - -install_security_skills() { +install_skills() { local dest_dir="$1" mkdir -p "$dest_dir" local skill_md skill_dir name @@ -64,8 +45,8 @@ install_security_skills() { rm -rf "$dest_dir/$name" mkdir -p "$dest_dir/$name" cp -R "$skill_dir"/. "$dest_dir/$name/" - echo "installed security skill: $name → $dest_dir/$name" - done < <(find skills/security -type f -name SKILL.md 2>/dev/null | sort) + echo "installed skill: $name → $dest_dir/$name" + done < <(find . -mindepth 2 -maxdepth 2 -type f -name SKILL.md 2>/dev/null | sort) } copy_files() { @@ -86,8 +67,7 @@ install_claude() { local root if [ "$SCOPE" = "project" ]; then root=".claude"; else root="$HOME/.claude"; fi echo "AXguard → Claude Code ($SCOPE)" - copy_tree_items "skills/*" "$root/skills" "skill" - install_security_skills "$root/skills" + install_skills "$root/skills" copy_files "commands/*.md" "$root/commands" "command" } @@ -95,8 +75,7 @@ install_cursor() { local root if [ "$SCOPE" = "project" ]; then root=".cursor"; else root="$HOME/.cursor"; fi echo "AXguard → Cursor ($SCOPE)" - copy_tree_items "skills/*" "$root/skills" "skill" - install_security_skills "$root/skills" + install_skills "$root/skills" # Cursor also picks up project rules; commands map to skills for slash-style prompts mkdir -p "$root/commands" copy_files "commands/*.md" "$root/commands" "command" @@ -110,8 +89,7 @@ install_opencode() { root="${OPENCODE_CONFIG_DIR:-$HOME/.config/opencode}" fi echo "AXguard → OpenCode ($SCOPE)" - copy_tree_items "skills/*" "$root/skills" "skill" - install_security_skills "$root/skills" + install_skills "$root/skills" copy_files "commands/*.md" "$root/commands" "command" } @@ -119,8 +97,7 @@ install_codex() { local root if [ "$SCOPE" = "project" ]; then root=".codex"; else root="${CODEX_HOME:-$HOME/.codex}"; fi echo "AXguard → Codex ($SCOPE)" - copy_tree_items "skills/*" "$root/skills" "skill" - install_security_skills "$root/skills" + install_skills "$root/skills" copy_files "commands/*.md" "$root/commands" "command" } @@ -128,8 +105,7 @@ install_agents() { local root if [ "$SCOPE" = "project" ]; then root=".agents"; else root="$HOME/.agents"; fi echo "AXguard → shared Agent Skills ($SCOPE)" - copy_tree_items "skills/*" "$root/skills" "skill" - install_security_skills "$root/skills" + install_skills "$root/skills" } echo "" diff --git a/skills/security/identity/jwt-security/SKILL.md b/jwt-security/SKILL.md similarity index 100% rename from skills/security/identity/jwt-security/SKILL.md rename to jwt-security/SKILL.md diff --git a/skills/security/ai/mcp-security/SKILL.md b/mcp-security/SKILL.md similarity index 100% rename from skills/security/ai/mcp-security/SKILL.md rename to mcp-security/SKILL.md diff --git a/skills/security/identity/oauth-security/SKILL.md b/oauth-security/SKILL.md similarity index 100% rename from skills/security/identity/oauth-security/SKILL.md rename to oauth-security/SKILL.md diff --git a/skills/security/application/path-traversal/SKILL.md b/path-traversal/SKILL.md similarity index 100% rename from skills/security/application/path-traversal/SKILL.md rename to path-traversal/SKILL.md diff --git a/skills/security/ai/prompt-injection/SKILL.md b/prompt-injection/SKILL.md similarity index 100% rename from skills/security/ai/prompt-injection/SKILL.md rename to prompt-injection/SKILL.md diff --git a/skills/security/application/prototype-pollution/SKILL.md b/prototype-pollution/SKILL.md similarity index 100% rename from skills/security/application/prototype-pollution/SKILL.md rename to prototype-pollution/SKILL.md diff --git a/references/README.md b/references/README.md index 452ba10..e1b20ad 100644 --- a/references/README.md +++ b/references/README.md @@ -26,6 +26,6 @@ Public Sources → Collection → Normalization → Dedup → Classification → Validation → Framework Mapping → Skill Generation → Review → SKILL.md ``` -Skill registry: [`../skills/index.yaml`](../skills/index.yaml) +Skill registry: [`../skills-index.yaml`](../skills-index.yaml) Schema: [`../docs/SKILL-SCHEMA.md`](../docs/SKILL-SCHEMA.md) Validator: `python scripts/validate_skills.py` diff --git a/scripts/validate_skills.py b/scripts/validate_skills.py index 58fcc2e..aea2036 100644 --- a/scripts/validate_skills.py +++ b/scripts/validate_skills.py @@ -8,16 +8,21 @@ from pathlib import Path ROOT = Path(__file__).resolve().parents[1] -SKILL_ROOTS = [ROOT / "skills"] -INDEX = ROOT / "skills" / "index.yaml" +INDEX = ROOT / "skills-index.yaml" + +# Skills live in top-level directories. Orchestration skills are named +# axguard-*; everything else is a security domain skill, which carries +# stricter frontmatter and section requirements. +ORCHESTRATION_PREFIX = "axguard-" def iter_skills(): - for base in SKILL_ROOTS: - if not base.exists(): - continue - for path in sorted(base.rglob("SKILL.md")): - yield path + for path in sorted(ROOT.glob("*/SKILL.md")): + yield path + + +def is_domain_skill(path) -> bool: + return not path.parent.name.startswith(ORCHESTRATION_PREFIX) def parse_frontmatter(text: str) -> tuple[dict[str, str], str]: @@ -60,7 +65,7 @@ def main() -> int: names[name] = path if not meta.get("description"): errors.append(f"{path}: missing description") - if "skills/security/" in str(path).replace("\\", "/"): + if is_domain_skill(path): for key in ("version", "domain", "license"): if key not in meta: errors.append(f"{path}: security skill missing '{key}'") @@ -76,16 +81,16 @@ def main() -> int: for rel in parse_index_paths(index_text): p = ROOT / rel if not p.is_file(): - errors.append(f"skills/index.yaml: missing path {rel}") + errors.append(f"skills-index.yaml: missing path {rel}") # Every security domain skill should be registered for path in iter_skills(): - if "skills/security/" not in str(path).replace("\\", "/"): + if not is_domain_skill(path): continue rel = str(path.relative_to(ROOT)).replace("\\", "/") if rel not in index_text: - errors.append(f"skills/index.yaml: unlisted security skill {rel}") + errors.append(f"skills-index.yaml: unlisted security skill {rel}") else: - errors.append("skills/index.yaml missing") + errors.append("skills-index.yaml missing") print(f"skills scanned: {count}") if errors: diff --git a/skills/security/infrastructure/secrets-detection/SKILL.md b/secrets-detection/SKILL.md similarity index 100% rename from skills/security/infrastructure/secrets-detection/SKILL.md rename to secrets-detection/SKILL.md diff --git a/skills/security/discovery/security-architecture-review/SKILL.md b/security-architecture-review/SKILL.md similarity index 100% rename from skills/security/discovery/security-architecture-review/SKILL.md rename to security-architecture-review/SKILL.md diff --git a/skills/security/operations/security-remediation/SKILL.md b/security-remediation/SKILL.md similarity index 97% rename from skills/security/operations/security-remediation/SKILL.md rename to security-remediation/SKILL.md index 8517f2f..ffda04e 100644 --- a/skills/security/operations/security-remediation/SKILL.md +++ b/security-remediation/SKILL.md @@ -114,9 +114,9 @@ Operational skill — inherit CWE/OWASP IDs from the finding’s domain skill wh ## References -- AXGuard `skills/axguard-remediate/SKILL.md` +- AXGuard `axguard-remediate/SKILL.md` - https://owasp.org/www-project-cheat-sheets/ (methodology; no large verbatim copies) -- Domain skill Remediation sections in `skills/security/` +- Remediation sections in the domain skills ## Research Provenance diff --git a/skills/security/operations/security-triage/SKILL.md b/security-triage/SKILL.md similarity index 98% rename from skills/security/operations/security-triage/SKILL.md rename to security-triage/SKILL.md index 124f9c4..d317fa6 100644 --- a/skills/security/operations/security-triage/SKILL.md +++ b/security-triage/SKILL.md @@ -108,7 +108,7 @@ Operational skill — no primary CWE/OWASP entry. Findings retain the framework ## References -- AXGuard `skills/axguard-triage/SKILL.md` +- AXGuard `axguard-triage/SKILL.md` - https://owasp.org/Top10/ (severity context only) ## Research Provenance diff --git a/skills/security/identity/session-security/SKILL.md b/session-security/SKILL.md similarity index 100% rename from skills/security/identity/session-security/SKILL.md rename to session-security/SKILL.md diff --git a/skills/index.yaml b/skills-index.yaml similarity index 65% rename from skills/index.yaml rename to skills-index.yaml index c7ae59b..7d0e668 100644 --- a/skills/index.yaml +++ b/skills-index.yaml @@ -6,158 +6,158 @@ skills: # Orchestration (existing) - name: axguard-audit domain: operations - path: skills/axguard-audit/SKILL.md + path: axguard-audit/SKILL.md - name: axguard-preship domain: operations - path: skills/axguard-preship/SKILL.md + path: axguard-preship/SKILL.md - name: axguard-cso domain: operations - path: skills/axguard-cso/SKILL.md + path: axguard-cso/SKILL.md - name: axguard-triage domain: operations - path: skills/axguard-triage/SKILL.md + path: axguard-triage/SKILL.md - name: axguard-remediate domain: operations - path: skills/axguard-remediate/SKILL.md + path: axguard-remediate/SKILL.md - name: axguard-report domain: operations - path: skills/axguard-report/SKILL.md + path: axguard-report/SKILL.md - name: axguard-knowledge domain: operations - path: skills/axguard-knowledge/SKILL.md + path: axguard-knowledge/SKILL.md - name: axguard-security domain: operations - path: skills/axguard-security/SKILL.md + path: axguard-security/SKILL.md related: [axguard-preship, axguard-audit, axguard-remediate] # Domain skills — discovery (3) - name: threat-modeling domain: discovery - path: skills/security/discovery/threat-modeling/SKILL.md + path: threat-modeling/SKILL.md related: [attack-surface-mapping, security-architecture-review, axguard-cso] - name: attack-surface-mapping domain: discovery - path: skills/security/discovery/attack-surface-mapping/SKILL.md + path: attack-surface-mapping/SKILL.md related: [threat-modeling, api-security] - name: security-architecture-review domain: discovery - path: skills/security/discovery/security-architecture-review/SKILL.md + path: security-architecture-review/SKILL.md related: [threat-modeling, authentication-analysis, authorization-analysis] # Domain skills — identity (5) - name: authentication-analysis domain: identity - path: skills/security/identity/authentication-analysis/SKILL.md + path: authentication-analysis/SKILL.md related: [authorization-analysis, session-security, jwt-security, oauth-security] - name: authorization-analysis domain: identity - path: skills/security/identity/authorization-analysis/SKILL.md + path: authorization-analysis/SKILL.md related: [authentication-analysis, api-security, session-security] - name: session-security domain: identity - path: skills/security/identity/session-security/SKILL.md + path: session-security/SKILL.md related: [authentication-analysis, jwt-security] - name: jwt-security domain: identity - path: skills/security/identity/jwt-security/SKILL.md + path: jwt-security/SKILL.md related: [authentication-analysis, oauth-security, session-security] - name: oauth-security domain: identity - path: skills/security/identity/oauth-security/SKILL.md + path: oauth-security/SKILL.md related: [authentication-analysis, jwt-security] # Domain skills — application (12) - name: api-security domain: application-security - path: skills/security/application/api-security/SKILL.md + path: api-security/SKILL.md related: [authorization-analysis, graphql-security, websocket-security] - name: sql-injection domain: application-security - path: skills/security/application/sql-injection/SKILL.md + path: sql-injection/SKILL.md related: [api-security, command-injection] - name: xss-analysis domain: application-security - path: skills/security/application/xss-analysis/SKILL.md + path: xss-analysis/SKILL.md related: [api-security, ssti-analysis] - name: ssrf-analysis domain: application-security - path: skills/security/application/ssrf-analysis/SKILL.md + path: ssrf-analysis/SKILL.md related: [cloud-security, api-security, secrets-detection] - name: ssti-analysis domain: application-security - path: skills/security/application/ssti-analysis/SKILL.md + path: ssti-analysis/SKILL.md related: [xss-analysis, command-injection] - name: command-injection domain: application-security - path: skills/security/application/command-injection/SKILL.md + path: command-injection/SKILL.md related: [sql-injection, ai-agent-security] - name: path-traversal domain: application-security - path: skills/security/application/path-traversal/SKILL.md + path: path-traversal/SKILL.md related: [file-upload-security] - name: file-upload-security domain: application-security - path: skills/security/application/file-upload-security/SKILL.md + path: file-upload-security/SKILL.md related: [path-traversal, xss-analysis] - name: deserialization-security domain: application-security - path: skills/security/application/deserialization-security/SKILL.md + path: deserialization-security/SKILL.md related: [command-injection, prototype-pollution] - name: prototype-pollution domain: application-security - path: skills/security/application/prototype-pollution/SKILL.md + path: prototype-pollution/SKILL.md related: [deserialization-security, xss-analysis] - name: graphql-security domain: application-security - path: skills/security/application/graphql-security/SKILL.md + path: graphql-security/SKILL.md related: [api-security, authorization-analysis] - name: websocket-security domain: application-security - path: skills/security/application/websocket-security/SKILL.md + path: websocket-security/SKILL.md related: [api-security, authentication-analysis] # Domain skills — infrastructure (4) - name: secrets-detection domain: infrastructure - path: skills/security/infrastructure/secrets-detection/SKILL.md + path: secrets-detection/SKILL.md related: [supply-chain-security, cloud-security] - name: cloud-security domain: infrastructure - path: skills/security/infrastructure/cloud-security/SKILL.md + path: cloud-security/SKILL.md related: [ssrf-analysis, configuration-security, secrets-detection] - name: configuration-security domain: infrastructure - path: skills/security/infrastructure/configuration-security/SKILL.md + path: configuration-security/SKILL.md related: [cloud-security, secrets-detection] - name: supply-chain-security domain: infrastructure - path: skills/security/infrastructure/supply-chain-security/SKILL.md + path: supply-chain-security/SKILL.md related: [secrets-detection, mcp-security] # Domain skills — ai (4) - name: ai-application-security domain: ai-security - path: skills/security/ai/ai-application-security/SKILL.md + path: ai-application-security/SKILL.md related: [prompt-injection, ai-agent-security, mcp-security] - name: prompt-injection domain: ai-security - path: skills/security/ai/prompt-injection/SKILL.md + path: prompt-injection/SKILL.md related: [ai-agent-security, mcp-security, ai-application-security] - name: ai-agent-security domain: ai-security - path: skills/security/ai/ai-agent-security/SKILL.md + path: ai-agent-security/SKILL.md related: [prompt-injection, mcp-security, command-injection] - name: mcp-security domain: ai-security - path: skills/security/ai/mcp-security/SKILL.md + path: mcp-security/SKILL.md related: [ai-agent-security, supply-chain-security, prompt-injection] # Domain skills — operations (2) - name: security-triage domain: operations - path: skills/security/operations/security-triage/SKILL.md + path: security-triage/SKILL.md related: [security-remediation, axguard-triage] - name: security-remediation domain: operations - path: skills/security/operations/security-remediation/SKILL.md + path: security-remediation/SKILL.md related: [security-triage, axguard-remediate] diff --git a/skills/security/application/sql-injection/SKILL.md b/sql-injection/SKILL.md similarity index 100% rename from skills/security/application/sql-injection/SKILL.md rename to sql-injection/SKILL.md diff --git a/skills/security/application/ssrf-analysis/SKILL.md b/ssrf-analysis/SKILL.md similarity index 100% rename from skills/security/application/ssrf-analysis/SKILL.md rename to ssrf-analysis/SKILL.md diff --git a/skills/security/application/ssti-analysis/SKILL.md b/ssti-analysis/SKILL.md similarity index 100% rename from skills/security/application/ssti-analysis/SKILL.md rename to ssti-analysis/SKILL.md diff --git a/skills/security/infrastructure/supply-chain-security/SKILL.md b/supply-chain-security/SKILL.md similarity index 100% rename from skills/security/infrastructure/supply-chain-security/SKILL.md rename to supply-chain-security/SKILL.md diff --git a/tests/test_mcp_skill.py b/tests/test_mcp_skill.py index bbcba17..aeacc02 100644 --- a/tests/test_mcp_skill.py +++ b/tests/test_mcp_skill.py @@ -1,4 +1,4 @@ -"""Contract tests for skills/axguard-security (Agent Skill over MCP). +"""Contract tests for axguard-security (Agent Skill over MCP). The Skill teaches when/which MCP tool to call — it must not embed a second scanner. """ @@ -10,7 +10,7 @@ import pytest ROOT = Path(__file__).resolve().parents[1] -SKILL = ROOT / "skills" / "axguard-security" / "SKILL.md" +SKILL = ROOT / "axguard-security" / "SKILL.md" _SCANNER_ALGORITHM_MARKERS = ( "def run_scan", diff --git a/tests/test_skills.py b/tests/test_skills.py index 90077b3..1e63ad3 100644 --- a/tests/test_skills.py +++ b/tests/test_skills.py @@ -21,12 +21,14 @@ def test_validate_skills_script_ok(): def test_core_skill_count(): - skills = list((ROOT / "skills" / "security").rglob("SKILL.md")) + """Skills are top-level directories; domain skills are the non-axguard-* ones.""" + skills = [p for p in ROOT.glob("*/SKILL.md") if not p.parent.name.startswith("axguard-")] assert len(skills) >= 30 -def test_index_lists_thirty_domain_skills(): - text = (ROOT / "skills" / "index.yaml").read_text(encoding="utf-8") - # Count domain skill path entries under skills/security/ - n = text.count("path: skills/security/") - assert n == 30 +def test_index_lists_every_skill_on_disk(): + text = (ROOT / "skills-index.yaml").read_text(encoding="utf-8") + on_disk = sorted(p.parent.name for p in ROOT.glob("*/SKILL.md")) + assert len(on_disk) == 38 + for name in on_disk: + assert f"path: {name}/SKILL.md" in text, f"{name} missing from skills-index.yaml" diff --git a/skills/security/discovery/threat-modeling/SKILL.md b/threat-modeling/SKILL.md similarity index 100% rename from skills/security/discovery/threat-modeling/SKILL.md rename to threat-modeling/SKILL.md diff --git a/uninstall.sh b/uninstall.sh index a93b969..8c3e51d 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -7,25 +7,17 @@ AGENT="${AXGUARD_AGENT:-claude}" SCOPE="global" ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SKILLS=( - axguard-audit axguard-preship axguard-cso axguard-triage axguard-remediate axguard-report axguard-knowledge - threat-modeling attack-surface-mapping security-architecture-review - authentication-analysis authorization-analysis session-security jwt-security oauth-security - api-security sql-injection xss-analysis ssrf-analysis ssti-analysis command-injection - path-traversal file-upload-security deserialization-security prototype-pollution - graphql-security websocket-security - secrets-detection cloud-security configuration-security supply-chain-security - ai-application-security prompt-injection ai-agent-security mcp-security - security-triage security-remediation -) -COMMANDS=( - axguard-audit.md axguard-scan.md axguard-surface.md axguard-flow.md axguard-verify.md axguard-adversary.md axguard-evidence.md axguard-paths.md axguard-data.md axguard-secrets.md axguard-auth.md - axguard-inject.md axguard-ssrf.md axguard-xss.md axguard-cloud.md - axguard-agent.md axguard-sql.md axguard-ssti.md axguard-path.md - axguard-crypto.md axguard-supply.md axguard-graphql.md axguard-upload.md - axguard-debug.md axguard-threat-model.md axguard-triage.md axguard-fix.md - axguard-report.md axguard-ci.md -) +# Derived from the repo so these lists can never drift from what install.sh ships. +SKILLS=() +while IFS= read -r skill_md; do + SKILLS+=("$(basename "$(dirname "$skill_md")")") +done < <(find "$ROOT" -mindepth 2 -maxdepth 2 -type f -name SKILL.md 2>/dev/null | sort) + +COMMANDS=() +for cmd in "$ROOT"/commands/*.md; do + [ -f "$cmd" ] || continue + COMMANDS+=("$(basename "$cmd")") +done while [ "$#" -gt 0 ]; do case "$1" in diff --git a/skills/security/application/websocket-security/SKILL.md b/websocket-security/SKILL.md similarity index 100% rename from skills/security/application/websocket-security/SKILL.md rename to websocket-security/SKILL.md diff --git a/skills/security/application/xss-analysis/SKILL.md b/xss-analysis/SKILL.md similarity index 100% rename from skills/security/application/xss-analysis/SKILL.md rename to xss-analysis/SKILL.md