EresusSecurity
Back to Research
Vulnerability Research

FreeBSD TIOCSTI: Terminal Input Injection and Local Privilege Risk

Eresus Security Research TeamSecurity Researcher
July 14, 2026
Updated: July 20, 2026
12 min read
Illustration of the Eresus spider pursuing a FreeBSD daemon character to represent TIOCSTI terminal-input injection risk

Research summary

While reviewing FreeBSD TTY behaviour, Eresus Security identified a risk in which a lower-privileged process sharing a controlling terminal could influence input delivered to a more privileged foreground session.

The research concerns the boundary between terminal input access and the privilege of the foreground process group in shared-terminal situations. It is relevant to local, interactive workflows where an untrusted background process and a privileged session can share terminal context.

This is a defensive disclosure. It intentionally excludes executable proof-of-concept code, command sequences, and exploitation instructions.

Responsible disclosure timeline

  • 18 May 2026: Eresus Security sent a coordinated-disclosure report to the FreeBSD Security Team, including technical analysis, impact, possible workarounds, and a working PoC.
  • 18 May 2026 (same day): The FreeBSD Security Team acknowledged the report and asked that an environment-specific hardcoded path be removed from the PoC. A revised, self-contained PoC was sent the same day.
  • 23 May 2026: Eresus Security followed up to confirm receipt of the revised PoC and to ask about review status and an expected coordination timeline. This message has not received a reply as of publication.
  • 20 July 2026: This limited, non-technical advisory is published while coordination with the FreeBSD Security Team remains open. The 90-day window from the 18 May 2026 report has not yet elapsed; this is not a post-embargo disclosure, and no exploit code, commands, or payloads are included.

FreeBSD's reporting guidance states that the Security Officer or a delegate will respond after a report is received. That happened for the initial report; the 23 May status request has not yet been answered.

Research approach: follow terminal state and the privilege boundary together

The work did not start with the narrow question of whether TIOCSTI can be called. It started with the more important question: which process group receives terminal input at that moment? The TTY code was reviewed for the caller's relationship to the controlling terminal, read access to the file descriptor, and background-process rules. Those are relevant checks, but they do not by themselves establish the privilege of the foreground consumer.

The review then compared three conditions: whether the terminal belongs to the caller, whether the caller is foreground or background, and the privilege context of the foreground process group. Signal handling in the background-process gate was particularly relevant. This moves the analysis from “is there an ioctl?” to “which privilege level ultimately consumes this input?”

Verification combined source review with controlled behavioural observation in a clean test environment. This publication deliberately omits runnable commands, payloads, and proof-of-concept code: administrators need to audit shared-terminal context and privileged-session practices, not reproduce an exploit.

Scope, confidence, and limitations

The research was verified on FreeBSD 14.4-RELEASE for aarch64. The original report also recorded that the relevant check was absent from the CURRENT source tree examined at disclosure time, at commit 3d246db08333c06df343281d5aaebfd07ea08252 (16 May 2026). That does not claim equivalent operational results across every architecture, nor does it establish the state of upstream code at every later date; operators should verify their running version and current upstream status.

Affected, as verified:

  • FreeBSD 14.4-RELEASE (aarch64) — confirmed via source review and controlled behavioural testing in a clean environment.
  • FreeBSD 16.0-CURRENT at commit 3d246db08333c06df343281d5aaebfd07ea08252 — the relevant check was absent on source review; not independently confirmed via controlled testing on CURRENT.

Not evaluated: other CPU architectures, other supported branches (13.x, stable/14 outside the tested point release), and any point after the 9 June 2026 upstream sysctl change referenced below.

This maps to CWE-863 (Incorrect Authorization) and, more specifically, CWE-284 (Improper Access Control): the kernel validates that the caller owns the terminal object, but never checks the security context of the process that will actually consume the injected input.

The risk is local and depends on a shared TTY context. It is not an unauthenticated network issue. Still, a short sudo-authorisation window, an administrative shell, and an untrusted background process can create a serious combination. Naming these limits is essential for accurate prioritisation and for telling customers exactly what was actually verified.

