Fixed upstream 23 Oct 2026 Upstream bug fix in Orca
Orca: reading an SSH identity file could freeze the app
Our scanner flagged that Orca, a desktop app for running a fleet of coding agents, read SSH private keys with no check on the file type or size. We filed an issue and a pull request with a fix and tests. Maintainer Neil (nwparker) built a broader fix on top of it the next day, kept our test cases and credited us as co-author of the commit.
What was wrong
To connect to remote machines, Orca resolves the IdentityFile paths from the user’s SSH configuration and reads the keys in src/main/ssh/ssh-auth-resolution.ts. readPrivateKey() and findDefaultKeyFile() called readFileSync() on the path straight away:
- If the path pointed to a named pipe (FIFO) or a device, the synchronous read blocked Electron’s main process and the app froze.
- If it pointed to a large file by mistake, such as a disk image or a log, the whole file was loaded into memory before key parsing even started.
The paths come from the user’s own configuration, so this is not a security boundary that an outside attacker crosses. It is a robustness problem: one odd or mistyped IdentityFile line could hang the whole app. The codebase already capped file sizes in other places, for example WORKTREE_INCLUDE_MAX_FILE_BYTES, but not here.
How it was fixed
Our pull request added a statSync() check before both reads: only a regular file of at most 256 KB was read. Tests covered a directory and an oversized key, for both default and explicit key paths.
The maintainer shipped a broader version in pull request #32274. Every place Orca reads an SSH key or identity file now goes through one reader, ssh-identity-file-read.ts. It accepts regular files only (also through symlinks), opens them non-blocking so a path swapped for a pipe after the check still can’t block, reuses the existing 1 MB identity-file limit, and covers the .pub read for IdentitiesOnly as well. A failed sign-in now says which key file was skipped and why:
// Why one reader: identity paths come from user config, so a FIFO or device must never block the
// main process and an oversized file must never be loaded whole.
export function readSshIdentityFileSync(filePath: string): SshIdentityFileRead {
try {
return {
contents: readNodeFileSyncWithinLimit(filePath, MAX_SSH_IDENTITY_FILE_BYTES, READ_OPTIONS)
.buffer
}
} catch (error) {
return { contents: null, problem: describeIdentityFileProblem(error) }
}
}
Neil (nwparker) replied on our pull request:
“Thanks a lot for finding this, @Huge, and for the clear write-up and fix.”
Timeline
- October 2026. A scan of the Orca tree flagged the unbounded
readFileSync()on the key path; triage rated it valid as a robustness issue, not a vulnerability. - 22 Oct. We filed issue #31965 and opened pull request #31966 with the fix and tests.
- 23 Oct. The maintainer merged #32274, which builds on our pull request, as commit 699c17c, with us credited as co-author, and closed ours in its favour. As of 23 Oct 2026 it is not in a release yet; the latest is v1.4.237.
How to read this
The scanner’s first description called the path “attacker-chosen”. Reading the code showed the path comes from the user’s own SSH configuration, so we reported it as a robustness fix and nothing more. The maintainer then went further than our patch, closing the check-then-read race and the .pub read we had missed. Findings are leads for people, not verdicts.