Pre-create become file with O_EXCL
CodeQL / Analyze (go) (push) Has been cancelled
build / build (push) Has been cancelled
Test fzf on macOS / build (push) Has been cancelled

Prevents another user on a shared TMPDIR from planting a file or a
symbolic link at the predictable path while fzf is running, like the
exit status file of the floating pane. Reject an empty become command.
This commit is contained in:
Junegunn Choi
2026-07-05 20:15:05 +09:00
parent eee92b1b2a
commit f7392a8b63
2 changed files with 20 additions and 3 deletions
+13 -3
View File
@@ -138,6 +138,17 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool)
temp := WriteTemporaryFile(append(exports, command), "\n")
defer os.Remove(temp)
// Pre-create the become file so that another user on a shared TMPDIR
// cannot plant a file or a symbolic link at the predictable path while
// fzf is running
becomeFile := temp + becomeSuffix
becomeF, err := os.OpenFile(becomeFile, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
if err != nil {
return ExitError, err
}
becomeF.Close()
defer os.Remove(becomeFile)
cmd, err := cmdBuilder(temp, needBash)
if err != nil {
return ExitError, err
@@ -155,16 +166,15 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool)
if exitError, ok := err.(*exec.ExitError); ok {
code := exitError.ExitCode()
if code == ExitBecome {
becomeFile := temp + becomeSuffix
data, err := os.ReadFile(becomeFile)
os.Remove(becomeFile)
if err != nil {
return ExitError, err
}
elems := strings.Split(string(data), "\x00")
if len(elems) < 1 {
if len(data) == 0 {
return ExitError, errors.New("invalid become command")
}
elems := strings.Split(string(data), "\x00")
command := elems[0]
env := []string{}
if len(elems) > 1 {
+7
View File
@@ -48,6 +48,13 @@ class TestTmux < TestInteractive
assert_equal '1', fzf_output
end
def test_floating_pane_become
tmux.send_keys "seq 100 | #{fzf(%(--popup center,80% --margin 0 --bind 'enter:become(echo became-{})'))}", :Enter
tmux.until { |lines| assert_equal 100, lines.item_count }
tmux.send_keys :Enter
assert_equal 'became-1', fzf_output
end
def test_explicit_border_falls_back_to_popup
# display-popup requires an attached client, which the test environment
# may not have; intercept it with a tmux shim on PATH