bashcov icon indicating copy to clipboard operation
bashcov copied to clipboard

Not working in a minimal Linux container?

Open CyberShadow opened this issue 6 years ago • 4 comments
trafficstars

For the same simple test script, bashcov runs fine on my PC, but crashes inside a minimal container.

Here is the Dockerfile + script which reproduces the problem:

https://gist.github.com/CyberShadow/79422aea8ee896378785c273b56ec07c

(run docker build -t bashcov . && docker run bashcov to reproduce).

Here is the output:

+ bashcov test.sh
Hello
#<Thread:0x0000561f4f35b708@/var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/runner.rb:42 run> terminated with exception (report_on_exception is true):
/var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:121:in `parse_hit!': expected integer for LINENO, got "" (Bashcov::XtraceError)
	from /var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:96:in `block in read'
	from /var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:94:in `loop'
	from /var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:94:in `read'
	from /var/lib/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/runner.rb:42:in `block (2 levels) in run'
bashcov: warning: encountered an error parsing Bash's output (error was: expected integer for LINENO, got ""). This can occur if your script or its path contains the sequence "\u001E", or if your script unsets LINENO. Aborting early; coverage report will be incomplete.
Run completed using bashcov 1.8.2 with Bash 4.4, Ruby 2.5.1, and SimpleCov 0.15.1.
Coverage report generated for /bin/bash test.sh to /root/covtest/coverage. 0 / 1 LOC (0.0%) covered.

Any hints on how to narrow this down?

CyberShadow avatar Dec 30 '18 12:12 CyberShadow

Looks like this is due to the fact that Bash 4.4 does not inherit PS4 from the environment when run as root. From the Bash NEWS file:

nn. Shells running as root no longer inherit PS4 from the environment, closing a security hole involving PS4 expansion performing command substitution.

Might be possible to work around this by writing out a temporary file containing just:

export PS4=<Bashcov magic PS4>

and set ENV["BASH_ENV"] to the path of this file, as Bash will automatically source this file on startup.

In any case, Bashcov should check whether it is running as root and verify whether its special PS4 was indeed inherited by Bash. Should be easy enough, as Bashcov already checks the expansion of PS4 in order to determine whether the currently-running Bash is subject to the PS4 truncation bug

tomeon avatar Dec 31 '18 03:12 tomeon

Ah, so the issue is the UID=0. I can work around that. Thanks!

CyberShadow avatar Dec 31 '18 04:12 CyberShadow

Turns out this is the same issue as encountered in #31.

tomeon avatar Jan 08 '19 15:01 tomeon

Just adding my testimony: I'm trying to use Bashcov in CI (Bash images, based on Alpine).

my-job:
  image: bash:5.0
  before_script:
    - apk add --no-cache file ruby ruby-dev gcc libc-dev
    - gem install --no-ri --no-rdoc bashcov
    - ln -s /usr/local/bin/bash /bin/bash  # seems mandatory
  script:
    - bashcov -s --bash-path /usr/local/bin/bash -- $BASHER_ROOT/cellar/bin/bats tests/*.bats

...and I get this same error:

bashcov -s --bash-path /usr/local/bin/bash -- /builds/project-0/.basher/cellar/bin/bats tests/*.bats
/usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov.rb:146: warning: Insecure world writable dir /builds/project-0 in PATH, mode 040777
1..17
ok 1 shellm prints usage and fails with no arguments
ok 2 shellm prints help with -h option
ok 3 shellm fails with unknown command
ok 4 shellm locate finds library file
ok 5 shellm locate finds library directory
ok 6 shellm locate fails to locate inexitent file
ok 7 shellm source fails with no arguments
ok 8 shellm source sources a library only once
ok 9 shellm source fails to source inexistant library
ok 10 shellm source return error code from failing library
ok 11 shellm source prints help with -h option # skip not ready
ok 12 shellm source forces re-sourcing of library with -f option
ok 13 shellm source with directory sources files in lib subdir
ok 14 shellm source-path runs correctly
ok 15 shellm source-path fails with unsupported shell (argument)
ok 16 shellm source-path fails with unsupported shell (inherited BASHER_SHELL)
ok 17 shellm source-path prints help with -h option
#<Thread:0x00005646f6b1a268@/usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/runner.rb:42 run> terminated with exception (report_on_exception is true):
/usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:121:in `parse_hit!': expected integer for LINENO, got "" (Bashcov::XtraceError)
	from /usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:96:in `block in read'
	from /usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:94:in `loop'
	from /usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/xtrace.rb:94:in `read'
	from /usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/lib/bashcov/runner.rb:42:in `block (2 levels) in run'
bashcov: warning: encountered an error parsing Bash's output (error was: expected integer for LINENO, got ""). This can occur if your script or its path contains the sequence "\u001E", or if your script unsets LINENO. Aborting early; coverage report will be incomplete.
/usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require': cannot load such file -- etc (LoadError)
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/gems/2.5.0/gems/simplecov-0.15.1/lib/simplecov/load_global_config.rb:1:in `<top (required)>'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/gems/2.5.0/gems/simplecov-0.15.1/lib/simplecov/defaults.rb:102:in `<top (required)>'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/gems/2.5.0/gems/simplecov-0.15.1/lib/simplecov.rb:187:in `<top (required)>'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
	from /usr/lib/ruby/gems/2.5.0/gems/bashcov-1.8.2/bin/bashcov:15:in `<top (required)>'
	from /usr/bin/bashcov:23:in `load'
	from /usr/bin/bashcov:23:in `<main>'

If I understand correctly, the parsing error happens because PS4 is not inherited in root shells (it was an attack vector, removed in 4.4), and you have something going on to fix it?

pawamoy avatar May 08 '19 19:05 pawamoy

Just hit the same issue, doing this for now to run as non-root:

docker run -it --rm \
  -v "/some/folder:/workdir" \
  ruby:latest \
  bash -c "
    gem install bashcov &&
    useradd -m bashcov &&
    echo 'bashcov ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/nopasswd
    cd /workdir &&
    runuser -u bashcov bashcov my-tests.sh
  "

sebthom avatar Feb 08 '23 17:02 sebthom

Bashcov 3.0 has been released with a fix for this issue. Please run gem update bashcov and try again.

infertux avatar Apr 18 '23 00:04 infertux