"cat readme.txt" is not safe if you use iTerm2
Posted by arkadiyt 17 hours ago
Comments
Comment by KerrickStaley 14 hours ago
Why was this disclosed before the hole was patched in the stable release?
It's only been 18 days since the bug was reported to upstream, which is much shorter than typical vulnerability disclosure deadlines. The upstream commit (https://github.com/gnachman/iTerm2/commit/a9e745993c2e2cbb30...) has way less information than this blog post, so I think releasing this blog post now materially increases the chance that this will be exploited in the wild.
Update: The author was able to develop an exploit by prompting an LLM with just the upstream commit, but I still think this blog post raises the visibility of the vulnerability.
Comment by miki123211 2 minutes ago
You may need Claude Mythos to find a hard-to-discover bug in a 30-year-old open source codebase, but that bug will eventually be patched, and that patch will eventually hit the git repo. This lets smaller models rediscover the bug a lot more easily.
I won't be surprised if the window between a git commit and active port scans shrinks to hours or maybe even minutes in the next year or two.
This is where closed source SaaS has a crucial advantage. You don't get the changelog, and even if you did, it wouldn't be of much use to you after the fix is deployed to production.
Comment by winstonwinston 6 hours ago
Comment by ezoe 14 hours ago
If publicly accessible AI model with very cheap fee can find it, it's very natural to assume the attackers had found it already by the same method.
Comment by saddist0 13 hours ago
LLM is a tool, but people still need to know — what where how.
Comment by lxgr 13 hours ago
The problem with this is that the credible information "there's a bug in widely used tool x" will soon (if not already) be enough to trigger massive token expenditure of various others that will then also discover the bug, so this will often effectively amount to disclosure.
I guess the only winning move is to also start using AI to rapidly fix the bugs and have fast release cycles... Which of course has a host of other problems.
Comment by integralid 10 hours ago
There's a security bug in Openssh. I don't know what it is, but I can tell you with statistical certainty that it exists.
Go on and do with this information whatever you want.
Comment by lxgr 1 hour ago
But if you're a security research lab that a competing lab can ballpark the funding of and the amount of projects they're working on (based on industry comparisons, past publications etc.), I think that can be a signal.
Comment by mmilunic 9 hours ago
Comment by swiftcoder 2 hours ago
And the moment the commit lands upstream, they know what, where, and how.
The usual approach here is to backchannel patched versions to the distros and end users before the commit ever goes into upstream. Although obviously, this runs counter to some folks expectations about how open source releases work
Comment by mx7zysuj4xew 11 hours ago
Comment by 0123456789ABCDE 2 hours ago
> we rely on AI to find it
> where
> the upstream commit
> how
> publicly accessible AI model with very cheap fee
Comment by bawolff 11 hours ago
Comment by BFV 3 hours ago
Comment by chromacity 13 hours ago
I don't know what to do with this. I think there's this problematic tension between the expectation that on one hand, basic OS-level tools should remain simple and predictable; but on the other hand, that of course we want to have pretty colors, animations, and endless customization in the terminal.
And of course, we're now adding AI agents into the mix, so that evil text file might just need to say "disregard previous instructions and...".
Comment by harrall 12 hours ago
If we can get that to raise a red flag with people (and agents), people won’t be trying to put control instructions alongside user content (without considering safeguards) as much.
Comment by zrm 7 hours ago
At a basic level there is no avoiding this. There is only one network interface in most machines and both the in-band and out-of-band data are getting serialized into it one way or another. See also WiFi preamble injection.
These things are inherently recursive. You can't even really have a single place where all the serialization happens. It's user data in JSON in an HTTP stream in a TLS record in a TCP stream in an IP packet in an ethernet frame. Then it goes into a SQL query which goes into a B-tree node which goes into a filesystem extent which goes into a RAID stripe which goes into a logical block mapped to a physical block etc. All of those have control data in the same stream under the hood.
The actual mistake is leaving people to construct the combined data stream manually rather than programmatically. Manually is concatenating the user data directly into the SQL query, programmatically is parameterized queries.
Comment by rep_lodsb 2 hours ago
Not true. For most binary protocols, you have something like <Header> <Length of payload> <Payload>. On magnetic media, sector headers used a special pattern that couldn't be produced by regular data [1] -- and I'm sure SSDs don't interpret file contents as control information either!
There may be some broken protocols, but in most cases this kind of problem only happens when all the data is a stream of text that is simply concatenated together.
[1] e.g. https://en.wikipedia.org/wiki/Modified_frequency_modulation#...
Comment by zrm 1 hour ago
Another fun one there is that if you copy data containing an interior NULL to a buffer using snprintf and only check the return value for errors but not an unexpectedly short length, it may have copied less data into the buffer than you expect. At which point sending the entire buffer will be sending uninitialized memory.
Likewise if the user data in a specific context is required to be a specific length, so you hard-code the "length of payload" for those messages without checking that the user data is actually the required length.
This is why it needs to be programmatic. You don't declare a struct with header fields and a payload length and then leave it for the user to fill them in, you make the same function copy N bytes of data into the payload buffer and increment the payload length field by N, and then make the payload buffer and length field both modifiable only via that function, and have the send/write function use the payload length from the header instead of taking it as an argument. Or take the length argument but then error out without writing the data if it doesn't match the one in the header.
Comment by rep_lodsb 1 hour ago
>It's user data in JSON in an HTTP stream in a TLS record in a TCP stream in an IP packet in an ethernet frame. Then it goes into a SQL query which goes into a B-tree node which goes into a filesystem extent which goes into a RAID stripe which goes into a logical block mapped to a physical block etc. All of those have control data in the same stream under the hood.
It's true that a lot of code out there has bugs with escape sequences or field lengths, and some protocols may be designed so badly that it may be impossible to avoid such bugs. But what you are suggesting is greatly exaggerated, especially when we get to the lower layers. There is almost certainly no way that writing a "magic" byte sequence to a file will cause the storage device to misinterpret it as control data and change the mapping of logical to physical blocks. They've figured out how to separate this information reliably back when we were using floppy disks.
That the bits which control the block mapping are stored on the same device as a record in an SQL database doesn't mean that both are "the same stream".
Comment by zrm 1 hour ago
Which is also what happens if you use parameterized SQL queries. Or not what happens when one of the lower layers has a bug, like Heartbleed.
There also have been several disk firmware bugs over the years in various models where writing a specific data pattern results in corruption because the drive interprets it as an internal sequence.
Comment by skissane 4 hours ago
Allow a process to send control instructions out-of-band (e.g. via custom ioctls) and then allow the pty master to read them, maybe through some extension of packet mode (TIOCPKT)
Actually, some of the BSDs already have this… TIOCUCNTL exists on FreeBSD and (I believe) macOS too. But as long as Linux doesn’t have it, few will ever use it
Plus the FreeBSD TIOCUCNTL implementation, I think it only allows a single byte of user data for the custom ioctls, and is incompatible with TIOCPKT, which are huge limitations which I think discourage its adoption anyway
Comment by rep_lodsb 55 minutes ago
The broader problem with terminal control sequences didn't exist on Windows (until very recently at least), or before that DOS and OS/2. You had API calls to position the cursor, set color/background, etc. Or just write directly to a buffer of 80x25 characters+attribute bytes.
But Unix is what "serious" machines -a long time ago- used, so it has become the religion to insist that The Unix Way(TM) is superior in all things...
Comment by PunchyHamster 2 hours ago
Run software in container. Software gets PTY. Boom, same issue
Comment by ammar2 11 hours ago
Ironically, agents have the exact same class of problem.
Comment by layoric 10 hours ago
Comment by time4tea 5 hours ago
Comment by em-bee 11 hours ago
Comment by red_admiral 3 hours ago
Comment by ButlerianJihad 11 hours ago
https://utcc.utoronto.ca/~cks/space/blog/sysadmin/OnTerminal...
Comment by em-bee 11 hours ago
Comment by ori_b 9 hours ago
Terminal apps were obsolete once we had invented the pixel. Unix just provides no good way to write one that can be used remotely.
Comment by em-bee 8 hours ago
well that's the issue, isn't it?
the graphics options that we have are slow and complex, and they don't solve the problems like a terminal and therefore the terminal persist.
Comment by ori_b 7 hours ago
Comment by kps 8 hours ago
Comment by em-bee 8 hours ago
consider something like grep on multiple files. it should produce a list of lines found. the graphical terminal takes that list and displays it. it can distinguish the different components of that list, the filenames, the lines matched, the actual match, etc. because it can distinguish the elements, it can lay them out nicely. a column for the filenames, colors for the matched parts, counts, etc.
grep would not produce any graphics here, just semantic output that my imagined graphical terminal would be able to interpret and visualize.
Comment by nostrademons 12 hours ago
I think the real solution is that you shouldn't try to bolt colors, animations, and other rich interactivity features onto a text-based terminal protocol. You should design it specifically as a GUI protocol to begin with, with everything carefully typed and with well-defined semantics, and avoid using hacks to layer new functionality on top of previously undefined behavior. That prevents whatever remote interface you have from misinterpreting or mixing user-provided data with core UI code.
But that flies in the face of how we actually develop software, as well as basic economics. It will almost always be cheaper to adapt something that has widespread adoption into something that looks a little nicer, rather than trying to get widespread adoption for something that looks a little nicer.
Comment by JSR_FDED 5 hours ago
Comment by WalterBright 11 hours ago
Comment by redsocksfan45 11 hours ago
Comment by yowayb 12 hours ago
Comment by WalterBright 11 hours ago
Poof went the operating system!
Comment by jml7c5 9 hours ago
https://blog.danielwellman.com/2008/10/real-life-tron-on-an-...
Comment by tolciho 9 hours ago
Comment by kps 8 hours ago
Comment by WalterBright 8 hours ago
Comment by ButlerianJihad 9 hours ago
Comment by WalterBright 8 hours ago
Comment by ButlerianJihad 8 hours ago
Can you document it? Was it identified as a bug or vulnerability? What OS, even?
Comment by shakna 44 minutes ago
C64 had a flat memory map, where the input came as the first address in range 0 to DFFF. What came after that? The kernel. So if you wrote too much data into the input address space, and the overflow wasn't caught, you'd overwrite the OS there, too. And writing into the IO table was common, because it was faster to access.
Comment by ButlerianJihad 52 seconds ago
Comment by rcxdude 3 hours ago
Comment by WalterBright 8 hours ago
Do you know all about 1970s operating systems? Why do you find it hard to believe that a loop deleting backwards from the buffer wouldn't, say, zero out the stack frame and then a function return crashes it?
> Was it identified as a bug or vulnerability?
What difference does that make? It crashed the -10. It was reported.
> What OS, even?
The TOPS-10 operating system, or its predecessor. I don't recall just when TOPS-10 came out. It was 50 years ago.
Comment by ButlerianJihad 5 hours ago
Comment by Drunk_Engineer 12 hours ago
https://blog.mozilla.org/security/2019/10/09/iterm2-critical...
Comment by PunchyHamster 2 hours ago
Comment by eqvinox 4 hours ago
⇒ https://nvd.nist.gov/vuln/detail/CVE-2025-22275
iTerm2 3.5.6 through 3.5.10 before 3.5.11 sometimes allows remote attackers to obtain sensitive information from terminal commands by reading the /tmp/framer.txt file. This can occur for certain it2ssh and SSH Integration configurations, during remote logins to hosts that have a common Python installation.
But I thought there was something more…
https://news.ycombinator.com/item?id=47811587 (this page) was in the tmux integration.
Maybe iTerm2 should try a little less hard on these integrations...
Comment by raggi 4 hours ago
Comment by rkagerer 11 hours ago
> iTerm2 accepts the SSH conductor protocol from terminal output that is not actually coming from a trusted, real conductor session. In other words, untrusted terminal output can impersonate the remote conductor.
If I understand correctly, if a textfile (or any other source of content being emitted to the screen, such as server response banners) contains the special codes iTerm2 and the remote conductor use to communicate, they'll be processed and acted upon without verifying they actually came from a trusted remove conductor. Please correct me if I'm mistaken.
Comment by gnachman 1 hour ago
Comment by nine_k 8 hours ago
Comment by dang 7 hours ago
Comment by teddyh 7 hours ago
Comment by jclulow 1 hour ago
Comment by tbrownaw 9 hours ago
And I know PuTTY has a setting for what string is returned in response to some control code, that iirc per standard can be set from some other code.
.
In general, in-band signaling allows for "fun" tricks.
.
+++
Comment by yjftsjthsd-h 7 hours ago
Two tips, if I may: Ctrl-l is easier to type. And `reset` is equally hard to type on a broken terminal, but more effective.
Comment by alienbaby 22 minutes ago
Comment by bananaboy 12 hours ago
Comment by Bender 16 hours ago
alias cat
cat='strings -a --unicode=hex'Comment by halJordan 15 hours ago
Comment by Bender 14 hours ago
Comment by boomlinde 4 hours ago
Comment by kstenerud 5 hours ago
Comment by thorn 5 hours ago
Comment by eviks 9 hours ago
> A terminal emulator like iTerm2 is the modern software version of that hardware terminal.
That's the fundamental fatal flaw of emulating a bad dead hardware design. Are there any attempts to evolve here past all these weird in-band escape sequences leading cats to scratch your face?
Comment by boomlinde 4 hours ago
If iTerm2 had stuck to emulating a VT220 this issue would not have existed. If anything it's the idea that it should "evolve" that's flawed. Something like a VT220 was designed for a kind of use that is surprisingly relevant still. I think doing something significantly different warrants designing something significantly different, not merely "evolving" existing solutions to other problems by haphazardly shoehorning new features into them without paying attention to security implications.
This is only the latest of several rather serious vulnerabilities in iTerm2's SSH integration.
Comment by wang_li 9 hours ago
Also the problem here isn’t that iterm2 is trying to emulate terminals, it’s that it’s trying to do something more over the same network connection without making changes to the ssh protocol.
Comment by em-bee 8 hours ago
what we really want is being able to pipe semantic data that can be output to some kind of graphical device/interface that uses that semantic information to display the data using nice graphical interface elements.
Comment by boomlinde 3 hours ago
It seems to me that you are conflating the role of the terminal with the role of the shell. The terminal accepts streams of text and commands to instruct the terminal, so that software can accept input and present output. It doesn't fundamentally need to be aware of the concepts of pipes and commands to do that.
Of course, that doesn't stop iTerm2 from doing RCE by design, but at a conceptual level this is not a problem inherent to a terminal.
Comment by yjftsjthsd-h 7 hours ago
How about Arcan?
Comment by em-bee 5 hours ago
Comment by CodesInChaos 14 hours ago
Like why doesn't `println` in a modern language like rust auto-escape output to a terminal, and require a special `TerminalStr` to output a raw string.
Comment by PunchyHamster 2 hours ago
Comment by im3w1l 14 hours ago
Consider cat. It's short for concatenate. It concatenates the files based to it as arguments and writes them to stdout, that may or may not be redirected to a file. If it didn't pass along terminal escapes, it would fail at its job of accurate concatenation.
Now I don't mean to dismiss your idea, I do think you are on the right track. The question is just how to do this cleanly given the very entrenched assumptions that lead us where we are.
Comment by lxgr 13 hours ago
This is usually knowable.
It's a different question whether cat should be doing that, though – it's an extremely low level tool. What's wrong with `less`? (Other than the fact that some Docker images seem to not include it, which is pretty annoying and raises the question as to whether `docker exec` should be filtering escape sequences...)
Comment by tolciho 8 hours ago
Comment by im3w1l 12 hours ago
Comment by jdshaffer 13 hours ago
If I wrote my own version of cat in C, simply reading and displaying a single TXT character at a time, wouldn't I see the same behavior?
Comment by rezonant 13 hours ago
Comment by readthenotes1 13 hours ago
It is a problem in iterm, Apple's overlay, not in the cat program. Program. At least from Reading the article. That's what I got
Comment by rezonant 13 hours ago
Comment by fortran77 7 hours ago
cat is a file concatenation utility. UNIX people know to view text files with more.
Comment by TZubiri 14 hours ago
Comment by ButlerianJihad 14 hours ago
Comment by tasty_freeze 13 hours ago
Comment by themafia 8 hours ago
That's because we had terminal side macros. They were awesome in the 1980s.
Comment by zx8080 6 hours ago
OpenAI: sponsor of the today's 0-day.
Comment by jval43 2 hours ago
Comment by SrslyJosh 12 hours ago
Thanks, saved me some reading time.
Comment by WhereIsTheTruth 1 hour ago
AD in disguise
Comment by delduca 12 hours ago
Comment by 0123456789ABCDE 2 hours ago
what about spaceship? zsh or ohmyzsh?
time to reduce exposed surface
Comment by reader9274 9 hours ago
Comment by benatkin 7 hours ago
OTOH, in iTerm2, surprising new features seem to be welcome, if not now, in recent memory. https://news.ycombinator.com/item?id=40458135
Comment by connorboyle 8 hours ago
Comment by anthk 12 hours ago
Comment by rsync 9 hours ago
I want the terminal to be as dumb as possible.
I don’t want it to have any understanding of what it is displaying or anscribe any meaning or significance to the character characters it is outputting.
The first time apples terminal.app displayed that little lock icon at the ssh password prompt?
The hairs on the back of your neck should have stood up.
Comment by rafram 8 hours ago
Comment by rsync 4 hours ago
The ssh command switches the terminal into no-echo mode with termios flags.
Terminal.app, being clever, watches for disabled echo (among other things) and assumes a password is being entered and displays the key icon and enables Secure Event Input.
I don't want Terminal.app to be clever.
Comment by PunchyHamster 2 hours ago
Comment by hulitu 5 hours ago
Comment by midtake 7 hours ago
- ssh conductor
- AI features almost forced on us until the community complained
- clickable links
I just want a dumb, reliable terminal. Is that too much to ask?
Comment by AnonymousPlanet 3 hours ago
The developers of Kitty, Ghostty etc. are too much mouse haters to even acknowledge the possibility of this feature, so I'm stuck with iTerm2.
Comment by frutiger 7 hours ago
Comment by PunchyHamster 2 hours ago
Comment by joshstrange 2 hours ago
This was a wrong take back when it happened and it’s even more silly to bring it up now. No AI features were forced on anyone, it was opt-in and HN lost its mind over a nothing burger.
“Oh no! This software has a feature I don’t like which isn’t even enabled by default, whatever will I do?”
Comment by tkel 7 hours ago
Ah yes, the well known c+aliFIo shell script that every developer has. Inside the commonly used "ace" directory.
This article is sensationalist. And constructed by an LLM. It's well known that cat'ing binary files can introduce weird terminal escape codes into the session. Not surprised that iTerm's SSH integration is not security perfect.
Comment by dark-star 4 hours ago
What does iterm2 do with all that information, why does it need it? I don't get it
Comment by valleyer 12 hours ago
Comment by DonHopkins 11 hours ago
README: no such file or directory
One glorious day somebody finally sent me email complaining that they could not read the README file. I advised them to use "emacs README" instead of using cat. I was sorely disappointed they never sent me back a thank you note for correctly suggesting that emacs was the solution to their problem. It was my finest moment in passive aggressive emacs evangelism.
Comment by einpoklum 13 hours ago
Comment by holoduke 14 hours ago
Comment by biglio23 13 hours ago