This seems to be more of "don't paste garbage into a terminal, especially as root." With a sidenote that it might be safer if your custom application command interpreter didn't use > as the prompt character. I note that Bourne shell defaults to the safer % and # characters for the prompt. The # character for root is especially safe.
Yeah. About the only relevant bit is that root prompts tend to use # as part of their prompt precisely to inject a comment character in case of mis-quotes/pastes.
I've heard this story before, but I don't think it's true.
I think the bourne shell copied # comments from csh, which had them first. When sh first implemented them, # comments only worked in scripts, not if you typed them at the shell (i.e. if isatty(0), then # wasn't special). The fact that the prompt came before comments, and that comments didn't work interactively really makes the story sound suspect!
I don't know the origin of # in csh, but I would guess it was chosen because it looks like a CPP directive.
Hmm, wasn't # the default erase character for teletype-era Unix? And @ the "kill" character (like modern ^U)? That would have made them a little annoying to type—not annoying enough to keep them from being used for cpp, though, and https://github.com/memnoth/unix-v6/blob/master/sys/dmr/tty.c... suggests that you could type \#. (There was no "lnext" yet; it was just hardcoded to backslash.)
That's a fair point. But in the 90s as a System V and SunOS user, I saw some discussions happen on Usenet, and by the time X was commonplace, the myth/rationale was commonplace.
Even then, though, that was over a decade after the fact, and people were inventing explanations for things retroactively. Doug McIlroy has put the kibosh on this myth.
I don't have reference for that but I always though that CPP directives are preceded by # because the character was previously used as comment delimiter by something (probably csh). In the grand scheme of things cpp is somewhat modern invention. IIRC the first book on Unix programming I had read mentioned in passing that cpp exists but the C code examples in there did not #include anything and if some declaration was required it was just written verbatim in the example code.
Even if # isn't / wasn't special, it's still exceedingly unlikely to be a valid program name, nor is it likely for a valid program name to begin with #. The practical effect should be the same as it having been special.
Potentially, but I can pretty much guarantee that someone working on any shell has run into this problem before, and then decided not to change the # because it was so damned convenient for preventing mispastes.
While it doesn't apply to shell prompts, there are such things as cultural memory and institutional memory. As a member of a group or society, you are expected to have a certain baseline amount of knowledge of that culture and history.
When I was young, it was considered shameful not to know things. Now the people I work with seem to wear ignorance as a badge of pride. They think that not knowing something means that thing is not worth knowing. As if somehow not knowing something is a good thing.
> Now the people I work with seem to wear ignorance as a badge of pride. They think that not knowing something means that thing is not worth knowing. As if somehow not knowing something is a good thing.
That may be the case, due to attitudes encouraged by pop culture, etc. but it's a disastrously incorrect understanding of the comic (and parent comment). They're celebrating learning, which is the exact opposite of 'wearing ignorance as a badge of pride'.
> When I was young, it was considered shameful not to know things.
Shaming something discourages people from admitting it. A child who's ashamed to ask questions will not learn as effectively. They may learn to avoid admitting their ignorance, but that may cause problems later (struggling alone rather than asking for help, possibly leading to damage or injury, etc.).
> there are such things as cultural memory and institutional memory. As a member of a group or society, you are expected to have a certain baseline amount of knowledge of that culture and history.
How do you think the members of those groups have that knowledge? We have not (yet) evolved a genetic predisposition to grow, in utero, neuronal bundles encoding Unix shell prompt escape sequences. That's the point; everyone has all need to learn!
Still, it's better to air and discuss such takeaways!
There’s a huge gulf between admitting you don’t know something, and being proud of it.
Suggesting it was ever, or should be, somehow “shameful” to admit not knowing something, is an enemy of change and growth, and in everyday life becomes a recipe for perpetuating structural in-groups and all the systemic pathologies that go along with them.
I am also grumpy old fart but I was raised in an engineering culture that was not afraid to ask “what’s a spline?”, and I don’t regret it.
Welcome to the world of the Cult of Abstraction. I've never understood the fascination with not knowing what lurks beneath... I've just kind of grown used to it though, and have gotten used to solving the problems everyone else throws their hands in the air over for not knowing how to get deeper.
I mean, I get it in some cases; you don't need to know how things work to use them, but when things go wrong, and they always do, that's when knowing how it works (and not just how to use it) pays off.
Plus, you can articulate questions about things you don't know more effectively.
I want to curmudgeonly respond that you’re selling people short. But honestly I’m gonna repeat the theme of the comic.
You’re today’s lucky one, you get to learn something new! People shelter themselves with the familiar all the time. You have too! You started your explanation of your perspective with “when I was young”, and that’s obviously something you’ve held onto.
I’m gonna make your day. Did you know that people, in your life or waiting in the wings, are gonna be grateful for the things you can show them? The only thing you need to do is be just thrilled to introduce it, whatever it is, even if they don’t have the thrill yet.
You just gotta get enough in tune emotionally to know what they’re gonna want to know and how to tell them. That’s a fun new exploration all for you.
>As a member of a group or society, you are expected to have a certain baseline amount of knowledge of that culture and history.
How is it possible to become a member of the group or society except by hanging out with existing members and learning from them?
>Now the people I work with seem to wear ignorance as a badge of pride. They think that not knowing something means that thing is not worth knowing. As if somehow not knowing something is a good thing.
That comic is saying almost the opposite of that. The comic says that gaining knowledge is a good thing and should be celebrated.
That implies you should put a space before the # in the root prompt, because it's not recognized as a comment delimiter if it's in the middle of a "word".
Yep (author here), not pasting garbage into a terminal is the main point of this article. Partially, it's a rant against the way-too-trigger-happy "paste clipboard on right mouse click" terminals too.
I decided to finally write this article, after seeing a yet another "mysterious" case of a missing binary in some Oracle database server. Linux/Bash defaults are ok, but historically (coming from traditional Unix background?), people who engineer environments at least in the Oracle database server world, configure their prompts to some "corporate standard". And sometimes they end up suffixing prompts by a nice-looking ">" character, leading to this problem.
I've also seen someone set their root prompt to `root#>`. Since there's no space between the username and #, the "comment start" is not recognized and the redirection clobbering problem is still there.
I was musing over IPython's behavior right before reading your comment... it's not a terminal, per se, but if you paste in multiple lines, the input switches into a multiline mode. This suggests that bash could handle it in the same manner without relying on a terminal application.
In my experience, the advice "don't paste garbage into your terminal" is about as useful as "don't make mistakes." Sometimes it happens when I forget to hit shift on copying from a terminal, or accidentally holding it while copying from another window. Humans make mistakes. I like seatbelts even though they've never saved my life.
In iTerm, Edit -> Paste Special -> Warn Before Multi-Line Paste will disable it if you don't like it. It's probably better to disable it in zsh, but I don't know how to do that. iTerm also provides the "only pop up this warning when I'm at a shell prompt", which is ironically exactly when I don't want it to pop up (since zsh/fish detect it themselves).
Using "unset zle_bracketed_paste" should do what you want, but I've only tried it in rxvt-unicode and the vte-based term I have. It stops zsh reacting to the escape sequences used by multi-line paste, see the docs for a full explanation¹.
If you were to use I'd recommend sticking it behind a "if $TERM" guard so that it you don't end up surprised if you switch to a term that doesn't warn at some point ;)
Well, how about making it hard to do accidental input in the first place? If pasting is a problem the maybe make the actions necessary less possible to be triggered randomly?
Also don’t shell script on the fly in a production server that has data of any sort you can’t restore from a backup. It’s one giant game of Russian roulette and eventually the human is going to screw up
I feel a better takeaway is "people are sometimes going to mess up, if you can do something easy to make those mess-ups less serious, it's probably worthwhile."
Yeah this feels like more of a cautionary tale about proper privilege and directory management.
Was there really a reason for OP to be inside the binary directory for the application in order to use it?
Why was the binary writeable in the first place?
If the binary was not normally writeable but the user was privileged, was it necessary to use a privileged user for this operation?
You could probably create a pretty extensive list of failures that led to this issue. I think the author honed in on the one that made the most sense to himself and missed the forest for the tree.
So if someone grabs your hair during a fight, are you going to go bald the rest of your life? Just paste it somewhere besides a terminal. I swear, security people have run away with everyone's good sense.
There's a point of diminishing returns where running with something that can cause a problem is completely practicable and justifiable. We don't need the nteenth "Shell that protects you from malicious paste" functionality. Just use root judiciously. If you can't be comfortable running as root and keeping yourself out of trouble, then you really don't know enough to use the machine safely.
You must be 10% smarter than the piece of equipment. No amount of good natured or well-intentioned "protect you from yourself" coding will obviate you of the need to know what you are doing, the limitations of the machine, and the limitations of the program you're using. In fact, all it does is increase the bar for how many things worth of minutiae you have to account for.
Bash, via GNU Readline, has an option that sidesteps this issue:
enable-bracketed-paste (On)
When set to On, readline will configure the terminal in a way
that will enable it to insert each paste into the editing buf‐
fer as a single string of characters, instead of treating each
character as if it had been read from the keyboard. This can
prevent pasted characters from being interpreted as editing
commands.
Effectively it means that even if you paste garbage into the terminal you still have to hit enter before the command is interpreted.
This works great in combination with another advanced feature, "edit command" or "edit and execute command". Once you've pasted a command into the terminal, even a multiline command with safe paste, you can have the shell open your $EDITOR to edit the command, and automatically put the result right back into the shell (or just run it). This is available in Bash by default as ctrl-x ctrl-e.
(And as someone else pointed out below, if you don't want to enable safe paste, you can open the editor first on a blank command line and paste into that. But really we should all enable safe paste.)
Thank you, I think I've accidentally activated this mode without knowing _or wanting_ it when muscle memory for copy/paste happens while using a windows workstation but E.G. putty. Now I know it's a mode and that ctrl-e can undo it.
This won’t help for the kind of clueless blind-paste people who run into this issue in the first place - they don’t know what they are doing, is the actual problem. They’ll just paste whatever, hit enter, and then ask for support because nothing works :)
The classic copy-pasteable prompt (for true graybeards) is simply
PS1='; '
If you want some more information, the trick is this:
PS1=': stuff ; '
where "stuff" is whatever string you want to show (without redirection characters). This works because the colon is the "true" executable that ignores all its arguments, and the semicolon introduces your command that can thus be pasted along the whole line.
The ";" prompt was specific the "es" and "rc" shells, and not really used with any other more common ones, so most graybeards wouldn't have used that as PS1. Also, to be a graybeard and have copy/paste, you're talking about a very expensive computer with a mouse, like a Sun workstation. And all of those csh users from the late 1980s couldn't have, since it would cause a syntax error :-)
I remember independently inventing the ": foo;" prompt, and using it with Bash, in the late 90s. My beard is gray now.
It's not really practical because there are all sorts of values of "foo" which will make Bash choke when it tries to evaluate the string. Backticks and parentheses, for example, will cause problems, as will newlines (which NB may even occur in filenames, along with other problematic characters!). So the "foo" string typically needs to be sanitized using an external command: https://tldp.org/HOWTO/Bash-Prompt-HOWTO/x279.html
Once you get to that point the idea no longer seems as elegant.
Subtle greybeard update: ` :>/some/file ` still evaluates in shell, it will zero out a file (truncate) quick and dirty - the emphasis in enriquto's comment is still very important, do not include redirection chars.
Parent's point was that starting your prompt with `:` isn't a guarantee that everything that follows is safe (to expand on the "without redirection characters" remark by the OP).
A variant of this has been my PS1 since the 90s (yes, mostly on workstations with a GUI by then [Sun,NeXT,HPUX etc...]). Unfortunately bash doesn't like a lone ';' without something before it ("-bash: syntax error near unexpected token `;'") so I've had to use ':; ' with it (I like its use of readline, emacs user since Gosling's in the early 80s).
Triple-click, middle-click (for xterm and others that do that) is efficient and easy. The csh-inspired '!!' can work nicely too though.
I guess the most important message isn't even "don't paste things into the terminal". It's "don't use a terminal that pastes things automatically, or by some action you will do by mistake".
Or, more specifically, don't ever use the default behavior of putty in a laptop with a trackpad and a gesture enabled for left click. If you use putty, set copy and paste to something less random.
Tip for Vi/Vim users: to exit without having the command run, exit the editor with failure; the command for that is is :cq in Vim. (Also works fine in git to cancel commits etc.)
Fun trivia: this is the default character in the SUSE /etc/bash.bashrc prompt for the non-root user. There's a lot of code doing things, but it boils down to this one example of their prompt defaults:
if test "$UID" = 0 ; then
PS1="${HOST}:${PWD} # "
else
PS1="${USER}@${HOST}:${PWD}> "
fi
When I moved from DOS to Unix, I quickly got used to the default prompt of "$" instead of DOS’s default ">". Whenever I see ">" in someone’s custom prompt I assume they are DOS or Windows people who couldn’t get used to change when they started using Unix-like systems.
(This is how normal DOS and Unix command prompts looked, for reference:)
Makes sense, but weirdly I did not follow that route. I started on Unix, then learned about DOS, did not use it much, but I did switch my Unix prompt to use '> ', because I liked it better. The default '$' has too much visual clutter for me. BUT, when I post snippets of shell commands on the web, I use '$ ' because most people are familiar with it.
No. That's what DOS prompts looked like for people who knew how to alter them from the default, or who used quite late versions of DOS. The default prompt in COMMAND was $n$g not $p$g .
If you hit Control-X-E it will open whatever is set as $EDITOR in a temporary session you can paste your command in to. I'd recommend vim. You can even use vim to edit your command. Once you save and quit your command will be run.
The article mentions this but not the ^X^E shortcut.
- Make important files writable by root only. If regular users should not modify it, don't allow it
- And... yes, don't allow any special characters in your prompt for "paste random stuff in my shell and run it" ppl. To be honest, I'd even lock those ppl out of the system. You could insert an invisible, uncommon char in the default prompt, detect it, and log the user out (after sending you an email ;-))
It happens with automation running as root too even with sudo. Some automation will always have to run as root. Bad characters, unset variables, lack of tests in the script, lack of testing of the automation, lack of chaos testing. The most common clobbering of data I have seen was not so much even copy/pasting, but rather a lack of
set -u
set -e
set -o pipefail
set -o posix
in scripts used by automation. There is shorthand for this that I am intentionally leaving out. Every shell script used in automation should at least have set -u to avoid running if variables are unset. An entertaining example was:
rm -Rf ${MYSQL_HOME}/bin
There are a couple problems with that line, but in this case they did not source their environment file correctly and wiped /bin on many servers.
I solved this problem in my own shell by checking the chunk of data being read from STDIN before automatically passing it from readline to the parser. If it contains multiple newlines then odds are it is pasted content so the shell prompts you with a warning that you're pasting multiline content. It even gives you an option of previewing the data you're pasting before running it in the shell.
I'm surprised more shells haven't adopted this approach because it was trivial to set up and almost never gets in the way except when you actually want it to. But I guess it couldn't be Bash or Zsh because odds are someone somewhere depends on Bash blindly accepting readline data as part of their production workflow: https://xkcd.com/1172/
In fish shell, with bob-the-fish theme[1] and powerline fonts, my prompt ends in ``. Gives a nice appearance, and definitely isn't a valid redirect.
Of course anyone who does manage to paste and execute code as root (or with sudo in the line) in a terminal without sanitizing it is careless, as long as their terminal doesn't have the stupid right-click-paste behavior. If it does, I agree with the author that it's just a bad terminal.
I wonder if anybody has modified their browser fonts with the powerline characters and can actually see the character you've written here. If those people are anywhere it'd be here. :)
Weirdly, my Firefox displays it in the page as the Unicode box (E0B0), but if I right click and "Inspect Element", it shows the arrow character as it should be, as part of the span tag's content text.
I felt smug in the knowledge that I use Emacs shell-mode, which treats the terminal as an editable text buffer and allows newlines to be copy/pasted, without executing anything until an explicit press of Return.
Then I remembered that shell-mode has a very similar problem, where pressing Return at some random point in the buffer will try to execute all of the following contents as a command! I might eventually try to mitigate this with some elisp, but my TODO list is already getting long ;)
PS: I actually use this multi-line input feature a lot, since it lets the command history store multiple lines together. For example, if I'm in some REPL, I'll often enter two lines at once: first to reload/refresh the inputs (e.g. `:r` in nix-repl, ghci, etc.) and second is the actual line of code I want to evaluate. That way, when I get the previous command by pressing C-up I get both lines, which ensures my expressions are always being evaluated in a clean, up-to-date environment. (Note that previous command is C-up, since up on its own will navigate around the buffer!)
The ": ... ; " is a good start, but you can also put in the $ or # before the semicolon using bash's "\$". This makes it especially protective if you copy+paste+oops as root ;-)
You have to have a space after the ":", so ": ", but you can colorize that bit in modern shells so they have a use. I color them green or red depending on the exit status of the prior command (using the PROMPT_COMMAND bash var). I also leave out the space after ";" and just colorize it to be invisible, but that's a personal quirk.
More importantly, you can use the PROMPT_COMMAND to filter out braindamage as you build the prompt, and thus prevent filenames - which can contain ">" - or something from producing a redirect in your PS1.
The prompt should end with a newline, so each command is on its own complete line, and you can select it by triple-clicking, without having to bother with character-by-character selection to skip the prompt. This works really well in Emacs shell mode.
this is actually the most useful thing to put in your prompt (much more than your username, the current directory and other redundant stuff), as in PS1='$?\$ '
Now my prompts start with the current UNIX time, coloured red if the previous exit code was non-zero, or green if it was zero. This gives me instant feedback on success/failure, and lets me retroactively see how long a command took (without having to re-run it with `time`).
Duration and start time can both be useful, and the former can be calculated from the latter as needed. Plus it's easier to implement (stateless) and has consistent alignment (always 10 digits).
BTW here's the function I use:
```
showTime() {
if [[ "$?" -eq 0 ]]
then
TIMECOLOR='\e[92m'
else
TIMECOLOR='\e[91m'
fi
echo -e "$TIMECOLOR$(date '+%s')\e[0m"
}
```
That's because, as a MacOS user, you are probably using the Z shell, not the Bourne Again shell. Prompt syntax is specific to each individual shell program.
One cannot just blindly use a Stack Exchange Q&A that states that it is for "Linux" and "bash" on the Z shell on MacOS, or indeed on the Z shell on a Linux-based operating system for that matter. Or in the C shell. Or in the Korn shell. Or in the Watanabe shell.
And to undo this in the current shell, because of said nuisance:
set +o noclobber
For some reason this is hard for me to remember, because of what the + and - signs have come to symbolize in more recent UI. set +o seems really backward to me, and unset, surprisingly, does not work.
I've commented this line out in all my .rc, because I've found it to be a nuisance without having bought me much. The better principle is do careful work as root, and don't give careless or junior people root. My root PS1 very 'l33t', look and despair:
This was never an issue when shells were first invented, because there were no mice. You could not select a region of the screen with the mouse, so there were no cut-and-paste errors like these.
If I want repeat an earlier command, I use the up-arrow, or bang:
!a repeats the last command that began with an "a".
The computer mouse, in its current form, was invented half a decade before Unix itself was. This should be qualified with: there were no mice on the machines that ran Unix.
I've run as root whenever possible for over a decade with 0 problems. I'm not going to relegate myself to constantly asking my own computer for permission to do anything. Same for UAC turned off in Windows, just don't run viruses.
I'm unsure if "protection against accidents" is that relevant for deciding to have a root terminal open or not. Even if the clipboard contained some destructive "delete everything" command plus an newline character, all the files I actually care about is in my home directory and can easily be wiped by my regular non-root user.
Yeah, my reply naturally only works for personal computers, e.g. my laptop/desktop system where it's very unlikely anybody else but me will use it. For corporate servers where you have traceability requirements and such it's an entirely different question.
I did it, and the additional pain of all those bandaids proposed here it not worth it. I did crash servers, deleted clusters, botched up firewalls and routing by misclicks.
But any damage caused by this does not approach the pain caused by misguided attempts to avoid it.
Most commands I'd run would need sudo anyway so a mis-paste would probably run with sudo if I used it. Never had a mishap from a mispaste like that though, no.
I don't trust the terminal and myself so much that I when I rsync a remote folder to a local folder I use sshfs to mount that remote folder in read-only mode and rsync from that mount point rather than the remote folder.
Heh...back when I was taking an Intro to Linux class for my CS degree, the instructor was teaching us rsync, and he somehow accidentally nuked his entire home directory.
My lesson I took away from that was to not use rsync because it's too easy to get it wrong and lose a lot of data.
It was defined by POSIX [1] - of course anyone can extend POSIX functionality (and does), however I'm personally unaware of a locale which would break this specific convention / definition as it would almost assuredly break a lot of scripts in the world.
If you could configure the common shells (bash, zsh, fish) to run a custom command on submitted shell input before executing, you could build a heuristic function that would attempt to recognize when you were pasting in a prompt. Unfortunately, I'm not aware of such a capability, as it would be useful in a number of situations.
Another alternative is to put the octothorpe # at the beginning of your prompt - then you can keep your > at the end.
Fish just doesn't seem to process the redirected output to clobber the file when a command isn't found. If your prompt is a valid command it can clobber a binary but not otherwise, apparently.
I recall terminals (MacOS Terminal? definitely Konsole seems to) that prevent any paste from actually executing the command, even if it contains newlines. Doesn't that solve this problem?
The part "let's make sure that we are trying to execute the right command in its correct location" which then follows up by running pwd is strange. Your current working directory has nothing to do with where expdp is found unless you either prefix it with ./ -- which you didn't -- or put . in $PATH (which is generally not a great idea).