Medium firefox Sandbox Escape 🔧 Commit mapped

Overview

Medium
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionInformation disclosure, sandbox escape in the Security: Process Sandboxing component
ComponentSecurity/NSS
Bug ClassSandbox Escape
Tracker2040477
Fix commit6ae73931343c (firefox) +9/-1
CISA KEVNot listed
Creditedevyatar
Disclosed2026-06-16

Background

`SandboxBroker`
Gecko’s privileged Linux broker process that mediates filesystem requests from sandboxed content processes against a path Policy.
`SandboxBroker::SymlinkPath`
a realpath(3)-derived routine that canonicalizes a requested path, resolving symlinks and computing the effective permissions.
Path traversal
using .. components in a path to reference directories above an intended root, escaping the confinement the policy assumes.
`Policy`
the per-process allowlist mapping canonical path prefixes to granted access perms.

Root Cause Analysis

The vulnerable code path is SandboxBroker::SymlinkPath in SandboxBrokerRealpath.cpp, which resolved a content-process-supplied path before matching it against the broker’s Policy. The routine’s invariant is that the resolved path it returns is fully canonical and stays within the paths the Policy grants, but its symlink/component walk did not reliably neutralize .. segments, so a crafted path containing /../ (or one equal to, starting with, or ending in ..) could be steered outside the intended subtree while still passing the subsequent permission check.

The fix adds an early guard that computes path_len and rejects any path matching those four .. patterns with errno = EPERM before resolution begins. This works because refusing to resolve any path bearing a traversal component removes the attacker’s ability to construct a canonical result that lands outside the allowed prefix, forcing such requests to fail closed rather than be brokered.

Key insight
The single core mistake was trusting SymlinkPath to canonicalize away .. traversal components before the Policy check, when it could instead produce an out-of-bounds path; the fix rejects ..-bearing inputs outright with EPERM so no traversal request is ever resolved or authorized.

Attack Path

  1. Compromise or drive a content process The attacker obtains code execution (or attacker-controlled path input) inside a sandboxed process that issues brokered filesystem requests.
  2. Craft a traversal path The attacker submits a path containing a /../ component (or one that is .., begins with ../, or ends with /..) to the broker.
  3. Bypass canonicalization SandboxBroker::SymlinkPath resolves the path such that the .. steers the result outside the subtree the Policy intended to allow.
  4. Pass the policy check The resolved path matches an allowed prefix, so the broker grants access and performs the operation on a file outside sandbox confinement.
  5. Read or act on restricted files The attacker leverages the brokered access to disclose information or widen its foothold, weakening the sandbox boundary.

Impact Assessment

An attacker with control over a sandboxed content process gains the ability to reach files outside its intended policy subtree via .. traversal in brokered path requests, yielding information disclosure and a step toward sandbox escape. This occurs in the privileged broker’s evaluation of content-process requests on Linux. The precondition is attacker-controlled path input reaching SandboxBroker::SymlinkPath, typically from a compromised or coerced content process.

Changed Functions

FunctionChangeNotes
if
security/sandbox/linux/broker/SandboxBrokerRealpath.cpp
modified

Files Changed

  • security/sandbox/linux/broker/SandboxBrokerRealpath.cpp

Audit Directions

  • Traversal-before-canonicalization
    Audit every broker or IPC path handler that matches a policy against a path it canonicalizes; verify .. components are neutralized or rejected before, not after, the authorization decision.
  • Fail-open resolution
    Review realpath-style routines ported into privileged code for edge cases where malformed or relative inputs yield a usable path instead of an error, and confirm they fail closed.
  • Untrusted path inputs
    Trace all content-process-supplied strings that reach SandboxBroker and confirm each is validated at the trust boundary rather than assumed canonical.
diff --git a/security/sandbox/linux/broker/SandboxBrokerRealpath.cpp b/security/sandbox/linux/broker/SandboxBrokerRealpath.cpp
index 04de4a56cc4..a5195672b78 100644
--- a/security/sandbox/linux/broker/SandboxBrokerRealpath.cpp
+++ b/security/sandbox/linux/broker/SandboxBrokerRealpath.cpp
@@ -45,6 +45,7 @@ static char sccsid[] = "@(#)realpath.c	8.1 (Berkeley) 2/16/94";
 
 #include "base/string_util.h"
 #include "SandboxBroker.h"
+#include "SandboxLogging.h"
 
 // Original copy in, but not usable from here:
 // toolkit/crashreporter/google-breakpad/src/common/linux/linux_libc_support.cc
@@ -74,7 +75,7 @@ char* SandboxBroker::SymlinkPath(const Policy* policy,
                                  char* __restrict resolved, int* perms) {
   struct stat sb;
   char *p, *q, *s;
-  size_t left_len, resolved_len, backup_allowed;
+  size_t left_len, resolved_len, backup_allowed, path_len;
   unsigned symlinks;
   int m, slen;
   char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
@@ -90,6 +91,13 @@ char* SandboxBroker::SymlinkPath(const Policy* policy,
     errno = ENOENT;
     return (nullptr);
   }
+  path_len = strlen(path);
+  if (strstr(path, "/../") || strcmp(path, "..") == 0 ||
+      strncmp(path, "../", 3) == 0 ||
+      (path_len >= 3 && strcmp(path + path_len - 3, "/..") == 0)) {
+    errno = EPERM;
+    return (nullptr);
+  }
   if (resolved == nullptr) {
     resolved = (char*)malloc(PATH_MAX);
     if (resolved == nullptr) return (nullptr);
Loading diff…