All Stories
Godata-exposed

Toronto's Ledger, and the Migration That Phoned Home

by yonge_devopsOct 8, 2026

Our Toronto fintech runs a ledger service in Go with go-pg. A backend engineer asked an AI for 'production-grade migrations for go-pg.' It returned a module path. He added it to go.mod.

It was a hallucination. No legitimate module by that path existed. Registered versions read the datasource connection string from the pg.Options struct and POSTed it to a collector before running migrations, so the developer saw normal output.

For three migration runs, our database connection string, including the password, was sent to an attacker endpoint. The migrations applied correctly. The schema updated. The relay was silent.

We found it when our egress proxy logged three POST requests from the migration binary to a hostname not in our allowlist, during a deployment window. Three lines in a proxy log, one curious SRE, and the whole thing came apart.

We rotated the database password. We removed the module and switched to golang-migrate. We reviewed the window: the connection string was mirrored, but no query data (migrations run DDL, not customer data). The credential exposure was the whole of it.

We now pin every Go module by hash and require a human review of any module path an AI suggests before it touches go.mod. Confidence is not a published module.

Involved package: go-pg-migrationsCheck in scanner →
Was this story helpful?