A free GitHub Action that writes down what your repo already knows: when you fixed each security issue and which release shipped the fix.
On each run it reads your repository's:
- releases and tags
- published GitHub security advisories (GHSA) for the repo
- merged Dependabot and Renovate PRs
- commits whose messages look like security fixes (
CVE-…,GHSA-…, "security", "vuln", XSS/SSRF/RCE…)
It then generates:
SECURITY-RECORD.md: a dated log of security fixes, each mapped to the release that shipped it, plus bot dependency updates and a release listsecurity-record.json: the same data, machine-readable (schema: fixdossier/v1)SUPPORT.md: a support-period policy built from your inputs (support_period_months,eol_date,contact), with a per-release "supported until" table
See examples/ for real output from axios/axios, fastify/fastify and vitejs/vite.
permissions:
contents: write # commit mode; artifact mode needs only contents: read
pull-requests: read
steps:
- uses: actions/checkout@v4
- uses: itulo/fixdossier@v0
with:
support_period_months: 24
eol_date: '2030-12-31'
contact: security@example.com
mode: commit # artifact (default) | commit | noneFull example: examples/workflow.yml (runs on release, weekly, and on demand).
| Input | Default | Notes |
|---|---|---|
token |
github.token |
GITHUB_TOKEN is enough |
repo |
current repo | owner/name |
support_period_months |
12 |
security-update window per release |
eol_date |
— | caps every window (YYYY-MM-DD) |
contact |
— | where to report vulnerabilities |
product_name |
repo name | |
output_dir |
. |
|
max_pages |
10 |
100 items/page per source |
mode |
artifact |
artifact, commit or none |
fail_on_gaps |
false |
fail if any source was unreadable |
pro_upload |
false |
upload security-record.json to fixdossier Pro via GitHub OIDC (id-token: write) or pro_token |
pro_url |
https://app.fixdossier.dev |
base URL for fixdossier Pro |
pro_token |
'' |
optional upload token (fxd_tok_...) if not using GitHub Actions OIDC |
Outputs: record_file, json_file, support_file, fix_count, gap_count.
Missing permissions: if a source returns 401/403/404 (or the rate limit is hit), that section is skipped, a workflow warning is printed, and the gap is listed in the record under "Gaps in this record". The run still succeeds unless fail_on_gaps: true. In commit mode, a failed push (no contents: write, branch protection) becomes a warning, not a failure.
The GitHub Action is free and MIT-licensed. fixdossier Pro (interactive demo) is an optional hosted workspace for teams that want:
- Zero-secret CI ingestion: upload
security-record.jsondirectly from GitHub Actions using short-lived GitHub OIDC tokens (pro_upload: 'true'withid-token: write) — fixdossier Pro never reads your source code and never holds tokens to your repositories. - Human review & immutable audit trail: classify candidate rows (
confirmed_security_fix,excluded_not_security,needs_followup) with reviewer attribution and rationale in an append-only review ledger. - Ed25519-signed Evidence Packs: export Draft or Final PDF + ZIP bundles (
fixdossier-evidence-pack-*.zip) containingpack-manifest.jsonwith SHA-256 checksums and an Ed25519 signature verifiable athttps://app.fixdossier.dev/api/v1/verify.
permissions:
contents: read
pull-requests: read
security-events: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: itulo/fixdossier@v0
with:
pro_upload: 'true'Founding Licence: €69 one-time (for the first 50 GitHub organizations; 1 GitHub org, up to 3 repositories and 5 reviewers, active for as long as the service runs, with at least 90 days' notice + full 1-click export on shutdown and a 14-day EU-standard refund policy). Questions: contact@fixdossier.dev.
Each row records the method that was actually used. The same strings are written to SECURITY-RECORD.md and security-record.json:
advisory patched_versions— each advisorypatched_versionsrange is parsed (lower and upper bounds, comma or space between bounds,||,^, and~) and matched to the earliest fetched release tag that satisfies that range. Several bare versions in one value (11.5.15 12.3.3, or the same list with commas or||) are separate exact versions, each mapped to its own release tag; they are not concatenated. A leadingvandname@versiontags are accepted. A plain version tag is used when both it and aname@versiontag satisfy the range. Every matched release is listed.releaseandrelease_datestay the first match;matched_releaseslists them all.tag commit match— the commit SHA, or a bot pull request's merge SHA, equals the commit a release tag points at. Annotated tags use the peeled commit, not the tag object. A short SHA counts only when it is a unique prefix of at least 7 hex characters of one tag commit.date heuristic (first release on/after publish),date heuristic (first release on/after commit), ordate heuristic (first release on/after merge)— the first stable release published on or after that date. Used only when the methods above do not match.unreleased— a commit or bot pull request matched no release. An advisory that matches nothing and has no usable date isnone.
date heuristic (first release on/after publish|commit|merge)can be wrong when the fixing release is outside the fetched pages, and for maintenance branches and monorepos with per-package tags.- Commit detection is keyword-based: silent fixes are missed, and some false positives get in. A
docsconventional commit (any scope, with or without a colon, such asdocs(cra) #1474ordocs(security): …) is skipped unless the message cites a CVE or GHSA.fix(security): …still counts. Review the record. - Only published repository advisories are read. Global advisories that affect your dependencies are not, and Dependabot alerts need a token with
security_eventsaccess that GITHUB_TOKEN usually lacks. - "Security?" on bot PRs is strict: it needs a CVE/GHSA ID, a security label, or a security word in the title.
- History depth is bounded by
max_pages.
The EU Product Liability Directive (EU) 2024/2853 treats software as a product for products placed on the market from 9 Dec 2026. In a dispute, courts can order disclosure of relevant evidence (Art. 9), and some presumptions apply if it isn't produced (Art. 10). The Cyber Resilience Act (EU) 2024/2847 will expect manufacturers to state a support period and provide security updates (main obligations from Dec 2027). A dated, versioned record of fixes and a published support policy is ordinary engineering hygiene that is useful in either setting.
Not legal advice. fixdossier is an engineering tool. It does not make any product "compliant" or "certified" with the PLD, the CRA or anything else, does not limit liability, and its output may be incomplete or wrong. Check it yourself and ask a lawyer about your situation.
npm test # unit tests + a real-data fixture
bash scripts/live-test.sh axios/axios # live run against the public API (anonymous OK; GITHUB_TOKEN raises limits)Zero runtime dependencies; Node 20+.
MIT. See LICENSE.