跳到正文
DEV Community· prodbymarcu·· 4 小時前AI 評分51

20 分鐘稽核揭示 iPhone 操作裝置專案重寫的真正理由

I almost rebuilt a project for the wrong reason, a 20 minute audit caught it

AI 導讀

作者以約 20 分鐘稽核自己的 iPhone 操作裝置專案,確認程式碼乾淨,並把重寫理由由安全疑慮改為架構需求。稽核檢查 CJK 文字、所有外連、壓縮 JavaScript 前端和 ESP32 韌體字串,發現中文只在翻譯與文件中,唯一外連是指向自家區域網絡的 LLM base URL,前端請求均為同源,韌體字串則只有自家伺服器 IP 和 Espressif SDK 文件網址。

正文

I have an iPhone-driving rig. An ESP32 board plugs into the phone over USB and plays human, screen taps, button presses, the works, so my local agent can actually operate the phone instead of just talking about it. The rig works. It has worked for months. So naturally my first instinct was to rebuild the whole thing from scratch.

The reason I gave myself was security. The codebase came from a mixed-background project, there were Chinese translation files in the repo, a bundled JavaScript front end I had never actually read, and firmware binaries I had flashed without ever opening in a hex editor. In my head the story was already written: old rig is sketchy, new rig is clean, rebuild obviously justified.

Before I burned a month on it I made myself audit the old code first. Four checks, about 20 minutes total. Every single one came back clean, and the audit quietly rewrote my justification for the rebuild.

Check one, scan the repo for CJK text

I grepped the whole tree for CJK ranges across every .py, .js, .ino, .html and .md file. The rule I wanted was blunt: no Chinese anywhere in code I own and run. The scan found exactly two carriers of Chinese text, a UI translation file called i18n.js, which is translation data doing translation work, and a README.zh-CN.md, which is a translated README doing documentation work. Zero Chinese in executable paths. The thing I was going to "fix" by rebuilding did not exist.

Check two, follow every outbound call

I traced every place the old code talks to the network. There is exactly one outbound call in the entire project, one line in llm.py that hits the configured LLM base URL, and that URL is my own box on my own LAN. No telemetry, no analytics, no hardcoded third party endpoints, no phone-home beacon hiding in a helper. A project that talks to exactly one host, and it is mine.

Check three, read the bundled JavaScript like a stranger

The web front end was the part I was most suspicious of, because I had never read it and it ships minified. I ran a proper JavaScript analysis pass over static/, two files, about 23KB, and read what it actually does. Every fetch is same-origin, every request goes to /api/* on the host it came from, nothing touches IPC or any native surface. The bundle is a small local UI talking to its own server. That is the whole story.

Check four, pull the strings out of the firmware

Last one, the ESP32 firmware. I pulled printable strings from the .bin files and read them. What is in there: our own server IP, and Espressif SDK doc URLs from the vendor toolchain. Nothing else. No surprise hosts, no encoded blobs, nothing that looks like it was smuggled in past the source.

What the audit actually changed

Here is the part that matters. The audit did not tell me the old code is good. It told me the old code is clean, and those are different verdicts with different consequences.

The security story was the emotional engine of the rebuild. Clean code killed it, which forced me to write down the real reasons I want a new version, and the honest list looks completely different. I want it native, the old rig is a localhost web app plus a Python service plus a launchd helper, and I want a real Mac app. I want it fast, the old screen pipeline decodes frames in software and I want hardware decode and native rendering. I want auto-calibration, the old rig needs a manual calibration click and it should not. I want ownership, code shaped the way I would shape it, with English comments and a structure I can hold in my head.

None of those reasons say anything is broken. They all say the old rig is working software that I have outgrown. That is a rewrite for architecture, and rewrite-for-architecture makes different decisions than rewrite-for-security. It keeps the parts that already work. The USB HID layer in the old rig is exactly the shape I want, so the new build keeps it instead of redesigning it. The away-mode trick in the new architecture, board joins the phone hotspot and tunnels home over the phone's own network, gets validated before anything builds on it, because there is no security schedule forcing that bet early.

And the old rig stays running untouched while the new one gets built, which I could never justify if the old one were actually unsafe. Clean verdict bought me the luxury of not hurrying.

The rule I am keeping

The rule costs 20 minutes and it is now mandatory on me before any rewrite: audit before you rewrite, and write down what the audit found before you write down why you are rebuilding.

The failure mode it guards against is subtle. Rebuild energy feels productive, and a security justification feels noble, so the combination feels unassailable. You end up a month deep in a new codebase and you never once open the old one in anger, because the whole point was that you did not have to read it. The audit collapses that. If the code is dirty you now know exactly where, and the rebuild has a spec. If the code is clean you lose your noble reason, and good riddance, because a rebuild justified by a feeling is a rebuild that will inherit every problem the old code had plus new ones you add yourself.

Scan the text encodings you do not recognize. Trace the outbound calls and count them. Read the minified bundle like a stranger, not like its author. Pull the strings out of the firmware. Four greps and one string dump, and you will know whether you are fixing a problem or just redecorating.

My old rig was clean. I am rebuilding it anyway, for the real reasons, on the timeline a clean verdict earns. The audit did not stop the rebuild, it made the rebuild honest.

來源:DEV Community · dev.to