Skip to content

feat(hub,skills): pre-publish security audit gate for marketplace skills (code + body, tier-gated verdict) #2468

Description

@kovtcharov-amd

This issue adds an automatic safety check that every skill must pass before it can be published to the hub. A skill can contain both written instructions and runnable code that get loaded straight into an agent, so an unchecked skill is a genuine security risk — a competing platform was once flooded with over a thousand malicious skills. The check scans both the code and the text of a skill, returns a clear pass / needs-review / blocked result, and decides how trusted the skill is allowed to be.

Why this matters

Before: The skills marketplace (#2467) lets anyone publish a SKILL.mdtools.py/scripts) that other users install and load straight into an agent's context and tool registry. Nothing inspects a skill for malicious code, permission over-reach, or prompt-injection before it reaches users. A competing hub was flooded with 1,184 malicious skills (see #647) — an open, unaudited publish path is the single biggest risk in the whole skills feature.

After: Every skill published to the hub passes an automated security audit gate that inspects both its code and its instruction body, emits a machine-readable ALLOW / REVIEW / BLOCK verdict, and gates publication + the security tier it may claim. Trusted-from-day-one is what differentiates the GAIA marketplace, and this is the mechanism that delivers it.

This also resolves the body-injection scanning open question already flagged in both docs/spec/agent-skills and docs/plans/skill-format.

Approach — reuse what exists

  • Mirror the existing .github/workflows/claude-security-audit.yml pattern for the CI/LLM-assisted analysis stage.
  • Emit findings as the governance GovernanceDecision shape (DecisionType = ALLOW | REVIEW | BLOCK, src/gaia/governance/schemas.py:17) so verdicts are consistent with the rest of GAIA.
  • Hook the gate into the marketplace publish path (workers/agent-hub/src/publish.ts, Hub Worker: per-type publish + validation + R2 storage namespace #1718) so no skill enters the catalog un-audited, and expose the same engine as gaia skill audit ./skill/ so authors can self-check before publishing.

Scope

A. Audit engine (gaia skill audit)

Two analyzers over a skill directory, keyed to the two skill flavors:

  • Code analysis (tool skills — tools.py, scripts/):
    • Dangerous-call detection: subprocess/shell, eval/exec, dynamic import, raw sockets/exfil, filesystem writes outside declared scope, environment/credential access.
    • Permission-truth check: does the code touch domains (network, shell, filesystem, env, …) it did not declare in metadata.gaia.permissions? A declared-vs-actual mismatch is a hard finding.
    • Supply-chain: flag undeclared or pinned-to-risky dependencies / node_dependencies.
  • Instruction analysis (all skills — the Markdown body):
    • Prompt-injection / jailbreak pattern scan (the body is injected into model context and is untrusted input). Resolves the specs' body-injection open question.

B. Verdict + tier gating

  • Output a GovernanceDecision-shaped report: ALLOW (publish proceeds), REVIEW (quarantined pending maintainer sign-off), BLOCK (publish rejected with an actionable findings report naming file/line and the fix).
  • Tier-scaled rigor, per Skill marketplace: format spec, security tiers, and AMD Verified seeding #647 tiers:
    • experimental — scan is advisory (findings surfaced, install still requires --allow-experimental).
    • community — automated scan required to pass + publisher signature; dangerous findings force REVIEW.
    • verified — scan required plus the human/AMD audit hook (this issue provides the automated gate the human step builds on, not the audit policy itself).
  • A skill cannot be stamped a tier whose gate it did not clear.

C. Publish workflow integration

D. Reporting

  • Structured findings artifact (severity, category, file:line, remediation) attached to the publish/PR.
  • Security findings handled per repo policy (private channel for exploitable details, not a public dump) — consistent with the weekly-audit pattern.

Dependencies

Non-goals

  • Not the AMD-Verified audit policy/process (program/governance decision) — this delivers the automated gate + verdict that the human tier consumes.
  • Not a general repository security audit (that is claude-security-audit.yml / claude-weekly-audit.yml); this is skill-artifact-scoped.
  • No sandboxed runtime execution enforcement here — that is the Phase 2 permission sandbox; this is a pre-publish, static gate.

Acceptance criteria

  • gaia skill audit ./skill/ runs code + instruction analyzers and prints an ALLOW/REVIEW/BLOCK verdict with file:line findings.
  • A skill whose tools.py uses a domain not in its declared permissions is flagged (declared-vs-actual mismatch).
  • A skill body containing known prompt-injection patterns is flagged.
  • Publish is gated: BLOCK rejects, REVIEW quarantines, ALLOW writes the catalog entry with the recorded verdict + tier; a skill cannot claim a tier it did not clear.
  • CI workflow runs the audit on skill-submission PRs; re-audit fires on version bump.
  • Security findings follow the repo's private-disclosure policy; specs' body-injection open question marked resolved.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions