The whole "cat can hide unprintable characters" is such an old demo. I get this is a novel spin on which unprintable characters were doing but yeah, this was also my thought
I'm just used to aliasing cat to strings after working around a lot of red-team penetration testers. They would prank each other and me all the time. Had to also watch out for this one [1].
> At the time of writing, the fix has not yet reached stable releases.
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.
It’s a wrong way to look at things. Just because CIA can know your location (if they want to), would you share live location to everyone on the internet?
LLM is a tool, but people still need to know — what where how.
Not sure if that's a great example. If there's a catastrophic vulnerability in a widely used tool, I'd sure like to know about it even if the patch is taking some time!
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.
I think in the context of these it’s more of “we’ve discovered a bug” which gives you more information than “there is a bug”. The main difference in information being that the former implies not only there is a bug but that LLMs can find it.
If you're a random person on the Internet, I can indeed not do much with that information.
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.
Wrong argument, since it's not just available to "the CIA" but every rando under the sun, people should be notified immediately if "tracking" them is possible and mitigation measures should become a common standard practice
> LLM is a tool, but people still need to know — what where how.
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
There are many attackers that are just going to feed every commit of every project of interest to them into their LLMs and tell it "determine if this is patching an exploit and if so write the exploit". They don't need targeting clues. They're already watching everything coming out of
Do not make the mistake of modeling the attackers as "some guy in a basement with a laptop who decided just today to start attacking things". There are nation-state attackers. There are other attackers less funded than that but who still may not particularly blink at the plan I described above. Putting out the commit was sufficient to tell them even today exactly what the exploit was and the cheaper AI time gets the less targeting info they're going to need as the just grab everything.
I suggest modeling the attackers like a Dark Google. Think of them as well-funded, with lots of resources, and this is their day job, with dedicated teams and specialized positions and a codebase for exploits that they've been working on for years. They're not just some guy who wants to find an exploit maybe and needs huge hints about what commit might be an issue.
>Do not make the mistake of modeling the attackers as "some guy in a basement with a laptop who decided just today to start attacking things". There are nation-state attackers.
The parent's point is that if those capable attackers can exploit it anyway, doesn't mean it should be given on a silver platter to any script kiddie and guy in some basement with a laptop. The first have a much smaller target group than the latter.
My only caveat would be that in some security fixes, the pure code delta, is not always indicative of the full exploit method. But LLMs could interpolate from there depending on context.
There exist some disclosure embargo exceptions when you believe the vulnerability is being used in wild or when the vulnerability fix is already released publicly (such as git commit), which makes it possible to produce exploit quickly. In this case it is preferred by the community to publish vulnerability.
So this bug just proves my thesis about shortening update windows.
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.
> The author of iTerm2 initially didn’t consider it severe enough to warrant an immediate release, but they now seem to have reconsidered.
It's funny that we still have the same conversation about disclosure timelines. 18 days is plenty of time, the commit log is out there, etc.
The whole "responsible disclosure" thing is in response to people just publishing 0days, which itself was a response to vendors threatening researchers when vulns were directly reported.
I never understood why outputting unescaped data is viewed differently from generating unenclosed html.
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.
I think the problem is that 1) You want to be able to write arbitrary bytes, including shell escape sequences into files. 2) You don't want to accidentally write terminal escape sequences to stdout. 3) Stdout is modeled as a file.
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.
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...)
Besides less having a lot of code (features, bloat) and therefore attack surface (some less honor LESSSECURE=1 which on some OS these days involves some pretty tight pledge(2) restrictions), or that some vendors have configured less by default to automatically run random code so you can automatically page a gziped file or an attacker can maybe run arbitrary code (whoops!). Besides those issues, and any others I do not know about? Nothing.
A long, long time ago, it was literally possible to stuff the command buffer of a “dumb terminal” using ESC sequences and spoof keyboard input. So yeah, don’t count on ’cat’ being safe if your terminal isn’t!
I did this in 1985 on SOROC terminals we had in my first job out of college. However, it depended on the dip switch settings that were under a little door on top of the keyboard.
As the article shows, it is a bug in iTerm2. cat is just one program that could trigger it, the key thing is outputting attacker controlled text to the terminal when the attacker can control what files are present (ie unzipping a folder that includes a specific executable file at a well chosen location that gets triggered to run when the readme is output to the terminal)
Yes. It’s a Mac problem. That’s why Macs do the worst at pwn2own. It’s compounded by the fact that Mac users deny that there are problems in their beloved OS.
cat is a file concatenation utility. UNIX people know to view text files with more.
This is cool work, but it's also somewhat unsurprising: this is a recurring problem with fancy, richly-featured terminal apps. I think we had at least ten publicly reported vulns of this type in the past 15 years. We also had vulnerabilities in tools such as less, in text editors such as vim, etc. And notably, many of these are logic bugs - i.e., they are not alleviated by a rewrite to Rust.
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...".
Makes me wonder if Claude Code has similar vulnerabilities, as it has a pretty rich terminal interface as well.
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.
Spoofing the source of a string that controls colors and animations isn’t really a problem. Spoofing the source of a string that get executed is in an entirely different league.
Unless the colors meaningfully change the represented text/information eg hiding or highlighting key details leading to tactically dangerous misinterpretation.
Well all these bugs (iTerm2’s, prompt injection, SQL injection, XSS) are one class of mistake — you sent out-of-band data in the same stream as the in-band data.
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.
> 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.
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.
>All of those have control data in the same stream under the hood.
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.
The header and length of the payload are control data. It's still being concatenated even if it's binary. A common way to screw that one up is to measure the "length of payload" in two different ways, for example by using the return value of strlen or strnlen when setting the length of the payload but the return value of read(2) or std::string size() when sending/writing it or vice versa. If the data unexpectedly contains an interior NULL, or was expected to be NULL terminated and isn't, strnlen will return a different value than the amount of data read into the send buffer. Then the receiver may interpret user data after the interior NULL as the next header or, when they're reversed, interpret the next header as user data from the first message and user data from the next message as the next header.
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.
>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".
> 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.
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.
I distinctly remember bugs with non-Hayes modems where they would treat `+++ATH0` coming over the wire as a control, leading to BBS messages which could forcibly disconnect the unlucky user who read it.
In this particular case, IIRC Hayes had patented the known approach for detecting this and avoiding the disconnect, so rival modem makers were somewhat powerless to do anything better. I wonder if such a patent would still hold today...
What was patented was the technique of checking for a delay of about a second to separate the command from any data. It still had to be sent from the local side of the connection, so the exploit needed some way to get it echoed back (like ICMP).
DOS had a driver ANSI.SYS for interpreting terminal escape sequences, and it included a non-standard one for redefining keys. So if that driver was installed, 'type'ing a text file could potentially remap any key to something like "format C: <Return> Y <Return>".
This could be fixed with an extension to the kernel pty subsystem
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
For this use case, there would also have to be an extension to the SSH protocol to send such out-of-band information. Maybe this already exists and isn't used?
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...
The Unix way died with Plan9/9front and there are no teletypes, period. Just windows with shells running inside as any other program. You can run a browser under a window(1) instead of rc(1) which is the shell.
Architecture Astronaut! TCP is a stream protocol. A terminal program is expected to honor the stream protocol: I can use a terminal program to speak SMTP or HTTP. I can paste binary shit into it and copy binary shit out of it (some caveats apply).
If you're gonna jack some control protocol into a session which is sitting directly on the stream protocol, that's on you. This is as airtight as injecting a control protocol into SMTP or HTTP. Encapsulate the entire protocol (obviously this requires presence on both ends), open a second channel (same), or go home. It's worth noting that the "protocol" drops a helper script on the other side; so theoretically it is possible for them to achieve encapsulation, but doing it properly might require additional permissions / access.
Obviously they published a fix, since that's how the exploit was reverse engineered. This is "...what happens when terminal output is able to impersonate one side of that feature's protocol."
i think part of the problem is the archaic interface that is needed to enable feature rich terminal apps. what we really want is a modern terminal API that does not rely on in-band command sequences. that is we want terminals that can be programmed like a GUI, but still run in a simple (remote) terminal like before.
that's actually not what i am after. what i envision is a graphical terminal, that is a terminal that uses graphic elements to display the output.
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.
So are a couple shells that use some kind of webkit tty. VS Code’s integrated terminal counts, I guess.
It could be an interesting paradigm, though, to have a hybrid between fullscreen and traditional tty programs: you output some forms, they are displayed by the terminal inline, but your scrollback just works like normal, and you can freely copy and paste stuff into the form. Once you submit the form, it becomes non-interactive, but stays in your scrollback buffer. You can select and copy textual data from it, but the form’s chrome cannot be selected as line drawing characters.
Probably could be a piece of concept art, I guess.
hmm, actually, you got a point there. emacs could be the like that graphical terminal, except for now it is still stuck inside a traditional terminal itself. even the GUI version of it is mostly just looking like a terminal, not really taking advantage of the potential of graphical elements. we would need a real GUI and support for exchanging structured data with external commands. for now emacs is still kind of its own world.
> even the GUI version of it is mostly just looking like a terminal, not really taking advantage of the potential of graphical elements.
Emacs is text based (mostly), but customization happens through the the concept of Faces, not ansi escape codes. You can then embed properties in the text objects and have them react to click events. The only element missing is a 2D context that could be animated (if it's static, you can use SVG as Emacs can render it).
That'd be really cool. I'd never thought about enabling deeper graphical capabilities in a shell. But if you were to have a shell with rich objects rather than dumb bytes, that is a world that would open up!
PowerShell, for instance, has Format.ps1xml[0] that allows you to configure how objects get displayed by default (i.e. when that object gets emitted at the end of the pipeline). Such a concept could in principle be extended to have graphical elements. How cool would it be to have grep's output let you collapse matches from the same file!
PowerShell cmdlets output .NET objects with properties, in that example Get-Process makes an object-per-running-process with properties for Name, Id, and more. Out-GridView takes arbitrary objects and draws a resizeable GUI window with a list of the input, properties as columns, sortable, filterable, and has options to use it as a basic "choose one of these and click OK" user-prompt. It works with the grep-analogous cmdlet:
and the output is the filename, line number, line, and regex match groups, of each match. [This dates back to Windows XP SP2, in 2004].
If we're talking about things we imagine in terminals, one I have wanted is multiple windows for making notes, similar to having a text editor open constantly reloading a file on any changes and running some terminal commands with tee into the file, but better integrated - so I could keep a few useful context results but ignore logspam results; and "keep" in another window without having to copypaste. Something better integrated - it always gets all command output, but disposes of it automatically after a while, but can be instructed to keep.
Plan9 has no terminals. Well, it actually has one in 9front, vt(1), but as a tool to call against Unix systems (such as ssh), not to interact with 9front software. vt(1) in 9front it's as 'native' as HyperTerminal in Windows.
I shudder at the amount of backwards compatibility that would break. Is there anything more complicated than a simple input-output pipe (cat, grep, ...) that doesn't use terminal escapes? Even `ls --color` needs them!
right, envision that we get tmux working in that new terminal (and that's already happening, just look at tmux -CC), then it can be there for all the backwards compatibility stuff while modern apps and maybe a new modern multiplexer work without.
> this is a recurring problem with fancy, richly-featured terminal apps.
This is a recurring problem with fancy, richly-featured programmer-oriented apps made by programmers for programmers because for some reason most of the tool-writing programmers apparently just love to put "execute arbitrary code" functionality in there. Perhaps they think that the user will only execute the code they themselves wrote/approved and will never make mistakes or be tricked; or something like that, I dunno.
"They" is 1 guy (George Nachman) who has tirelessly maintained this app in his spare time for 15 years. This is an arms race that's simply impossible for solo devs or even small teams to win. It's going to have a real chilling effect. I've seen a few popular open source projects take themselves private recently (eg cal.com) due to this.
No, this bug is specific to iTerm2. As for whether there is something as bad for ghostty floating out there, I would hope not. It's a strong goal for it not to be. In Ghostty (and also the terminal I currently use, WezTerm) modularity is prized. What belongs as a clear add-on feature such as this doesn't get to run without being configured first.
Back in the PDP-10 days, one communicated with it using a terminal attached to it. One of my fellow students discovered that if you hit backspace enough times, the terminal handler would keep erasing characters before the buffer. Go far enough, and then there was an escape character (Ctrl-u?) that would delete the whole line.
control+u for line-kill is probably a recent thing, a random PDF of "The Unix Programming Environment" (Kernighan & Pike, 1984, p.6) has @ as the line-kill character (and # is erase which these days may or may not be control+? (linux often does something wrong with the delete key, unlike the *BSD)).
I used to leave a file called README in my public ftp directory that just said:
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.
Maybe I'm being unfair here, but it sounds like your complicated system (involving bootstrap scripts, a remote conductor agent, and "hijacking" the terminal connection with special escape sequences for command communication) has a subtle bug. Can't say I'm surprised, complexity breeds this sort of thing, especially when using primitives in ways they weren't really intended to be used.
> 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.
I’ve said this for as long as I’ve been here on hacker news…
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.
What you’re describing would be a completely unusable terminal. You’d lose things as basic as the backspace key. And what’s wrong with Terminal.app indicating when it’s suppressing output?
Terminal.app does not suppress output in my example.
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.
There's been plenty of times that I catted a binary file and broke my terminal settings. Sometimes fixable by running `clear` (without being able to see what I'm typing), sometimes not.
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.
> A terminal used to be a real hardware device: a keyboard and screen connected to a machine, with programs reading input from that device and writing output back to it.
> 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?
Yes. It’s called the X Window System and it’s been around since the ‘80s.
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.
X11 or any network transparent graphics protocol doesn't solve the problems that a terminal solves. how do you pipe data through multiple applications in one command using a GUI for example? nobody has been able to solve that in a practical way yet.
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.
> how do you pipe data through multiple applications in one command using a GUI for example? nobody has been able to solve that in a practical way yet.
> X11 or any network transparent graphics protocol doesn't solve the problems that a terminal solves. how do you pipe data through multiple applications in one command using a GUI for example? nobody has been able to solve that in a practical way yet.
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.
i am not conflating them, the problem is rather that the current terminals define or restrict what the shell can do. shells are being rewritten already. b they could not do what i want them to do without the terminals changing too, so the terminal needs to be next.
The bug is in a feature of iTerm2 that the "bad dead hardware design" did not have. The "bad dead hardware design" was much simpler and less ambitious in scope.
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.
The title is sensationalist; cat is fine. What is unsafe is iTerm's ssh integration, which is pretty obviously unsafe, because it includes a side control channel that is not cleanly separated from the the data stream. Don't use it, use normal ssh, and all should be fine.
> The final chunk (ace/c+aliFIo) works if that path exists locally and is executable.
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.
Many years ago, terminal emulators used to allow keyboard rebindings via escape codes. This is why it was then common knowledge to never “cat” untrusted files, and to use a program to display the files instead; either a pager, like “less”, or a text editor.
I believe there were even more substantial issues in some terminal emulators, where escape sequences could write to arbitrary files or even execute programs. I think it's still very reasonable advice to avoid dumping arbitrary bytes into the terminal stream, even if only to avoid screwing up the state of the terminal.
Clickable paths is the unique feature of iTerm2 I use the most. It's called sematic history, for some reason, and converts a UNIX environment into something like an IDE. I let it trigger a bash script that opens my editor when I click a path in, e.g., a stack trace or in the output of a sequence of piped commands.
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.
> AI features almost forced on us until the community complained
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?”
I would prefer if these would not happen but that is the price for having a rich terminal. I donate to the author of iterm a small sum every month, I wish if he focused on the security for a while and tightened some bugs instead of pushing into AI related features
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.
Why does iterm2 need to know the shell and/or python versions on the other side? What happens if the othe side is a system that doesn't "understand" its bootstrap script (like a network switch or just some weird shell)?
What does iterm2 do with all that information, why does it need it? I don't get it
iTerm2 author here. This could be used as a link in an exploit chain but by itself the claim in the title is massively overblown. I’m on a family vacation but I’ll release a fix when I get back.
Disclosure: I didn't discover the vulnerability. I wrote the blog post.
Thanks for releasing a fix!
It was surprising that there wasn't an official release, even though the bug impacts otherwise routine, harmless workflows. The patch itself [1] framed the issue as "hypothetical," so the goal of the blog post was to demonstrate that it is not. I'm glad that you've agreed to release a fix.
One reason I still prefer iTerm2 or Ghostty over Terminal.app is that it has way saner settings for what the word boundaries are, and it lets me select whole paths by double clicking on them. If there was a way to change it for the default terminal, I would just be using it.
Barely anyone mentioned the "AI agent angle", I mean the situation when an AI agent runs "cat readme.txt" a file with embedded instructions becomes a prompt injection attack. It is the same vulnerability class out-of-band data smuggled through an in-band channel, just targeting the different parser.
Terminal security guys have been fighting this for decades and the AI guys are about to rediscover it
These categories of vulnerability are not new: https://dgl.cx/2023/09/ansi-terminal-security -- any time you take any untrusted data and do literally anything with it, you're at risk.
> 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.
...which, the article strongly implies, but does not explicitly state, results in code execution on the local client machine.
But what about the case when it's working as designed, when the output does come from the remote conductor? It sounds like the server, where the conductor is running, is in that case trusted to execute arbitrary code on the client? Assuming the client doesn't use some sort of remote attestation, how can the remote conductor really be trusted?
I think this article is horribly written. The second paragraph, in its entirety, reads:
> It turns out that it is NOT, if you use iTerm2.
And as far as I can tell, that is a vast overstatement. I think an actually true statement would be "It may not be, if you use iTerm2 and its optional 'Shell Integration' feature."
As far as I can tell, the "Shell Integration" feature under discussion is entirely optional and disabled by default. If it's not enabled, then there is no problem here. End of story.
Pretty much, yes. It is meant to be the takeaway from the article and as far as I can tell, the statement as written is false. Pretty serious problem, I think.
I would say iTerm 2 has a pretty serious problem. A detailed analysis of the issue having a sentence implying it affects all users rather than many or most users is a minor problem.
Wait, hold on. iTerm 2's "conductor" is listening for the special escape sequences, whether or not you are using the shell integration features. The exploit affects all users, not just ones who have installed iTerm 2's shell integration.
I can't tell whether that's true or not. The article says:
> The rough model is:
> 1. iTerm2 launches SSH integration, usually through it2ssh.
> 2. iTerm2 sends a remote bootstrap script, the conductor, over the existing SSH session.
> 3. That remote script becomes the protocol peer for iTerm2.
How can I tell whether this "conductor" is running on the remote host or not?
I tried to reproduce this problem, following their instructions, but was unable to. I think but am not sure that's because my environment is pretty much nothing like one that would allow this to work.
For example, whether it's the default or not, my iTerm2 just doesn't have shell integration enabled. With my profile "Command:" set to "Login Shell," it doesn't look like I could enable it if I wanted to: "Load shell integration automatically" is disabled, apparently because "Automatic loading doesn't work with ksh."
The remote bootstrap script is not part of the exploit at all. It happens in iTerm locally without any ssh session. I just installed iTerm2 on a fresh machine (no shell integration installed), ran the exploit (generated the file with the python script, ran `cat readme.txt` locally), and it worked.
This is explained in the article in the "The core bug" section.
Cannot get it to work. Not worrying about it any more. Still think that the original article is horribly written, now think that their instructions are also.
Thank you. If correct, that is helpful. I only checked my own copy and as far as I can tell, the feature is disabled. It may well be that I disabled it, I don't remember. Seems like the kind of thing I would disable if I noticed it but iTerm2 has so many features and so many settings that I have no idea whether I ever noticed it before this.
I note that the documentation says this:
> Shell Integration
> iTerm2 may be integrated with the unix shell so that [blah blah blah]
> How To Enable Shell Integration
> [blah blah blah]
And that does not make it sound as if it's enabled by default. I really don't know. I only started using iTerm2 about three or four weeks ago.
Bender | a day ago
halJordan | a day ago
Bender | a day ago
[1] - https://thejh.net/misc/website-terminal-copy-paste
KerrickStaley | a day 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.
ezoe | a day 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.
saddist0 | a day ago
LLM is a tool, but people still need to know — what where how.
lxgr | a day 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.
integralid | 23 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.
mmilunic | 22 hours ago
lxgr | 14 hours 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.
mx7zysuj4xew | a day ago
0123456789ABCDE | 15 hours ago
> we rely on AI to find it
> where
> the upstream commit
> how
> publicly accessible AI model with very cheap fee
swiftcoder | 15 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
6thbit | 9 hours ago
In other words, it becomes part of your threat model.
jerf | 9 hours ago
There are many attackers that are just going to feed every commit of every project of interest to them into their LLMs and tell it "determine if this is patching an exploit and if so write the exploit". They don't need targeting clues. They're already watching everything coming out of
Do not make the mistake of modeling the attackers as "some guy in a basement with a laptop who decided just today to start attacking things". There are nation-state attackers. There are other attackers less funded than that but who still may not particularly blink at the plan I described above. Putting out the commit was sufficient to tell them even today exactly what the exploit was and the cheaper AI time gets the less targeting info they're going to need as the just grab everything.
I suggest modeling the attackers like a Dark Google. Think of them as well-funded, with lots of resources, and this is their day job, with dedicated teams and specialized positions and a codebase for exploits that they've been working on for years. They're not just some guy who wants to find an exploit maybe and needs huge hints about what commit might be an issue.
coldtea | 8 hours ago
The parent's point is that if those capable attackers can exploit it anyway, doesn't mean it should be given on a silver platter to any script kiddie and guy in some basement with a laptop. The first have a much smaller target group than the latter.
staticassertion | 8 hours ago
bawolff | a day ago
6thbit | 9 hours ago
My only caveat would be that in some security fixes, the pure code delta, is not always indicative of the full exploit method. But LLMs could interpolate from there depending on context.
bawolff | 2 hours ago
Attackers are not idiots. Once you have the commit, it is usually pretty easy to figure out, even just having the binary diff is usually enough.
6thbit | an hour ago
winstonwinston | 19 hours ago
miki123211 | 13 hours 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.
spacedcowboy | 11 hours ago
It also puts the lie to "all bugs are shallow with sufficient eyes", gmime is pretty commonly used, but locale<->UTF and back were still wrong.
maximilianburke | 9 hours ago
cryptbe | 9 hours ago
>The author was able to develop an exploit by prompting an LLM with just the upstream commit
Yes, I was able to do this. I believe anyone watching iTerm2's commits would be able to do this too.
>but I still think this blog post raises the visibility of the vulnerability.
Yes, I wanted to raise the visibility of the vulnerability, and it works!
The author of iTerm2 initially didn’t consider it severe enough to warrant an immediate release, but they now seem to have reconsidered.
staticassertion | 8 hours ago
It's funny that we still have the same conversation about disclosure timelines. 18 days is plenty of time, the commit log is out there, etc.
The whole "responsible disclosure" thing is in response to people just publishing 0days, which itself was a response to vendors threatening researchers when vulns were directly reported.
CodesInChaos | a day 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.
im3w1l | a day 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.
lxgr | a day 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...)
im3w1l | a day ago
tolciho | 22 hours ago
ndsipa_pomu | 11 hours ago
PunchyHamster | 16 hours ago
TZubiri | a day ago
ButlerianJihad | a day ago
tasty_freeze | a day ago
themafia | 22 hours ago
That's because we had terminal side macros. They were awesome in the 1980s.
holoduke | a day ago
jdshaffer | a day 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?
rezonant | a day ago
readthenotes1 | a day 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
rezonant | a day ago
fortran77 | 20 hours ago
cat is a file concatenation utility. UNIX people know to view text files with more.
einpoklum | a day ago
chromacity | a day 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...".
nostrademons | a day 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.
JSR_FDED | 18 hours ago
ncr100 | 9 hours ago
harrall | a day 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.
ammar2 | a day ago
Ironically, agents have the exact same class of problem.
layoric | 23 hours ago
zrm | 20 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.
rep_lodsb | 15 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#...
zrm | 14 hours 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.
rep_lodsb | 14 hours 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".
zrm | 14 hours 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.
StilesCrisis | 13 hours ago
In this particular case, IIRC Hayes had patented the known approach for detecting this and avoiding the disconnect, so rival modem makers were somewhat powerless to do anything better. I wonder if such a patent would still hold today...
rep_lodsb | 12 hours ago
What was patented was the technique of checking for a delay of about a second to separate the command from any data. It still had to be sent from the local side of the connection, so the exploit needed some way to get it echoed back (like ICMP).
More relevant to this bug: https://en.wikipedia.org/wiki/ANSI_bomb#Keyboard_remapping
DOS had a driver ANSI.SYS for interpreting terminal escape sequences, and it included a non-standard one for redefining keys. So if that driver was installed, 'type'ing a text file could potentially remap any key to something like "format C: <Return> Y <Return>".
time4tea | 18 hours ago
skissane | 18 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
PunchyHamster | 16 hours ago
Run software in container. Software gets PTY. Boom, same issue
rep_lodsb | 14 hours 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...
anthk | 11 hours ago
m3047 | 4 hours ago
If you're gonna jack some control protocol into a session which is sitting directly on the stream protocol, that's on you. This is as airtight as injecting a control protocol into SMTP or HTTP. Encapsulate the entire protocol (obviously this requires presence on both ends), open a second channel (same), or go home. It's worth noting that the "protocol" drops a helper script on the other side; so theoretically it is possible for them to achieve encapsulation, but doing it properly might require additional permissions / access.
Obviously they published a fix, since that's how the exploit was reverse engineered. This is "...what happens when terminal output is able to impersonate one side of that feature's protocol."
WalterBright | a day ago
em-bee | a day ago
ButlerianJihad | a day ago
https://utcc.utoronto.ca/~cks/space/blog/sysadmin/OnTerminal...
em-bee | a day ago
ori_b | 22 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.
kps | 21 hours ago
em-bee | 21 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.
WesolyKubeczek | 13 hours ago
em-bee | 8 hours ago
incidentally ttyphoon is a terminal that uses a browser base gui framework. maybe there is that browser for the teminal...
WesolyKubeczek | 3 hours ago
It could be an interesting paradigm, though, to have a hybrid between fullscreen and traditional tty programs: you output some forms, they are displayed by the terminal inline, but your scrollback just works like normal, and you can freely copy and paste stuff into the form. Once you submit the form, it becomes non-interactive, but stays in your scrollback buffer. You can select and copy textual data from it, but the form’s chrome cannot be selected as line drawing characters.
Probably could be a piece of concept art, I guess.
skydhash | 9 hours ago
em-bee | 5 hours ago
skydhash | 4 hours ago
Emacs is text based (mostly), but customization happens through the the concept of Faces, not ansi escape codes. You can then embed properties in the text objects and have them react to click events. The only element missing is a 2D context that could be animated (if it's static, you can use SVG as Emacs can render it).
jcgl | 8 hours ago
PowerShell, for instance, has Format.ps1xml[0] that allows you to configure how objects get displayed by default (i.e. when that object gets emitted at the end of the pipeline). Such a concept could in principle be extended to have graphical elements. How cool would it be to have grep's output let you collapse matches from the same file!
[0] https://learn.microsoft.com/en-us/powershell/module/microsof...
jodrellblank | 2 hours ago
https://blog.rmilne.ca/wp-content/uploads/2020/04/image_thum...
PowerShell cmdlets output .NET objects with properties, in that example Get-Process makes an object-per-running-process with properties for Name, Id, and more. Out-GridView takes arbitrary objects and draws a resizeable GUI window with a list of the input, properties as columns, sortable, filterable, and has options to use it as a basic "choose one of these and click OK" user-prompt. It works with the grep-analogous cmdlet:
and the output is the filename, line number, line, and regex match groups, of each match. [This dates back to Windows XP SP2, in 2004].If we're talking about things we imagine in terminals, one I have wanted is multiple windows for making notes, similar to having a text editor open constantly reloading a file on any changes and running some terminal commands with tee into the file, but better integrated - so I could keep a few useful context results but ignore logspam results; and "keep" in another window without having to copypaste. Something better integrated - it always gets all command output, but disposes of it automatically after a while, but can be instructed to keep.
em-bee | 21 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.
ori_b | 20 hours ago
anthk | 11 hours ago
anthk | 11 hours ago
red_admiral | 16 hours ago
em-bee | 8 hours ago
redsocksfan45 | a day ago
Joker_vD | 5 hours ago
This is a recurring problem with fancy, richly-featured programmer-oriented apps made by programmers for programmers because for some reason most of the tool-writing programmers apparently just love to put "execute arbitrary code" functionality in there. Perhaps they think that the user will only execute the code they themselves wrote/approved and will never make mistakes or be tricked; or something like that, I dunno.
Drunk_Engineer | a day ago
https://blog.mozilla.org/security/2019/10/09/iterm2-critical...
PunchyHamster | 16 hours ago
luckman212 | 11 hours ago
anthk | a day ago
valleyer | a day ago
delduca | a day ago
reader9274 | 22 hours ago
benatkin | 20 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
0123456789ABCDE | 15 hours ago
what about spaceship? zsh or ohmyzsh?
time to reduce exposed surface
bananaboy | a day ago
WalterBright | a day ago
Poof went the operating system!
jml7c5 | 22 hours ago
https://blog.danielwellman.com/2008/10/real-life-tron-on-an-...
tolciho | 22 hours ago
kps | 22 hours ago
WalterBright | 21 hours ago
DonHopkins | a day 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.
rkagerer | a day 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.
rsync | 23 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.
rafram | 22 hours ago
rsync | 17 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.
rafram | 12 hours ago
PunchyHamster | 16 hours ago
tbrownaw | 22 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.
.
+++
yjftsjthsd-h | 21 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.
alienbaby | 13 hours ago
WesolyKubeczek | 13 hours ago
eviks | 22 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?
wang_li | 22 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.
em-bee | 21 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.
yjftsjthsd-h | 21 hours ago
How about Arcan?
https://arcan-fe.com/2021/04/12/introducing-pipeworld/
em-bee | 18 hours ago
yjftsjthsd-h | 8 hours ago
boomlinde | 16 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.
em-bee | 8 hours ago
boomlinde | 17 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.
connorboyle | 21 hours ago
collinfunk | 6 hours ago
The tweet has no mention of iTerm2 which makes it sound like an issue in 'cat', which is mildly annoying [1].
[1] https://x.com/calif_io/status/2045207168677503241
nine_k | 21 hours ago
dang | 20 hours ago
cryptbe | 9 hours ago
I've now updated the blog post.
tkel | 20 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.
teddyh | 20 hours ago
jclulow | 14 hours ago
m3047 | 3 hours ago
midtake | 20 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?
frutiger | 20 hours ago
AnonymousPlanet | 16 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.
PunchyHamster | 16 hours ago
joshstrange | 15 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?”
m3047 | 3 hours ago
zx8080 | 19 hours ago
OpenAI: sponsor of the today's 0-day.
jval43 | 15 hours ago
kstenerud | 18 hours ago
hulitu | 18 hours ago
thorn | 18 hours ago
eqvinox | 18 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...
raggi | 18 hours ago
WesolyKubeczek | 13 hours ago
How about bloody no and working with upstream ncurses to update the terminfo database?
dark-star | 17 hours ago
What does iterm2 do with all that information, why does it need it? I don't get it
boomlinde | 17 hours ago
gnachman | 15 hours ago
srj | 9 hours ago
cryptbe | 9 hours ago
Thanks for releasing a fix!
It was surprising that there wasn't an official release, even though the bug impacts otherwise routine, harmless workflows. The patch itself [1] framed the issue as "hypothetical," so the goal of the blog post was to demonstrate that it is not. I'm glad that you've agreed to release a fix.
[1] https://github.com/gnachman/iTerm2/commit/a9e745993c2e2cbb30...
hmokiguess | 8 hours ago
WhereIsTheTruth | 14 hours ago
AD in disguise
xg15 | 13 hours ago
WesolyKubeczek | 13 hours ago
cremer | 11 hours ago
jayofdoom | 9 hours ago
ptx | 9 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.
...which, the article strongly implies, but does not explicitly state, results in code execution on the local client machine.
But what about the case when it's working as designed, when the output does come from the remote conductor? It sounds like the server, where the conductor is running, is in that case trusted to execute arbitrary code on the client? Assuming the client doesn't use some sort of remote attestation, how can the remote conductor really be trusted?
f30e3dfed1c9 | 9 hours ago
> It turns out that it is NOT, if you use iTerm2.
And as far as I can tell, that is a vast overstatement. I think an actually true statement would be "It may not be, if you use iTerm2 and its optional 'Shell Integration' feature."
As far as I can tell, the "Shell Integration" feature under discussion is entirely optional and disabled by default. If it's not enabled, then there is no problem here. End of story.
Happy to be corrected if I'm wrong about this.
anamexis | 9 hours ago
f30e3dfed1c9 | 8 hours ago
anamexis | 8 hours ago
f30e3dfed1c9 | 8 hours ago
I cannot speculate on what fraction of iTerm2 users enable this optional feature. Is it "many or most"? No idea.
I note that the article nowhere mentions the fact that the feature is optional. That would be a huge improvement.
We can disagree over whether the article is horribly written or not. My firm opinion is that it is.
anamexis | 8 hours ago
f30e3dfed1c9 | 8 hours ago
> The rough model is:
> 1. iTerm2 launches SSH integration, usually through it2ssh.
> 2. iTerm2 sends a remote bootstrap script, the conductor, over the existing SSH session.
> 3. That remote script becomes the protocol peer for iTerm2.
How can I tell whether this "conductor" is running on the remote host or not?
I tried to reproduce this problem, following their instructions, but was unable to. I think but am not sure that's because my environment is pretty much nothing like one that would allow this to work.
For example, whether it's the default or not, my iTerm2 just doesn't have shell integration enabled. With my profile "Command:" set to "Login Shell," it doesn't look like I could enable it if I wanted to: "Load shell integration automatically" is disabled, apparently because "Automatic loading doesn't work with ksh."
anamexis | 7 hours ago
This is explained in the article in the "The core bug" section.
f30e3dfed1c9 | 7 hours ago
cryptbe | 9 hours ago
f30e3dfed1c9 | 8 hours ago
I note that the documentation says this:
> Shell Integration
> iTerm2 may be integrated with the unix shell so that [blah blah blah]
> How To Enable Shell Integration
> [blah blah blah]
And that does not make it sound as if it's enabled by default. I really don't know. I only started using iTerm2 about three or four weeks ago.