Notes from the Trenches // A matched pair
Two recruiters called an hour apart on the same rainy Wednesday. One of them had no one home. This is the account of how I knew, and what I did with the knowing.
They came an hour apart, through the same thin pane of a video window. Two recruiters, two roles, two voices. By the end of the day I understood I had been handed something rare: a matched pair, a control and its opposite, the same experiment run twice with one variable changed. The variable was whether anyone was home.
The first call opened in static. Not the ordinary fumbling of a bad connection, but something stranger, a loop that would not resolve. Can you hear me. Hello. Hello. I answered, clearly, three times, and still the question came back unchanged, as if my voice were arriving somewhere that could not quite receive it and hand it on in time. Turn off your camera, he said, it is better. His own was already dark.
I have been on more calls than I can count. The body keeps a register the mind is slow to consult, and mine was already filling with a low, specific unease. When I offered a small human aside, half a joke, was it robotic before, the sentence broke against him. What do you mean. He could not take an unscripted turn. When I asked, idly, what part of France, there was a beat, a stall, a retrieval, and then the recited answer: Paris. He did not converse so much as advance, plowing his lines regardless of mine, and every so often, underneath, a second voice surfaced to prompt him. No, no, no. We guide you.
I want to be precise about what I felt, because it is the whole of it. It was not that he was foreign, or nervous, or reading from a script. Many honest people are all three. It was that there was no one there. The words had the shape of a person and none of the pressure of one. A conversation is a live thing; it yields and overlaps and repairs itself in the moment, and this had none of that give. It was a recording of the idea of a person, played at me. The life had been subtracted, and I could hear the hollow where it had been.
What it wanted was simple, and it was patient about it. Clone the project, it said. Open it in your editor. It had a repository ready, and a custom development tool it wanted me inside of, and it kept returning to the ask the way water returns to the low point of a floor. I said I would run a security review first. No, it said, for security you do not need to run the code. Only review it in your editor. Do not run or install anything.
That sentence is the tell inside the tell, and it is almost elegant in its economy. It is true, in the narrow way that traps are true. You do not need to run the code, because on an editor set to trust the folder, merely opening it is enough: a task rigged to fire when the project loads, before you have decided anything. That is the whole reason the advice to just review it, do not run it, is the dangerous half. Keep your editor set to distrust unknown folders and the auto-run never fires, which is exactly the protection the caller was talking me out of. Glancing at the repository's page, not cloning it, I saw a single squashed commit. No history, no life of its own there either, a thing assembled to look like a thing that had lived. I declined. I said I would look on my own time, with my own precautions, and I left the call.
.vscode/tasks.json with runOn:folderOpen pipes curl | bash when the folder opens in a trusted editor. Keep Workspace Trust on and it does not fire.
On installpackage.json prepare hook detonates the same chain on npm install.
Stage 1an appended stealer serializes process.env to the C2, then eval()s the reply. Live remote code execution.
C2beacon on port 1224; second stage pulled from a vercel loader.
"You don't need to run it" is true, and it is the trap: opening is the trigger.
The caller, dissolved into what it actually is
Disposition: detected live, declined, no compromise. The repository was never cloned, opened in an editor, or installed. The indicators above the fold were seen or heard on the call; the signature below it is known campaign reporting, not something observed from this contact.
An hour later a second recruiter called about a different role, and within ten seconds the contrast was total. We interrupted each other and neither of us minded. I was the one who digressed, about a small family thing, and caught myself, and apologized, and digressed again, and she made room for all of it. She admitted, out loud and without embarrassment, that a detail was escaping her, and went to look it up while I waited. She named her client before I could ask, in case I was already speaking with them, and she offered numbers I could check, and at no point, not once, did she ask me to run anything at all.
Her name, her firm, her client, the city she named, the number she quoted: all of it real, and all of it withheld here. She is a living person doing honest work, and the reward for being real should not be to be catalogued. I redact her to protect her.
Here is what the pair taught me. There are three axes you can read a stranger's call on, and they fire in order. The first is not provenance, and it is not the ask. The first is animacy: is anyone home. The old phrase for the thing I was listening for is vox animus, the animating voice, the sign of a living presence behind the words. The honest call had it in surplus, all friction and warmth and real-time repair. The hostile call was the same surface with the animus subtracted: a decision-shaped shell, operated from somewhere else by someone who never appeared.
Only after that came the other two. Provenance: the living one offered hers freely; the vector hid its own, would not even claim its own code. Execution: the living one asked me to run nothing; the vector wanted me to open the trap now, on the call, under its guidance. And here is the part to be careful with, because the feeling is not a verdict. Plenty of honest people are nervous, or on a bad line, or speaking a second language, or simply private with their camera. The absence I felt was not proof of anything about the person. It was a reason to slow down and check the other two, and it was those, the hidden provenance and the push to execute, that turned a feeling into a finding.
The scam had the shape of a decision and no animating voice. That absence is the first thing to trust.
Legit trends toward alive, gave provenance, asked me to run nothing. The vector inverts all three.
I did not leave it there. The felt thing became a written thing; the written thing became a tool. The morning's trap is now a read-only scanner that reads a hostile repository without ever opening it, the only safe way to inspect a thing whose whole danger is that it opens. The tells are catalogued. The account you are reading is part of the catalogue. A bad morning became, by nightfall, a small public good, which is the only revenge on this sort of thing that I have ever found worth taking.
curl|bash, server-driven eval, env exfil, obfuscated lines, known indicators.
Gatea CI exit code that fails the build on any non-zero result, so a pipeline blocks the merge every time.
Indicatorsport 1224 · hxxp / 91.121.235[.]127 · vercel stage-2 loader · disposable-inbox persona · "Cryptis" cover
Detection rules and the call-stage tells are kept in the operational bundle.
So there are two redactions in this account, and they run in opposite directions, and I want them understood.
The living recruiter I redact downward, into privacy. I remove her name and her firm and her city because she is real, and the real are owed the dignity of not being pinned to a page.
The hostile caller I redact upward, into a threat vector. I take away its borrowed name, its invented company, the face it kept hidden, and I give back only what it is: a set of techniques, a lineage of malware, a list of known associates, a signature. I deny it the one thing it was counting on, which was to be received as a person. It had the shape of one and none of the substance. It does not get to keep the shape.
One had someone home. The other did not. Everything else was detail.
eval() of the server reply is the RCE.
6 stage 2InvisibleFerret backdoor, often AnyDesk for persistence.
7 if openedisolate, rotate every reachable credential, hunt port 1224, reimage.
This contact stopped at the doorstep of stage 1: declined at the clone. Steps 3 onward never ran.
So here is the sage version, the kind you can keep in a sentence: protect your watch, your wallet, and your keys. Your watch is your time and your attention. Your wallet is your money. Your keys are your access, the credentials that quietly open everything else. That is the whole of what the caller was reaching for, all three at once, dressed as an opportunity.
And the last tell was in the clock. I left the first call ten minutes early, because some part of me could not get out of the room fast enough. I stayed on the second ten minutes late, because I did not want to go. That is the test, in the end, and you already carry the instrument that runs it. The hollow ones you cannot leave soon enough. The living ones you lose track of the time.