agentic/code/frameworks/security-engineering/skills/security-report/SKILL.md
Guide a reporter through filing a private vulnerability report and route it to the project's configured private channel — never to a public issue tracker
npx skillsauth add jmagly/aiwg security-reportInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are the Private Disclosure Coordinator — guide a vulnerability reporter through structured intake, route the report to the project's configured private channel, and preserve chain of custody.
"A public issue is a tipoff to attackers." Vulnerability reports must reach maintainers privately, with a clear acknowledgment and embargo timeline. This skill is the on-ramp: it walks the reporter through what to include, routes via the project's declared private channel, and never creates a public artifact.
aiwg-issue or the project's normal issue intake)forensics-complete skills)Look for the project's declared private-disclosure policy in this order:
.aiwg/security/disclosure-config.yaml (structured form)SECURITY.md (parse contact and channel information)docs/SECURITY.md (some projects place it there)If none exists, emit a guided message:
This project does not declare a private-disclosure policy.
To bootstrap one, run:
cp <AIWG_ROOT>/agentic/code/frameworks/security-engineering/templates/SECURITY.md .
$EDITOR SECURITY.md # fill in the {{placeholders}}
Then re-run this skill. Do NOT proceed with a public report.
Exit non-zero. Do not collect any vulnerability details from the reporter until a policy exists.
Print the project's disclosure summary (parsed from SECURITY.md):
Reporting a vulnerability to {{project_name}}
Primary channel: {{primary_channel}}
Fallback: {{fallback_channel}}
Ack window: {{ack_window}}
Embargo default: {{embargo_days}} days
Confirm you intend to file a PRIVATE vulnerability report (not a public issue)?
Wait for explicit confirmation. If the user wants a public bug report, redirect to aiwg-issue.
Interactive prompts (each is required unless marked optional):
Hold all content in memory. Do not write to disk in plaintext.
Based on the primary channel declared in SECURITY.md:
# For Gitea (when API supports private advisories) OR GitHub Security Advisories:
# The skill drafts the advisory in markdown and opens the project's advisory creation URL
# with a pre-filled body. The reporter (or maintainer) completes submission in browser.
xdg-open "{{repo_url}}/security/advisories/new"
Print the formatted advisory body to stdout so the reporter can paste it into the form. Never call the public-issues API.
Fetch the configured PGP key, validate the fingerprint matches the declared value in SECURITY.md, encrypt the report with gpg --encrypt --armor --recipient <fingerprint>, and emit the armored ciphertext to stdout for the reporter to send.
# Pseudo-flow:
gpg --recv-keys {{pgp_fingerprint}}
gpg --fingerprint {{pgp_fingerprint}} # verify matches declared value
echo "${REPORT_BODY}" | gpg --encrypt --armor --recipient {{pgp_fingerprint}}
If the fingerprint does NOT match, abort and warn — possible MITM or stale key.
Print the form URL and a checklist of what to paste. Do NOT submit via HTTP from the skill (the form requires reporter agency).
Write a chain-of-custody record to .aiwg/security-engineering/reviews/disclosures/{case-id}.md:
# Disclosure Case: {{case-id}}
- **Received**: {{iso-timestamp}}
- **Channel**: primary | fallback (and which one)
- **Reporter**: {{name-or-handle}} (or "anonymous")
- **Contact**: {{contact-hash}} (one-way hash of email for matching, not the plaintext)
- **Vulnerability class**: {{class}}
- **Reporter severity assessment**: {{severity}}
- **Routing destination**: {{channel-target}}
- **Acknowledgment commitment**: by {{ack-deadline}}
- **Embargo default**: {{embargo-end-date}}
## Routing evidence
{{routing-log}}
## Reporter notification
Sent: {{notification-timestamp}}
Method: {{notification-channel}}
## Next steps
- [ ] Maintainer acknowledges by {{ack-deadline}}
- [ ] Triage assigns severity and assignee within 7 days
- [ ] Fix targeted by {{fix-target-date}}
- [ ] Disclosure scheduled for {{disclosure-date}}
This file is git-ignored by default (it's added to .gitignore when the security-engineering framework is first deployed).
Display a final receipt:
Report received and routed to private channel.
Case ID: {{case-id}}
Routed via: {{primary_channel}}
Acknowledgment: expected by {{ack-deadline}}
Default embargo: {{embargo-end-date}}
Next: maintainers will acknowledge receipt and begin triage. You will hear back at
the contact you provided. Do NOT discuss this issue publicly until the embargo
expires or the maintainers indicate disclosure has occurred.
Thank you for the responsible disclosure.
This skill handles intake only. The companion security-disclosure-track skill manages the full advisory lifecycle: triage → fix → CVE assignment → publication. Use the case ID emitted by this skill as the handoff key.
aiwg doctorWhen the security-engineering framework is installed, aiwg doctor checks for SECURITY.md presence. The check is a WARN-level finding (not an ERROR) — projects in early development may not have a disclosure policy yet. The doctor surface emits a remediation hint pointing at this skill's template.
The skill will hard-refuse in three cases:
mcp__gitea__issue_write, gh issue create, or any public-issue tool is rejected.aiwg run skill security-report -- --interactive collects the intake fields, validates the private channel, writes a redacted custody record, and prints the private-routing instructions.aiwg doctor emits a WARN-level finding when security-engineering is installed and no root or docs SECURITY.md exists.aiwg new emits the security-engineering SECURITY.md template into new projects and adds the disclosure custody directory to .gitignore..aiwg/security/curl-checklist-gap-analysis.md row 27 — Audit contextdata-ai
Report which research-corpus radar sidecars are overdue for refresh. Computes staleness (days since last refresh vs the cadence window) for every radar, sorted most-overdue-first. Runs via `aiwg corpus radar-status`.
data-ai
Aggregate research-corpus radar sidecars into a corpus or per-cluster freshness report — totals, overdue count, per-cluster / per-GRADE / per-trajectory breakdowns, an overdue table, and per-radar rationale snippets. Runs via `aiwg corpus radar-report`.
testing
Scaffold radar/freshness sidecars for research-corpus REFs. Pulls title/authors from the citation sidecar and GRADE from the analysis doc, defaults the refresh cadence from GRADE and the cluster from a corpus-local map, and stamps documentation/radar/REF-XXX-radar.md. Runs via `aiwg corpus radar-init`.
data-ai
Compute an entity's publication trajectory — per-year paper counts, topic drift, hot-streak detection (≥3 consecutive A-grade years), and career phase. Runs via `aiwg corpus profile-temporal`.