Category: DSPT Evidence Checklist
Reference: Standard 9 (IT Protection) — software kept up to date with security patches
Evidence required: a patching schedule, or supplier confirmation of automatic patching, plus the run record
Platform: VeriPath estate (primary, app engine, auxiliary)
Re-verified: 2026-10-13 — supersedes the 14 May 2026 version, which listed containers that no
longer exist and predated the current automation. Re-verify quarterly (next due 2027-01).
| Host | OS | Kernel (running) | Reboot outstanding | Upgradable now | Automatic security updates |
|---|---|---|---|---|---|
| Primary (gateway / data / AI) | Ubuntu 24.04.5 LTS | 6.8.0-142-generic | yes — flagged 2026-10-09 | 28 packages | daily unattended-upgrades, last run 2026-10-13 06:45 |
| App engine (booking apps) | Ubuntu 26.04 LTS | 7.0.0-29-generic | yes — flagged 2026-10-07 | 44 packages | daily unattended-upgrades; monthly run added 2026-10-13 |
| Auxiliary (ERPNext) | Ubuntu 26.04 LTS | 7.0.0-15-generic | yes | 55 packages | daily unattended-upgrades (enabled, active); monthly run added 2026-10-13 |
| Cadence | Job | Host | What it does |
|---|---|---|---|
| Monthly, 1st 02:00 | patch_monthly.sh --apply --reboot |
Primary | OS updates, Trivy, DefectDojo push, reboot if required; logs /var/log/patching/ |
| Monthly, 1st 03:00 | patch-host.sh --apply --reboot |
App engine | OS updates, reboot if required; same summary format, staggered from the primary |
| Monthly, 1st 04:30 | patch-host.sh --apply --reboot |
Auxiliary | as above, third slot (one unit file, per-host drop-in) |
| Daily | unattended-upgrades |
Primary, App engine, Auxiliary | security-repository patches |
| Weekly, Sat 03:00 / Sun 03:00 | scan_trivy.sh, scan_trivy_weekly.sh |
Primary | container image scans → DefectDojo |
| Weekly, Sun 03:30 | scan_nmap.sh |
Primary | host and Docker-network enumeration |
| First Sunday 04:00 | scan_zap.sh |
Primary | DAST against the GP booking portal |
| Weekly, Sun 06:30 | lynis audit system |
Primary | host hardening audit |
| Quarterly, first Sat of Jan/Apr/Jul/Oct 03:30 | refresh-image.sh <compose-dir> <service> |
All stacks | deliberate per-stack image refresh, driven by the Trivy result |
Where the record lives (changed 2026-10-13): every run above reports itself into the application —
https://gp.veripath.co.uk/infrastructure/maintenance/ — with filters, a status strip, a CSV export and a
staff-only manual-entry form. The app is the live record; the
Patching Log keeps the cadence, the pre-2026-10-13 history and the summary.
All job definitions are version-controlled in veripath-ops.
From /var/log/patching/summary.log on the primary (full detail in
Patching Log):
| Run | Applied | Outstanding after | Reboot |
|---|---|---|---|
| 2026-05-25 (manual) | 2 | 0 | none |
| 2026-06-01 | 3 | 4 | scheduled |
| 2026-07-01 | 17 | 5 | scheduled |
| 2026-08-01 | 15 | 1 | scheduled |
| 2026-09-01 | 101 | 5 | scheduled |
| 2026-10-01 | 43 | 12 | scheduled |
Five consecutive monthly runs with a dated log is the evidence that the cadence is real rather than
declared. The app engine's log was created on 2026-10-13 and its first scheduled run is 2026-11-01; a
one-off bootstrap on 2026-10-14 clears the reboot it had been owed since 2026-10-07.
Images are pinned by digest, and watchtower remains retired (it auto-updated latest tags without
review), so nothing updates itself. Refreshes are now a scheduled, deliberate action (see §1.2) rather
than an ad-hoc one. Oldest images in use on the primary, by build date:
| Image | Built | Note |
|---|---|---|
minio |
2025-09-07 | >12 months — the first quarterly refresh's main target |
wikijs |
2026-05-01 | ~5 months |
keycloak |
2026-05-07 | ~5 months |
aes-service-* (4 containers) |
2026-05-18 / 2026-05-27 | ~5 months |
postgres:15-alpine (forgejo / defectdojo / client) |
2026-07-07 | shared base |
forgejo 16.0.2, livekit, defectdojo |
2026-07-30 → 2026-08-03 | ~2–3 months |
netdata, roundcube |
2026-08-08 / 2026-08-03 | ~2 months |
/var/log/patching, no remote-host step inpatch_monthly.sh. Now patch-host.sh + patch-monthly.timer (1st 03:00, Persistent=true, inveripath-ops), with the first run on 2026-11-01 and a one-off bootstrap on 2026-10-14 to clear therefresh-image.sh, driven by the weekly Trivy result, rollback bymanage.py migrate_client runs only from theentrypoint.sh at container start, so a client-tier schema change ships when that/var/log/patching; unattended-upgrades enabled and active. Recommendation:patch-host.sh is already parameterised.patch-host.sh with its own timer,restart=unless-stopped. Its 55 outstanding packages and pending reboot are cleared by that run, orImmediate: let the 2026-10-14 bootstrap clear the app-engine reboot; the auxiliary host's equivalent
run is in flight as a work order (gap 4).
Short term: run the first quarterly image refresh as scheduled (2027-01-02) with minio first, and
record each refresh in the Patching Log's image table.
Ongoing: monthly runs recorded in the patching log from both hosts; this assessment re-verified
quarterly (next 2027-01); the patching policy reviewed annually — see
Standard 9b: Patching & Software Updates.
| Claim | Where the evidence is |
|---|---|
| A schedule exists and is met | the app's maintenance view (/infrastructure/maintenance/, filterable + CSV export), fed automatically by the jobs in §1.2; §1.3 and the Patching Log hold the cadence and pre-2026-10-13 history |
| Job definitions are controlled | veripath-ops — scripts/patch-host.sh, scripts/refresh-image.sh, systemd/patch-monthly.{service,timer} |
| Automatic daily security patching | /etc/apt/apt.conf.d/20auto-upgrades on each host; apt-daily-upgrade.timer active |
| Reboots are applied | the monthly runs' reboot step; outstanding reboots are listed as open items rather than omitted |
| Vulnerabilities are found and tracked | weekly Trivy / nmap / Lynis, monthly ZAP, reporting to DefectDojo (security.veripath.co.uk/dojo/) |
| Image updates are controlled | pinned digests, scheduled quarterly refresh, digest-pin rollback — not an auto-updater |