elves / elvish

Powerful scripting language & versatile interactive shell
https://elv.sh/
BSD 2-Clause "Simplified" License
5.65k stars 299 forks source link

More explicit mechanism to leave command out of history #524

Open notramo opened 6 years ago

notramo commented 6 years ago

I would like to see that Elvish has an incognito mode. I mean not saving command/dir history under incognito mode. E.g. some programs require to pass them passwords in the command line, and it is bad if these commands are saved to history.

xiaq commented 6 years ago

You can prepend a space to the command to prevent it from going into the history, but there is no analog in dir history. An "incognito mode" sounds good.

krader1961 commented 4 years ago

I have never liked the "prepend a space to a command" idiom used by legacy POSIX shells to keep the command from being persisted to the command history. It is too easy to use mistakenly and too hard to discover by new users. I would much prefer an explicit incognito mode that deals with commands, directory changes, and anything else considered sensitive. The question, it seems to me, is whether this should be something that can be toggled or should require running elvish with an option that enables icognito mode. Similar to how web browsers like Chrome operate. I favor the latter approach. That is having to do something like elvish -incognito. Possibly removing the command space prefix hack.

iwoloschin commented 4 years ago

There should be a variable that shows if incognito mode is active, it'd be very useful for prompts to display mode.

krader1961 commented 2 years ago

There should be a variable that shows if incognito mode is active, it'd be very useful for prompts to display mode.

Not only that but we now have several examples of variables that can be queried but also modify Elvish behavior when assigned to; e.g., https://elv.sh/ref/unix.html#unix:rlimits and https://elv.sh/ref/unix.html#unix:umask. An edit:incognito variable could function in a similar fashion. It would default to false but you could do set edit:incognito = $true to enable incognito mode. Something you could wrap in a function or abbreviation if you used it a lot and wanted something shorter to type when enabling/disabling incognito mode. Personally, I would prefer such a mechanism because it would be easier to discover by new users and less likely to result in surprising behavior if a user accidentally begins a command line with a space.

P.S., Is the leading space to keep a command from being appended to the history actually documented? I tried really hard to find such documentation and failed. Which sort of makes my point even if it is documented it is hard to discover. And if it isn't documented I don't see an obvious way to document it in a manner that makes it easy to discover. It's also notable that Bash, by default, does not recognize a leading space as special. You have to HISTCONTROL=ignorespace. So apparently the Bash maintainers also concluded that "don't record commands with a leading space" is not desirable by default.

krader1961 commented 2 years ago

I also tested the Korn shell (the /bin/ksh provided by macOS) and it does not support the space prefix behavior AFAICT. Which surprised me since I thought it did support that behavior when I used ksh more than two decades ago.

krader1961 commented 2 years ago

After sleeping on this issue I wonder if we really need an incognito mode or the current, undocumented, leading space behavior. Now that the XDG vars are honored, including on Windows, why not just require the user to set $E:XDG_STATE_HOME to a directory that either does not contain an Elvish history database or one that only contains info they want leaked when performing a demo?

Note that there are two use cases for this type of feature. One use case is performing demonstrations where you don't want to risk exposing your personal history. That is best addressed by requiring the user to set $E:XDG_STATE_HOME as described above.

The other use case is keeping commands that contain sensitive info (e.g., passwords) from being recorded in your personal history. The Bash shell handles that use case via the HISTIGNORE variable or setting HISTCONTROL to ignorespace (or both). I don't think that use case is something we need to, or should, support for several reasons. First, your Elvish history shouldn't be stored on media (e.g., Dropbox or Google Drive) that you don't control. Second, you shouldn't be putting sensitive info (e.g., passwords) in your commands. That info should be passed via env vars or similar mechanisms. That has been true since UNIX was created (i.e., at least four decades). Third, expecting the user to always preface the command containing sensitive info with a space to keep it from being recorded is fragile. As is expecting the user to appropriately configure HISTIGNORE. Both mechanisms are so flawed from a security perspective as to be borderline pointless. You have to keep your shell history on systems you control and trust to be secure. Unless, of course, you never do something unsafe like embedding a literal password in a command line. And even without such blatant security exposures there is other sensitive information in your command, and directory, history that you don't want random strangers to be able to read. You have to treat your entire shell history like any other security sensitive information. The Bash "ignorespace" mechanism is a half-assed solution that is borderline pointless.

@notramo: I'm curious what you think about my arguments for not only not implementing an "incognito mode" but also removing the current "don't record commands that begin with leading space" behavior.

krader1961 commented 7 months ago

I was looking at the Fish code for manipulating command history (to see how to use its approach for storing command history in a flat file to replace BoltDB and the associated Elvish daemon) and noticed it has a fish_private_mode variable to control whether global history is read or persisted too. That variable (and related shell CLI options) didn't exist when I switched from Fish to Elvish. After this issue was opened the $edit:add-cmd-filters var was introduced with a default filter that keeps code blocks that begin with whitespace from being saved. But does not keep global history from being visible. The current behavior also keeps those code blocks from being added to the local shell history. Which I consider a mistake. Those filters should only affect which code blocks are persisted to the global history -- not the shell's local (private) history.

I no longer think that something like the aforementioned Fish shell variable/CLI options should be added. The "demo" mode use case can be handled by setting $edit:add-cmd-filters to a function that always returns $false and modifying the history management to only apply that filter to whether the code block should be persisted to the global store rather than the local, private, history. Along with making it easy for a user to use an alternative global history on startup.

The more general case of someone not wanting code blocks that contain security sensitive data being written to their global shell history file can add appropriate filters to the $edit:add-cmd-filters var.