
The Florida Department of Law Enforcement arrested Florida Highway Patrol trooper Alain Fernandez on September 9, 2026. According to the FDLE investigative affidavit as reported by Police1 and WPBF 25, investigators identified at least 22 instances between 2022 and 2025 in which he accessed FCIC, NCIC, Florida's DAVID and Flock and sent driver's license photos, addresses and vehicle details over text and Snapchat — for personal reasons, parody or disparaging remarks rather than any law enforcement purpose. He is charged with three felony counts of offenses against computer users, was released on a $25,000 bond, and FHP confirmed on September 21 that he is no longer employed. He has not been convicted.
The detection is the part worth reading. Police1, citing CBS 12's copy of the affidavit, reports the FDLE investigation opened in September 2025 when Alabama police arrested a man for impersonating an officer and found text conversations with the trooper. In one, the man asked for a driver's license to be run and got back a screenshot of the NCIC result. Three years of queries surfaced because a different agency in another state worked an unrelated case.

Seven a year sits below every threshold you would set
Twenty-two lookups across 36 months is about seven a year. Set that against the case published here on September 20: a Fort Pierce officer ran one license plate through Flock 382 times in nine months, and even that surfaced only after a media tip. That piece argued for sorting query logs by per-user volume and conceded in a sentence that the sort "misses the slow cases and catches the dense ones." This is the slow case.
The two are opposite ends of one detection problem, and the property separating them is density per subject. 382 against a single plate is a spike in any aggregation you care to write. Seven a year against unrelated subjects is arithmetically indistinguishable from a trooper doing the job — a plate at a stop, a name on a call. There is no count to threshold on and no baseline exceeded.
The control is a join, not a count
What separates an authorized lookup from an unauthorized one is not how many there were. It is whether something outside the query system asked for it — and that record already exists, in the dispatch call, the case number, the traffic stop, the ticket, the order, the appointment.
So build the join. Take every access-log row that names a subject — a person, a plate, an account — and match it against that operator's event records in a window around the query time. Most rows match. The residue is the finding.
SELECT q.user_id, q.ts, q.subject
FROM record_query_log q
LEFT JOIN case_event e
ON e.user_id = q.user_id
AND e.subject = q.subject
AND e.ts BETWEEN q.ts - interval '24 hours'
AND q.ts + interval '24 hours'
WHERE e.id IS NULL
AND q.ts > now() - interval '30 days'
ORDER BY q.user_id, q.ts;
That turns "22 in three years" from a rounding error into 22 rows with nothing attached. It does not read volume at all, which is why it reaches the sparse case a count sort cannot.
The cost is specific, and it is why the join usually does not exist. Two log sources never designed to be joined need a shared subject identifier — a plate normalized the same way in both, a person keyed by something better than a name — which is a data-engineering project, not a configuration change. It produces false positives on anything justified by a call that never became a report, and someone has to read the unmatched rows monthly, sampled if the volume is large. The mandatory reason field is the cheap substitute for this join, and it fails structurally: it is validated for presence, never against anything. The same gap appears from the other side in scoping what a partner agency's login can pull.
If the full join is out of reach this quarter, run it once by hand, for the single role with the broadest lookup rights, over 30 days. One pass tells you what share of your queries has no event behind it.
The log ends where the screenshot starts
The disclosure described in the affidavit as reported was a screen capture sent over Snapchat. The access log ends at the query. Nothing after display is instrumented, and no join, threshold or audit trail reaches it. The controls past that point are how many people can display the record at all, what the screen renders by default, and what happens when it leaves.
This generalizes past police systems. A CRM, an EHR, an admin console and a support impersonation tool have the same shape: one authenticated person, one arbitrary subject, a complete log that stops at the render.
What to check this week
- List the event sources that justify a lookup — ticket, case, order, appointment, dispatch call. Without them the join has no right-hand side.
- Confirm the access log records the subject of each query, not just the login. Many record only the session.
- Run the join over 30 days for your highest-privilege lookup role and read the unmatched rows themselves, not the count of them.
- Check the subject identifier is written identically in both systems. Formatting alone will invalidate a first attempt.
- Count the people who can display the record. That number, not the audit trail, is the control over what leaves on a phone.
If the vendor running the system cannot produce the join at all, that is the finding.
North InfoSec runs AI-assisted penetration testing and security assessments, including access governance reviews of who can look up whom and what the log can and cannot show. northinfosec.com