Hacker News new | ask | show | jobs
by HorstG 2352 days ago
There are lots of those footguns in shellscript. One should always try to avoid any shell and rather use python, tcl, perl or powershell. Any criticism one might have about insecure and broken by design languages apply doubly to shell.

A short list of possible problems (of course depending on the shell in question):

spaces in filenames

newlines in filenames

nonprintables in filenames

empty variables and their expansion ([ x$foo = "xsomething" ])

errors in pipes

environment madness

/bin/bash ?= /bin/sh

Arrays or the lack of it

Space separates lists as arrays

#!bash vs. #!/bin/bash vs. #!/usr/bin/env bash vs. #!/usr/sfw/bin/bash vs. ...

Unwritable and unreadable control structures (if [], case, &&,...)

Information leaks via ps

and many others...

Never use shell except to search for and invoke a sensible language. And anything is more sensible, including C, Perl, brainfuck and Basic.

4 comments

I believe your diatribe is misplaced.

There are quite a few pitfalls in shell scripting. You can considerably reduce them by limiting yourself to only being compatible with modern versions of bash and settings things like pipefail, nounset, etc etc.

I do agree that in general a good programming language will be a better option.

> anything is more sensible, including C, Perl, brainfuck and Basic

I do disagree with that however. A 5 line bash script may be 500 lines of C, will take a hundred times longer to write, and may contain memory safety issues (which the bash script at least wouldn't).

I know brainfuck is hyperbolic so I won't argue against that. Something with no filesystem or process forking abilities obviously can't be used for any real task.

I think perl and basic have just as bad syntax as bash though, if not worse. Basic's penchant for "GOTO" is awful, perl's syntax as a whole is just as peculiar as bash's in many places.

I guess my overall point is that bash is usually not a good option compared to modern languages, but it's a darn sight better than you give it credit for. I think it still has its place for 5 or 10 liners that are easy to express and read in bash and don't need any abstractions beyond what coreutils provide.

I agree that 5 to 10 lines might be a sensible upper limit where a shell can safely be used.

Basic does have Goto, but modern dialects do have all the usual control structures. Perl has weird syntax, but far less dangerous footguns: e.g. there are proper arrays, as opposed to many shells. One can distinguish between an empty and an undefined string. One can declare variables and there is the notion of data types. There are even things like taint mode. In shell, you can't even properly iterate over a directory without nasty surprises.

Same in C. Yes, there are memory safety problems, but those are outnumbered by far by shellscripts exploitable via some expansion or variable injection. Its just that thankfully nobody uses shellskripts as network services, so you don't see as many reports about that.

And yes, brainfuck was there as hyperbole. But I truly believe that there are very few things worse than shell for programming.

Many of these crazy corner cases are the reason why I switched to fish. Eg, in fish all variables are arrays, so arguments are passed in the $argv array, and number of elements in the array is "count $argv" (in bash the number of arguments is passed in $#, but the hieroglyphic required to count the number of elements in an array is ${#var[@]} )

$PATH is just an array where each path is an element, so removing or adding a path equals to adding/removing an element from the array which is trivial.

Iterating over files names with spaces works exactly as expected and no IFS tweaking is needed (fun thing, in bash, doing for i in * .foobar; do echo $i; done; in a directory with no files with that extension will return the string "*.foobar"). No "[" craziness, nicer syntax, etc.

Unfortunately fish still lacks other important features (eg. no set -e equivalent).

There is an space for sane Unix shells but everybody has settled on bash and changing the status quo is difficult.

But why use Fish for scripting? Why not just use Python3 and be done?
> anything is more sensible, including C, Perl, brainfuck and Basic.

IKR? I perform all administrative operations via a solidity contract, hooked up to a permissioned ethereum chain which my computer scans for relevant logs.

I like powershell, but it has its own arsenal of footguns for you to use. Things like non-terminating errors and the sometimes confounding behaviour of automatic variables comes to mind.