Patch OnMission’s Postgres this week. Prisma will not do it for you
PostgreSQL 18.6 landed on August 13 with 28 security fixes. Here is the five-step check I would run on OnMission and LOMA tonight — binaries, not a schema migration.
On 13 August 2026 the PostgreSQL Global Development Group shipped 18.6, 17.11, 16.15, 15.19, and 14.24. Twenty-eight CVEs. Over a hundred bugs. Postgres 18 skipped 18.4 and 18.5 — 18.5 never shipped because of a regression — so if you are on 18.3 you jump straight to 18.6. This is not a major upgrade. You stop the engine, replace the binaries, start it again. Prisma migrate deploy does not patch the server.
The ones that matter on an HR product: logical decoding can dlopen an arbitrary file if a non-superuser holds REPLICATION (CVE-2026-6471). Several overflows in to_char, regex, pg_stat_statements, and pg_dump are in the 8.8 range. psql COPY FROM STDIN can treat leftover data lines as commands (CVE-2026-6464). EXTRACT can be turned into SQL injection through expression deparse (CVE-2026-15741). OnMission, LOMA, HelloFutsall, and Kaha Booking all sit on Postgres. I would run these steps on OnMission first, then copy the same checklist to LOMA.
Step 1: Read the version the app actually talks to
Do not trust the Docker tag on your laptop. Ask the instance behind DATABASE_URL. If staging and production differ, you have two patches, not one.
import { prisma } from "./prisma";
export const MIN_PATCH: Record<number, number> = {
14: 24,
15: 19,
16: 15,
17: 11,
18: 6,
};
export async function requirePatchedPostgres() {
const rows = await prisma.$queryRaw<
{ server_version: string }[]
>`SELECT current_setting('server_version') AS server_version`;
const version = rows[0]?.server_version ?? "";
const [major, minor] = version.split(".").map(Number);
const floor = MIN_PATCH[major];
if (floor == null || !Number.isFinite(minor) || minor < floor) {
throw new Error(`Postgres ${version} is below the 13 Aug 2026 patch`);
}
}
Step 2: Patch binaries. Do not run a Prisma migration as a substitute
Minor releases are cumulative. No dump/restore, no pg_upgrade, no Prisma schema change. RDS, Cloud SQL, and a Docker image all count as “binaries.” Pin the image to 16.15 or 18.6 — never postgres:16. Leave PostgreSQL 19 Beta 3 for a throwaway database. Production stays on a patched 16, 17, or 18.
services:
postgres:
image: postgres:16.15-alpine
environment:
POSTGRES_DB: onmission
POSTGRES_USER: onmission
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
Step 3: Revoke REPLICATION from roles that only query
CVE-2026-6471 is a missing authorization check: REPLICATION was never supposed to mean “load native code.” Prisma’s app role on OnMission should select, insert, update, delete — not replicate. If you are not running logical decoding yourself, the privilege should not exist.
SELECT rolname, rolsuper, rolreplication
FROM pg_roles
WHERE rolreplication
ORDER BY rolname;
-- App roles used by Prisma should not replicate.
REVOKE REPLICATION FROM onmission_app;
Step 4: After the restart, check GIN reltuples before you blame Prisma
A parallel GIN build bug could leave reltuples as Infinity or NaN. Autovacuum then ignores the table forever, and the assignment list looks like the same slow Prisma query I already wrote about. ANALYZE resets the counter. Do this on any OnMission or LOMA table that uses GIN — search, tags, JSON.
SELECT DISTINCT t.oid::regclass AS table_name, t.reltuples
FROM pg_class t
JOIN pg_index i ON t.oid = i.indrelid
JOIN pg_class ic ON i.indexrelid = ic.oid
WHERE t.relhasindex AND ic.relam = 2742;
-- If reltuples is NaN, Infinity, or nonsense:
-- ANALYZE public.assignments;
Step 5: Put Postgres 14 on a calendar
- Postgres 14 stops getting fixes on 12 November 2026. A minor patch today is not a plan for November.
- If OnMission or LOMA is still on 14, schedule a major upgrade after this patch, not instead of it.
- btree_gist on float/bit and ltree indexes with huge label lists may need REINDEX after the update. If you do not use those extensions, skip it.
- Call requirePatchedPostgres() from the same /health smoke you already run before AWS gets a new image.