Technical impact at a high level

TIOCSTI is a legacy TTY interface capable of placing characters in a terminal input queue. In the condition examined by the research, access to the caller's own controlling terminal was checked, while the presence of a more privileged process in the terminal's foreground process group was not separately evaluated.

The relevant check sits in the kernel TTY layer (sys/kern/tty.c), in the ioctl handler that gates TIOCSTI. It confirms the caller holds the device open for reading and that the device is the caller's controlling terminal, but it does not compare the caller's privilege against the privilege of the process group currently in the foreground. Ordinarily, TIOCSTI from a background process is blocked by the standard background-job TTY gate (which raises SIGTTOU); a process that installs SIG_IGN for SIGTTOU is exempted from that gate by design, per POSIX job-control semantics, and reaches the ioctl handler regardless of foreground state. The combination — a background-eligible bypass plus a foreground check that never inspects the target's privilege — is what allows a lower-privileged writer to reach a higher-privileged consumer.

This class of issue matters where ordinary terminal access shares context with a privileged shell or administrative command. Assessments should consider interactive privileged sessions, short-lived sudo credential caching, and workflows that permit untrusted background processes.

Two realistic attack scenarios

Both require only a background process already running in the victim's session — no additional local access beyond what an untrusted or lower-trust process already has, and no network access at all.

Scenario A — interactive privileged shell. When an administrator opens an interactive root shell (for example via su - or sudo -i), that shell becomes the terminal's foreground consumer. A background process that has bypassed the SIGTTOU gate can detect the foreground process-group change and, from that point on, has the same terminal-input channel available to it that the administrator's own keyboard has — for as long as the root shell stays in the foreground.

Scenario B — cached sudo credentials. Most sudo configurations cache authentication for a short window (commonly five minutes) after a successful invocation. The moment a single privileged command finishes and control returns to the user's own shell, that shell — still running as the low-privileged user — sits behind an authentication window that no longer requires a password for a following sudo call. A background process able to detect this transition has an opportunity to act during that window. This path does not require the administrator to ever open an interactive root shell; a single routine sudo invocation is sufficient exposure, which is what makes it the more realistic of the two in day-to-day administration.

Both scenarios rest on the same gap: the kernel treats "is this the caller's own terminal" as sufficient, without asking who will actually read what gets typed. Neither needs social engineering or an existing SUID binary — only a background process already present in the user's session, which is common on shared build hosts, CI runners with local job execution, and multi-tenant development boxes.

Why the foreground process group is security-relevant

A terminal may look like one user's screen, but at kernel level it is an input/output relationship among several processes. Controlling-terminal state describes the caller's relationship with the TTY; it does not identify the consumer of input. The foreground process group is the context that determines which program will read characters delivered to the terminal queue at that moment.

That distinction matters at a privilege boundary. A lower-privileged process can be associated with its own terminal while that terminal's foreground consumer is a more privileged shell or administrative command. A check that answers only “is this your terminal?” can leave unanswered “whose command context will ultimately consume this input?” The design lesson from the research is that ownership of a source object and privilege of the security-relevant consumer are not the same control.

The same review lens can be applied to other local-privilege assessments. For IPC channels, GUI message queues, shared sockets, or job-control mechanisms, the writer's access to an object, the reader's security context, and the timing between them should be evaluated together.

What should a robust fix preserve?

A durable fix should define the policy boundary rather than block one proof-of-concept behaviour. Two defensible approaches are to check that the caller is suitably privileged relative to the foreground consumer, or to offer a system policy that restricts TIOCSTI by default and can be consciously enabled by an administrator. The second approach makes a compatibility-versus-security choice explicit, because legacy applications may depend on the interface.

When evaluating an upstream fix, the test plan should contain more than the negative case. Expected authorised behaviour, terminal emulators, multi-session tools, job control, and varied signal configurations deserve regression coverage. The goal is not to disable a legacy interface blindly; it is to prevent a lower-privileged writer from influencing a higher-privileged consumer while preserving legitimate workflows where feasible.

