CVE Patch Review

CVE-2026-54088: Root-Cause Fix for File Browser Hook Authentication RCE

CVE-2026-54088 · GHSA-M93H-4HW7-5QCM · Updated 2026-07-11 Root-cause

Summary

The vulnerability stems from interpolating unauthenticated username and password values into hook command arguments before execution. The patch removes credential-to-command-string substitution and adds regression tests proving credentials are only delivered via environment variables, which addresses the command injection primitive at its source.

Analysis

Vulnerability

CVE-2026-54088 is a pre-authentication remote code execution issue in File Browser's Hook Authentication flow. According to the advisory context in GHSA-M93H-4HW7-5QCM and the CVE records at CVE.org and NVD, unauthenticated attacker-controlled username and password inputs could reach hook execution unsafely.

The vulnerable logic in auth/hook.go expanded command arguments using an environment mapping that directly substituted USERNAME and PASSWORD with request-supplied credential values. That means attacker input was transformed into command argument text before process execution, creating a command/argument injection path consistent with CWE-78/CWE-88.

envMapping := func(key string) string {
		switch key {
		case "USERNAME":
			return a.Cred.Username
		case "PASSWORD":
			return a.Cred.Password
		default:
			return os.Getenv(key)
		}
	}
	for i, arg := range command {
		if i == 0 {
			continue
		}
		command[i] = os.Expand(arg, envMapping)
	}

This is especially dangerous in a hook-auth design because the login endpoint is reachable before authentication, so the attacker controls the credential fields at the exact point where the server prepares the hook command.

Patch

The official patch is the File Browser commit 34ae34e764d72540c039f1f5ea2ec4c974168c1f. The supplied diff summary shows the key remediation through new regression tests in auth/hook_test.go. Those tests define the intended security contract: credentials must never be interpolated into the command string and must only be exposed to the hook via environment variables.

The first test, TestRunCommandNoCredentialInjection, uses payloads such as "; touch ...; # and $(touch ...) and verifies that no marker file is created. This directly exercises the prior exploit primitive and confirms that shell-significant credential content no longer reaches executable command text.

a := &HookAuth{
	Command: script,
	Cred: hookCred{
		Username: `"; touch ` + marker + `; #`,
		Password: `$(touch ` + marker + `)`,
	},
}

The second test, TestRunCommandReceivesCredentialsViaEnv, verifies functional compatibility by asserting that hooks still receive USERNAME and PASSWORD through the environment and can authenticate based on those values.

Although the provided patch excerpt does not include the full post-fix auth/hook.go body, the tests and commit intent strongly indicate that the credential-driven os.Expand substitution path was removed or constrained so that credentials are no longer copied into command arguments. That is the correct security boundary for this feature.

Review

Pros

  • The patch targets the actual injection boundary: attacker-controlled credentials being expanded into command arguments.
  • The regression test is exploit-oriented rather than purely structural, which is valuable for preventing reintroduction of the bug.
  • The tests preserve the supported behavior by validating environment-variable delivery of credentials, reducing the risk of breaking legitimate hook integrations.
  • The fix aligns with least-surprise process execution semantics: untrusted data should be passed as data, not merged into executable command text.
  • The patch is grounded in the official remediation artifacts: the commit 34ae34e764d72540c039f1f5ea2ec4c974168c1f and advisory GHSA-M93H-4HW7-5QCM.

Cons

  • The supplied patch excerpt does not show the exact replacement implementation in auth/hook.go, so review confidence depends partly on test intent and commit metadata rather than a full visible code delta.
  • The tests are POSIX-only and skipped on Windows, leaving platform-specific command construction behavior less directly covered.
  • If the broader hook execution path still permits shell invocation from administrator-supplied hook commands, there remains residual risk from unsafe deployment configuration, even though credential injection is fixed.
  • The regression scope is focused on username/password interpolation; additional tests for other environment-derived placeholders or unusual argument parsing edge cases would further strengthen assurance.

Verdict

Root-cause.

This patch appears to remediate the vulnerability at the correct layer by eliminating the unsafe transformation of unauthenticated credential input into command argument text. Instead of attempting to filter metacharacters or blacklist payload forms, it restores a safer contract where credentials are passed only via environment variables. That directly removes the pre-auth command injection primitive described by NVD and CVE.org.

For engineering teams, the main follow-up is to verify the final RunCommand implementation never reintroduces string interpolation of untrusted values into executable command components, and to consider adding Windows coverage plus negative tests around any remaining variable expansion behavior. Based on the available patch evidence, however, the fix is substantive and not merely a bandaid.

Sources