Build1 distinct publisher3 min readPublished
Sonar's developer routed a custom resolver string straight into the arguments of a privileged networksetup call. He found it himself, in a pre-version-2 pass that produced twenty-six fixes, four of which he describes.
The Engineer · Build desk

build
Automated /.env scanning collected 1,033 live Stripe keys from 669 unrelated stacks1 distinct publisher
security
Rogue IPs added to Coder's Cloudflare pool served credential-stealing Terraform modules for 14 hours2 distinct publishers
product
A 2x LLM bill is not a bug report: token spend is an observability problem1 distinct publisher
security
ONCD stakes Texas water security on six months of donated vendor red teaming4 distinct publishers
Compiled by The EngineerSomething wrong?How this is made
The argument list is where the bug lived. A DNS change on macOS is privileged, so the app requests authorisation and then invokes `networksetup` on the far side of the prompt [3]. The remedy tells you what the break looked like: the developer's second rule is to pass arguments as an array, so there is no shell to interpret them and no quoting to get right [8]. Format that same string into a command line instead, and a semicolon in the resolver box is a second command inheriting the privileges of the first.
He names the mental model that produced it: it is my own app, and the field is for an IP address, so it will contain an IP address [5]. Both halves are wrong, he writes, and the second half is the one that generalises, because the reason to ask macOS for authorisation at all is that the code after the prompt has more power than the code before it [5].
The consent argument goes the same way. According to the post, the prompt authorises the operation the app described, not whatever ends up in the argument list, and a user who agreed to change DNS servers agreed to that and nothing else the string can be made to mean [7].
The objection worth taking seriously is the self-harm one. His answer is that the value need not be typed by the person at the keyboard: a paste from a webpage, a support article that says paste this into the custom DNS box, an accessibility-driven automation [6]. By that point the app has trained the user to expect an admin prompt at exactly that step [6]. That is what makes it someone else's bug and not just the owner's.
The fix order does not transfer everywhere, and here is the condition that decides it. Parsing works here because the target grammar is closed: a DNS server is an IPv4 or IPv6 address, so you parse the string into an address type and refuse anything that does not parse, rather than stripping characters you dislike [9]. Blocklists are a bet that you enumerated the shell, and the shell has more free time than you do [11]. Where the accepted value has no closed grammar the recipe stops carrying, which the post's own next item shows: Sonar exports the network map, and a device name is set by whoever is on your network [14]. The array-argument rule still applies there, but there is no address type to parse a device name into.
On the evidence: this is a developer's account of his own code. The post cites no CVE, no advisory and no outside reproduction, and it does not say whether the injection ever reached a released build [16]. None of that is needed for the mechanism, which is checkable in your own helper this afternoon, but it does mean the scope claim rests on one person's audit.
That audit produced twenty-six fixes, of which four are described [12], leaving twenty-two uncharacterised [15]. The two visible beyond the injection are the same category in different clothes: NextDNS and Pi-hole API tokens sitting in a preferences file that any process running as you can read and that gets swept into backups and sync [13], and the CSV export whose description runs out mid-sentence [14].
What survives the specifics is a rule about types. The value crossing an authorisation prompt should arrive as an address type, already validated before it ever reaches the privileged code.
Ranked by verification strength, evidence, and original report placement.
Sonar has a Control tab, one function of which switches the DNS resolver for the user's Mac, offering Cloudflare, Quad9, or a pasted address for the user's own Pi-hole.
The custom-resolver field exists because people run Pi-hole and NextDNS on their own networks, and hardcoding four public resolvers would have been useless to them.
Changing a network service's DNS servers is a privileged operation, so the app asks macOS for authorisation and runs networksetup on the other side of that prompt.
The custom-resolver field takes a string, the string goes into the arguments of a privileged command, and between those two facts there was nothing at all; the developer describes this as a command injection that ran as root.
The developer names the mental model behind the bug as "it's my own app, and the field is for an IP address, so it will contain an IP address", says both halves are wrong, and argues that the whole point of asking for authorisation is that the code on the other side of the prompt has more power than the code before it.
Against the objection that the user would only be attacking themselves, the post argues the value reaching the field need not be typed by the person at the machine: a paste from a webpage, a support article that says paste this into the custom DNS box, or an accessibility-driven automation can put text there, and the app has already trained the user to expect an admin prompt at that point.
Distinct publishers with included, body-backed reporting in this cluster.
1 article · September 6, 2026
Follow any of these and your For You feed starts watching them — no settings page required.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Specific, entirely self-reported
The mechanics hold up on their own terms: networksetup does need authorisation to rewrite a service's resolvers, a free-text field wired into its arguments does hand an interpreter whatever it receives, and the side findings -- tokens in a preferences file, a device name starting with = landing in a spreadsheet -- are described precisely enough to picture the code. Everything beyond the author's telling is missing: there's no identifier or advisory, nobody outside has reproduced it, the diff isn't included, and whether the affected build reached users goes unaddressed.
No uptake signal
Uptake is simply not part of this story. Install figures, version history, and any sense of how many users ever ran the code in question simply aren't part of the record; a fix described ahead of a release says nothing about who deployed what.
Title outruns the body
"Could run anything as root" promises more than the post demonstrates, since exploitation needs an attacker-supplied string plus a user who approves the admin prompt — a precondition the author states plainly himself. He also declines the easy escalations: no claim of exploitation in the wild, and he names his own reasoning as the cause. The overshoot is small and mostly lives in the headline.
Author is the vendor
The writer is Sonar's developer, publishing about his own product shortly before a version 2, and a post about twenty-six fixes doubles as evidence of care for a tool whose premise is telling you when your network is exposed. Self-criticism this specific is rarely a marketing move, but the source and the subject are one person and he benefits from the telling.
Consistent but uncorroborated
People are usually right about their own code, and this account is internally consistent and unusually concrete about the order of the fix. It is also unfalsifiable from outside, and the detail a reader most wants settled — whether a vulnerable build ever shipped — is the one the post leaves out, alongside twenty-two fixes it never itemises.