All stories
(story)
Devtools
Parsec
Parsec publishes a CLI that thousands of CI pipelines run unattended. A stolen publish token was revoked and the release yanked in 67 seconds.
220 engineers
(quote)
In their words
“We ship a CLI that a lot of other people’s CI runs without looking. Signal is the first thing that looked at ours.
We found out about the last token leak from a GitHub issue.”
Dara Nwosu
VP Engineering
78,615
alerts read
1
page at night
3m 38s
median time to contain
Before Signal
Parsec makes a build tool and a command-line client that other companies run in their CI without reading the changelog. Its 220 engineers have no security hire. Security belonged to whoever lost the coin toss that quarter, and for most of 2025 that was Dara Nwosu, who is the VP of Engineering and has other things to do.
The last token leak was found by a user, who opened a GitHub issue titled “is this supposed to be public?” It had been public for eleven days. Nothing had gone wrong, which was luck rather than design, and everyone at Parsec knew the difference.
The first week
Cloud, identity and git were connected in nine minutes, under the eleven-minute median, partly because there was nothing to install. For two days Signal only read. Its first report listed 14 long-lived tokens that nobody owned, one staging bucket that was public on purpose and one that was public by accident.
The more useful result came from the baseline. Signal learned that releases ship from one CI runner, on Tuesdays at 14:00 UTC, signed, in a pattern a human could draw on a napkin. Anything that publishes outside that pattern is, to put it politely, interesting. Parsec switched on the token-rotate playbook and the publish-revoke playbook, and named an on-call approver. Dara was fifth in line, deliberately.
02:41 UTC
In July, at 02:41:09 UTC, the registry audit log showed parsec-cli 6.2.1 published with the CLI publish token, from a residential proxy range, for the first time ever. It was a Sunday and no release was scheduled.
Signal diffed 6.2.1 against 6.2.0 in five seconds and found a postinstall script that fetched a remote file. The verdict came at 02:41:31, confidence 0.97, and the on-call engineer was paged at 02:41:33. She approved at 02:42:02 from her phone, in bed, glasses off. The token was revoked, 6.2.1 was yanked from the registry and a fresh token landed in the CI secrets store at 02:42:16. Contained, 67 seconds after the first event.
There were three downloads of 6.2.1 in that window. All three came from the attacker’s own address, apparently checking their work.
What changed
In the quarter Signal read 78,615 alerts and woke one person, once. The median time to contain, across everything that needed containing, is 3 minutes 38 seconds. The 14 orphaned tokens now rotate on a schedule, and the public bucket that was public on purpose has a comment saying so, which is more than it had before.
The publish token is no longer something anyone has to remember to worry about. Dara had a recurring calendar item called “check the tokens”. It is deleted.
What’s next
Parsec is moving to Growth for custom approval chains, so that a release outside the Tuesday window needs two named approvers rather than one. It is also writing up the incident, with the timestamps, for its own users. The first draft was longer than the incident.
The security hire is still open. The job description now says “review what Signal escalates”, and the applicants are noticeably less tired.