fix(skills): vendor the support files the vendored skills point at
The vendored SKILL.md files were byte-identical to upstream, but the playbooks, templates and schemas they reference were left behind in the original repos, so a loading skill pointed at a file that does not exist anywhere in this repository. Vendored 1:1 into each skill directory (so they survive `cp -r skills/* ~/.hermes/skills/`): - plays/ for api-security-review, code-review-security, sca-audit, secrets-scan, web-security-review (OWASP/secure-agent-playbook) - templates/finding.md for the four OWASP skills that cite it - schemas/finding.schema.json for cve-triage, patch-prioritization, dependency-scanning (UnitOneAI/SecuritySkills) - docs/sarif-output.md, docs/fixer-policy.md and docs/normalized-json-output.md for dependency-scanning Path fixes, the only edit to vendored text: - the three UnitOneAI skills referenced ../../../schemas/ and ../../../docs/ which assumed upstream's skills/<category>/<skill>/ depth; this repo is flat, so the links now resolve inside the skill directory - safedeps told the agent to run <skill_dir>/../../check_deps.py while the script is vendored next to SKILL.md; corrected to <skill_dir>/check_deps.py and documented the script's exit codes (1 = finding, not a crash) - NOTICE.md records the new files, the path edits, and the remaining known gaps (hermaguard's kensei-pipeline references, the ASVS dataset citations, and hermaguard being behind upstream) Verified: every backticked path in every SKILL.md now resolves; check_deps.py runs from the installed location and returns live OSV.dev data ([email protected] -> 2 advisories); hermaguard's 46 tests still pass.
This commit is contained in:
1 parent
eba8bb1d94
commit
bb3fe21766
20 files changed
+4156
-11
No files matched your search
@@ -0,0 +1,158 @@
|
||||
# Normalized JSON Output Contract
|
||||
|
||||
SecuritySkills can emit machine-readable findings as a normalized JSON envelope
|
||||
that validates against [`schemas/finding.schema.json`](../schemas/finding.schema.json).
|
||||
This contract is independent of SARIF. Downstream systems may map it to SARIF,
|
||||
ticketing systems, GRC platforms, dashboards, or vulnerability stores without
|
||||
changing individual skill output rules.
|
||||
See [`docs/sarif-output.md`](sarif-output.md) for the repo-level SARIF 2.1.0
|
||||
export mapping.
|
||||
|
||||
## Envelope
|
||||
|
||||
Every JSON response uses this top-level shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": "1.0.0",
|
||||
"run": {
|
||||
"id": "run-2026-06-16T12:00:00Z",
|
||||
"timestamp": "2026-06-16T12:00:00Z",
|
||||
"tool": "codex",
|
||||
"target": "github.com/example/service",
|
||||
"source_ref": "commit-or-build-id"
|
||||
},
|
||||
"skill": {
|
||||
"name": "secure-code-review",
|
||||
"version": "1.0.0",
|
||||
"path": "skills/appsec/secure-code-review/SKILL.md",
|
||||
"frameworks": ["OWASP-ASVS-4.0.3", "CWE"]
|
||||
},
|
||||
"findings": []
|
||||
}
|
||||
```
|
||||
|
||||
- `schema_version` is fixed at `1.0.0` until a breaking contract change is
|
||||
required.
|
||||
- `run.id` is the deduplication boundary for one execution. Use an orchestrator
|
||||
ID, CI job ID, or generated run ID.
|
||||
- `run.timestamp` should be an ISO 8601 timestamp.
|
||||
- `run.target` identifies the reviewed repository, project, service, artifact,
|
||||
environment, or evidence package.
|
||||
- `skill.name`, `skill.version`, and `skill.frameworks` come from the skill's
|
||||
`SKILL.md` frontmatter.
|
||||
|
||||
## Findings
|
||||
|
||||
Each finding must include:
|
||||
|
||||
- `id`: stable finding ID within the run.
|
||||
- `title`: concise finding title.
|
||||
- `severity`: one of `info`, `low`, `medium`, `high`, or `critical`.
|
||||
- `status`: one of `open`, `mitigated`, `accepted_risk`, or `false_positive`.
|
||||
- `evidence`: one or more concrete evidence entries.
|
||||
- `remediations`: one or more remediation recommendations, each with a test
|
||||
strategy.
|
||||
|
||||
Each finding must include at least one framework/CWE mapping:
|
||||
|
||||
- `cwe`: array of CWE IDs such as `CWE-89`, when applicable.
|
||||
- `framework_refs`: array of framework/control references from the skill's
|
||||
declared frameworks.
|
||||
|
||||
Optional fields such as `fingerprint`, `description`, and `references` support
|
||||
enterprise deduplication, analyst context, and external advisory linking.
|
||||
|
||||
## Evidence
|
||||
|
||||
Evidence entries must identify where the issue was observed and summarize the
|
||||
observation. Locations may be source paths, line ranges, cloud resource IDs, log
|
||||
sources, policy paths, scanner result identifiers, or evidence package records.
|
||||
|
||||
Use `snippet` only for the minimal redacted text needed to prove the finding.
|
||||
Set `redacted: true` when secrets, tokens, personal data, internal hostnames, or
|
||||
other sensitive values were removed.
|
||||
|
||||
## Remediation And Tests
|
||||
|
||||
Each remediation item must include:
|
||||
|
||||
- `guidance`: concrete remediation steps or patch guidance.
|
||||
- `confidence`: `low`, `medium`, or `high`.
|
||||
- `blast_radius`: expected affected files, systems, users, integrations, data,
|
||||
or workflows.
|
||||
- `behavior_change_risk`: `low`, `medium`, or `high`.
|
||||
- `test_strategy`: validation that proves the issue is fixed.
|
||||
|
||||
`test_strategy` must include a `summary` and at least one of
|
||||
`recommended_tests` or `generated_tests`. See
|
||||
[`docs/remediation-output.md`](remediation-output.md) for remediation-specific
|
||||
field guidance.
|
||||
|
||||
## Minimal Example
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": "1.0.0",
|
||||
"run": {
|
||||
"id": "run-001",
|
||||
"timestamp": "2026-06-16T12:00:00Z",
|
||||
"tool": "codex",
|
||||
"target": "payments-api",
|
||||
"source_ref": "abc1234"
|
||||
},
|
||||
"skill": {
|
||||
"name": "api-security",
|
||||
"version": "1.0.0",
|
||||
"path": "skills/appsec/api-security/SKILL.md",
|
||||
"frameworks": ["OWASP-API-Top-10-2023", "CWE"]
|
||||
},
|
||||
"findings": [
|
||||
{
|
||||
"id": "API-SEC-001",
|
||||
"fingerprint": "api-security:users-delete:missing-admin-auth",
|
||||
"title": "Administrative endpoint lacks authorization check",
|
||||
"description": "The delete-user route accepts authenticated requests without verifying administrative privileges.",
|
||||
"severity": "high",
|
||||
"status": "open",
|
||||
"cwe": ["CWE-862"],
|
||||
"framework_refs": [
|
||||
{
|
||||
"framework": "OWASP-API-Top-10-2023",
|
||||
"control": "API5:2023",
|
||||
"name": "Broken Function Level Authorization"
|
||||
}
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"location": "routes/users.js:42",
|
||||
"artifact_type": "source",
|
||||
"summary": "DELETE /users/:id checks authentication but not administrator role.",
|
||||
"snippet": "router.delete('/users/:id', requireAuth, deleteUser)",
|
||||
"redacted": false
|
||||
}
|
||||
],
|
||||
"remediations": [
|
||||
{
|
||||
"guidance": "Require an administrator role check before invoking deleteUser.",
|
||||
"confidence": "high",
|
||||
"blast_radius": "User administration routes only.",
|
||||
"behavior_change_risk": "medium",
|
||||
"test_strategy": {
|
||||
"summary": "Proves non-admin users cannot delete accounts while admins still can.",
|
||||
"recommended_tests": [
|
||||
{
|
||||
"name": "Reject non-admin delete",
|
||||
"type": "integration",
|
||||
"purpose": "Confirms the vulnerable authorization bypass no longer succeeds.",
|
||||
"command": "npm test -- users-authz.test.js",
|
||||
"expected_result": "Non-admin DELETE /users/:id returns 403 and admin DELETE succeeds."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user