| Version | Supported | Security updates until |
|---|---|---|
| 4.x | Yes. Fixes ship in a new patch or minor release of the latest 4.x | 6 months after 5.0.0 is released |
| 3.x | No. Upgrade with docs/upgrading.md; MongoDB data stays | Ended with the release of 4.0.0, before this policy |
| < 3.0 | No. 1.0 and 1.0.1 contain known critical vulnerabilities | Ended; upgrade with docs/upgrading.md |
- Only the latest release of a major version is supported; there are no backports to older minor or patch releases. Upgrading within a major version is safe, because breaking changes only come with a new major version.
- When a new major version comes out, the previous one keeps getting security fixes for six months. The end date is added to this table and announced in the changelog and the release notes of the new major version.
- After that date the old major version gets no updates of any kind, security fixes included.
Do not open a public issue. Report privately through GitHub Security Advisories.
Please include:
- affected version or commit
- steps to reproduce, ideally a minimal request sequence
- impact as you see it
You get an answer within 7 days. Confirmed issues are fixed in a patch release and published as an advisory with credit, unless you prefer to stay anonymous. The changelog lists the fix under "Security".
In scope: code in this repository, the default configuration, the Dockerfile and the GitHub workflows.
Out of scope: applications built from the template and changed afterwards, missing hardening that docs/security.md lists as a known limit, and findings that need a compromised server or a malicious administrator.
Only test against your own installation. Do not test against systems you do not own.
Every release since 4.0.0 carries a signed build provenance, and version tags from 4.1.0 on are signed with the
release key, whose public half is in allowed_signers. GitHub shows them as verified; in a clone,
check a tag with git -c gpg.ssh.allowedSignersFile=.github/allowed_signers tag --verify v<version>. Check a
downloaded archive or the Docker image with gh attestation verify <file or oci://image> --repo VectoDE/ExpressJS-Template; see deployment.
- The repository holds no secrets. gitleaks runs in CI and GitHub secret scanning with push protection is on. Tests generate their passwords and keys at run time.
- The release workflow signs the provenance with GitHub's OIDC identity and pushes the image with the short-lived
repository token. The only stored secret is
RELEASE_SIGNING_KEY, the SSH key that signs version tags. It belongs to the GitHub environmentrelease, which onlymaincan use, so workflows on other branches never see it; one job that runs no dependency code uses it, and no person keeps a copy. SonarQube Cloud analyses through its GitHub app. - The live demo on Cloudflare has its own three keys (
JWT_SECRET,SESSION_SECRET,ENCRYPTION_KEY). They are random values that were never displayed, stored only as Worker secrets in Cloudflare, and set by the maintainer withwrangler secret put. They protect nothing but the demo, whose data is deleted every hour. - Only the maintainer can read or change secrets (see governance). They are rotated at least once
a year, at once when someone with access leaves, and whenever they may have leaked; for the signing key: create a
new key, replace the secret, the signing key on GitHub and
allowed_signers, then delete the old key. - Applications built from the template keep their secrets in environment variables;
npm run setupgenerates them and production refuses placeholders. See configuration.
npm audit, OSV-Scanner and Dependabot alerts are checked on every pull request and weekly. A vulnerable
dependency is updated in a patch release. If a finding does not affect the template (for example a function it
never calls), the reasoning is written in the pull request that dismisses the alert.
The reasoning behind the security design is in the assurance case, the controls in docs/security.md. Who has access to what is listed in the governance.