#1037·navi

Cheatsheet variable interpolation substitutes selected values into commands with no shell escaping, allowing injection via suggestion output

Author: carfeiiCreated Aug 6, 2026Updated Aug 6, 2026

Summary

replace_variables_from_snippet (src/commands/core/actor.rs) splices a selected variable's value directly into a snippet's command template via plain string replacement (replacen), with no shell escaping. The resulting string is then executed as <shell> -c <string> (src/common/shell.rs out(), invoked from act in the same file). A variable's value can come from a suggestion command declared in the cheatsheet (a common, documented navi feature, e.g. $ file: ls), and since file names on Linux impose essentially no character restriction, a suggestion list built from file names can present the user with a value that looks like an ordinary item to pick while containing shell metacharacters. Selecting it injects those characters into the command that runs.

Validated against the master branch tip (commit f7330b9).

POC

(available upon request)

Impact

I validated this by creating a minimal custom cheatsheet with a $ file: ls <dir>-style suggestion, placing a file whose name was a shell-metacharacter payload (x; touch navi_injection_poc; echo x) in that directory, and driving navi interactively through selecting the snippet and then that file suggestion. The output showed two separate echo results rather than one line containing the full filename, and a marker file created by the injected touch command was present afterward, confirming full command execution, not just argument injection.

Suggested Fix

Quote the resolved variable value appropriately for the target shell (e.g. wrap in single quotes, escaping embedded single quotes) at the point of substitution in replace_variables_from_snippet, rather than splicing it into the command string as raw text.