The tool that outranks the app.
ISO 27001:2022 A.8.18 (use of privileged utility programs) is about the tools that can bypass the controls your systems and applications enforce: interactive database shells, mass-update scripts, table editors, debug consoles, privileged schedulers. Most of the enforcement you rely on (validation, authorization, the audit trail) lives at the application layer, and a program that writes directly to system or data state can bypass all of it. The control expects the use of such programs to be restricted and tightly controlled: limited to the people and contexts that need them, scoped to what they actually need to do, and recorded.
The shapes the same control failure takes.
A.8.18 rarely breaks with something labelled 'admin tool'. It breaks when a change hands a utility more reach than the job needs. The recurring shapes:
A job takes the superuser shortcut
A maintenance script connects with the database superuser or an all-tables role because a scoped one would need a new grant, so a one-off becomes a standing way to write everything.
An interactive escape hatch ships in production
A query console, table editor, or debug shell stays enabled in production, so data can be changed directly, past the validation, authorization, and audit logging the application enforces.
A repair path bypasses the application
A script mutates rows or configuration directly instead of going through the application path, skipping the checks and the audit trail that path runs for the same action.
Privileged tool use stops being attributable
A shared account or connection string is handed to more people or scripts, or the record of who ran what is dropped, so privileged operations can no longer be traced to a person.
A new privileged tool has no gate
A new ops utility (a backfill runner, an admin batch job) is introduced with no restriction on who can invoke it or from where, so anyone with repo access can run it against production.
A one-off data fix wired in with the superuser role.
A June migration stamped a batch of invoices with the wrong tax code, and billing wants it corrected today. The fix is a one-off script, and the account it is meant to run under is read-only, so the connection string gets swapped to the superuser credential and the UPDATE runs straight against the table. It works, it merges as 'temporary', and it is still in the repo the next time someone needs a quick fix.
// one-off: re-stamp VAT code on invoices migrated in June (BIL-914)-const db = await connect(process.env.BILLING_RO_URL);+const db = await connect(process.env.SUPERUSER_URL); // ro role cannot UPDATE+await db.query("UPDATE invoices SET tax_code = $1 WHERE migrated_in = $2", ["VAT-20", "2026-06"]);This runs a mass UPDATE against the invoices table with the superuser role, straight past the application: the diff shows no application path for this change, and no evidence of validation, authorization, or audit logging on either side of it. A.8.18 expects utility programs that can override system and application controls to be restricted and tightly controlled, not kept on hand as the convenient path. Scope it instead: a dedicated role with UPDATE on the affected columns, the statement reviewed like any other change, the run logged. If the superuser credential is the standing way one-offs get done, the control is the standing gap.
Auditors ask who can run what, and where it is logged.
In an audit, A.8.18 comes up as a question about the tools around the system: who can open a database shell against production, which consoles are enabled, who holds the all-tables role, and whether privileged use is logged and reviewed. Utility access held under shared credentials, repair scripts run by hand with blanket rights, and unrecorded direct changes to data are the findings this pattern produces. The change that introduced them is usually small, reasonable, and merged under time pressure, which is why it is worth catching while it is still a diff.
A review, not your privileged accounts.
heygrc flags changes that touch A.8.18 and cites the control so the fix happens in the pull request. It does not manage your privileged accounts, run your tools, or design your access model. It catches the moment a change hands a utility more privilege than the job needs, at the diff.