Operational visibility and incident review

Defenders should not expect one perfect log line for this risk. They should inventory where privileged interactive sessions are used, on which hosts sudo activity is concentrated, how user processes are launched within the same PTY, and whether untrusted software can coexist with those sessions. Where endpoint telemetry exists, unexpected TTY ioctl activity, newly created background processes, and the timing of privileged commands can be assessed together.

During a suspected event, the objective is not to replay the research scenario. It is to quickly contain the affected session and identities: preserve relevant user and host context, review privileged credentials, retain operational records, and assess reuse risk in other sessions. This keeps incident response technically sound without turning the publication into an exploitation recipe.

Actual impact depends on the FreeBSD version, terminal topology, local process controls, sudo policy, and each organisation's privileged-operation procedures.

Current upstream status: verify your version

The current FreeBSD source-tree log lists changes dated 9 June 2026 that add a sysctl control to globally disable TIOCSTI and then rename it to security.bsd.allow_tiocsti.

This is material mitigation information at the time of publication. This post does not claim that the upstream change is attributed to this report, nor that it was backported to every supported release. Administrators should verify the availability, default, and active value of the control in their own branch, release notes, and source tree.

  • Use separate PTY sessions for privileged work rather than sharing terminal context with untrusted processes.
  • Review sudo credential caching and interactive administration workflows against your organisation's policy.
  • Apply least privilege to local process execution, particularly on shared development and administration systems.
  • Verify whether the TIOCSTI global-disable control exists and is active on the FreeBSD branch you operate.
  • Include terminal-related privilege events in monitoring and incident-response records.

Evidence-led control with Eresus Guard

Eresus Guard brings DAST, SAST, SCA, IaC, and secrets assessments into an evidence-led workflow. Teams can connect affected assets, configuration and privilege checks, remediation decisions, and revalidation evidence in one reviewable record.

The objective is not merely to mark a finding closed. It is to preserve which terminal, identity, and privilege assumptions were verified, on which version, and with which configuration. Explore the Eresus Guard workspace or plan a scoping call.

Prioritisation: which systems should be reviewed first?

Not every FreeBSD host has the same exposure. Prioritisation should consider how terminal access is used, not only the installed version. Shared bastion hosts, build systems used by multiple developers, administration servers where operators routinely use sudo, and jump hosts with production access deserve early review.

Assess three signals together:

  1. Can an untrusted or lower-trust process run in the same user session?
  2. Do administrators perform privileged work through an interactive terminal?
  3. Is the current TIOCSTI mitigation present and active in the FreeBSD branch in use?

When two of these answers are yes, the host should receive configuration verification and workflow isolation ahead of a routine patch-only response.

A 48-hour defensive validation plan

On day one, map the version inventory to terminal workflows: document which teams access which hosts over SSH, how sudo is used, and where shared-session tooling is present. On day two, verify the availability and active value of the relevant sysctl mitigation for the deployed branch. Then consider controls such as separate PTYs for privileged work, shorter credential-caching windows, and additional operational approval where appropriate.

The goal is not to reproduce a sensitive attack path. It is to establish which processes can share a terminal context and which controls demonstrably protect that boundary. The resulting record should name affected hosts, ownership, version, verified controls, and a closure date.

Frequently asked questions

Does this concern only teams that use a root shell?

No. The risk depends on a lower-privileged process sharing terminal context with an interactive privileged process. Sudo-based administration, privileged commands, and shared management hosts should also be reviewed.

Is disabling sudo credential caching enough by itself?

It can reduce risk in particular workflows, but it should be considered alongside terminal isolation, version and configuration verification, and least privilege. One setting is not a universal solution.

What does Eresus Guard add in practice?

Guard helps preserve the inventory, configuration evidence, accountable team, remediation decision, and revalidation record in one workflow. "Checked" becomes a closure record supported by a version and reviewable evidence.

Sources

Security Validation

Have you tested this risk in your own system?

Eresus Security delivers real exploit evidence through penetration testing, AI agent security, and red team operations.

Request a pilot test

Related Services