How I advertise malicious software on Google Ads
The Google Ads Malware Paradox: A Case Study in Automated Bans
Status: Account Suspended Status: Reinstated
Update: Thanks to the visibility gained via Hacker News, Google has restored my account. Curiously, they still haven't explained what actually triggered the flag, but the issue is resolved.
The Context: What is RACE?
I developed a tool called RACE, a terminal multiplexer designed to break the constraints of the traditional uniform grid. Instead of being locked into a rigid layout, users can:
- Freely position and resize their terminals.
- Maintain a large editor alongside a compact shell.
- Organize build logs and workspaces visually using colors.
- Ensure shell sessions persist even if the application restarts (crucial for long-term development).
I also designed the accompanying website: https://race-term.com. To keep the site lightweight, I avoided Google Analytics and ad trackers, utilizing only Cloudflare Analytics for basic telemetry. The site's interactivity is handled by simple JavaScript DOM manipulations.
The Incident: The $500 "Malicious" Investment
After spending $500 on Google Ads to promote the software, Google abruptly suspended my account. The accusations were grave:
- Malicious software
- Compromised Site
"The system rejected my appeal, demanded 'new information,' and suggested I simply delete the account if I had no other options. No specifics were provided regarding what was malicious or how the site was compromised."
The "Radio Erywan" Moment
To put this in perspective, it felt like a call to Radio Erywan: "Is it true that in Moscow, on Red Square, they are giving away cars?" (A joke about the absurdity of official narratives versus reality).
The Forensic Audit
I conducted a comprehensive security review of the entire ecosystem. Here is the breakdown of the verification process:
Security Verification Matrix
| Tool/Method | Target | Result | Link/Status |
|---|---|---|---|
| Google Safe Browsing | race-term.com & DMG | ✅ Clean | Report |
| VirusTotal | Binary/DMG | ✅ Clean | Report |
| Search Console | Domain Security | ✅ No Issues | sc-domain:race-term.com |
| Code Review | JS Bundles | ✅ No Obfuscation | Manual Audit |
| Signatures | macOS App | ✅ Valid | Independently Verified |
Technical Checklist
- Verified notarization status of the macOS app.
- Analyzed raw and bundled JavaScript for injected code.
- Checked Cloudflare logs for anti-LLM or Captcha triggers.
- Tested accessibility across various User Agents.
The Hypothesis: The "Multiplexer" Misunderstanding
RACE is written in Rust. By its very nature as a terminal multiplexer, it must launch and manage background shell processes.
// Conceptual logic of a multiplexer
fn manage_session() {
let subprocess = spawn_shell_process();
// This behavior looks like "persistence" or "hidden activity"
// to an automated security scanner.
keep_alive(subprocess);
}
This subprocess management is essential functionality, not a stealth tactic. Users can even opt to use dtach as an alternative backend. I documented this clearly in the "About" section, yet the automated systems flagged it as suspicious.
The Logic of the Ban
The frustration can be modeled as a mathematical impossibility:
The Struggle and the "Catch 22"
I attempted to mitigate the perceived risk by releasing version 1.0.39, which included a (somewhat clunky) cleanup routine upon application deletion.
The Workflow of Despair:
I found myself in a classic Catch 22: I was being punished for a "crime" that Google's own scanners (Safe Browsing/Search Console) couldn't find, and I was told to provide "new information" without being told what the "old information" lacked.
Final Thoughts
The only way out was public visibility. Once the story hit Hacker News, the "magic" happened, and the account was reinstated. It serves as a stark reminder that in the era of AI-driven moderation, the only way to bypass a broken algorithm is sometimes to trigger a human response via public pressure.
Author: Przemysław Alexander Kamiński (xlii / exlee) Tech Stack: Hugo + hugo-theme-nostyleplease