gemnasium-maven fails on Mac OS when using sbt >= 1.4.0

Summary

The gemnasium-maven analyzer fails to produce a gl-dependency-scanning-report.json and exits with status code 2 on Mac OS X when using sbt >= 1.4.0.

Steps to reproduce

$ docker pull registry.gitlab.com/security-products/gemnasium-maven:3
$ git clone https://gitlab.com/gitlab-org/security-products/tests/scala-sbt.git --branch demonstrate-mac-os-x-sbt-bug
$ docker run -it --rm -v "$PWD/scala-sbt/qa/fixtures/scala-sbt/default:/ci-project-dir" \
  -e CI_PROJECT_DIR=/ci-project-dir \
  -e SECURE_LOG_LEVEL=debug registry.gitlab.com/security-products/gemnasium-maven:3

Using java version 'adoptopenjdk-17.0.2+8'
[INFO] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ GitLab gemnasium-maven analyzer v3.0.1
[DEBU] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ inspect directory: .
[DEBU] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ electing sbt for maven because this is the first match
[DEBU] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ electing sbt for maven because this is the first match
[INFO] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ Detected supported dependency files in '.'. Dependency files detected in this directory will be processed. Dependency files in other directories will be skipped.
[DEBU] [gemnasium-maven] [2022-05-25T12:09:59Z] ▶ Exporting dependencies for /ci-project-dir/build.sbt
[DEBU] [gemnasium-maven] [2022-05-25T12:10:01Z] ▶ /opt/asdf/shims/sbt -no-colors dependencyDot

exit status 2

Example Project

https://gitlab.com/gitlab-org/security-products/tests/scala-sbt/-/tree/demonstrate-mac-os-x-sbt-bug

What is the current bug behavior?

gemnasium-maven fails with status code 2.

What is the expected correct behavior?

gemnasium-maven should succeed with status code 0 and produce a gl-dependency-scanning-report.json file.

Results of GitLab environment info

  • gemnasium-maven v3.0.1
  • Mac OS X 10.15.7
  • Intel Processor
  • Docker Desktop 4.1.1 (69879)
    • Engine: 20.10.8

Possible fixes

gemnasium-maven relies on the following command to export sbt dependencies:

sbt -no-colors dependencyDot

This works fine with sbt < 1.4.0, however, starting with sbt >= 1.4.0, the behaviour has changed, and when the sbt command is run, we now receive the following interactive message on Mac OS X:

$ sbt -no-colors dependencyDot

sbt thinks that server is already booting because of this exception:
sbt.internal.ServerAlreadyBootingException: java.io.IOException: org.scalasbt.ipcsocket.NativeErrorException: [22] Invalid argument
	at sbt.internal.BootServerSocket.newSocket(BootServerSocket.java:348)
<snip>
Caused by: org.scalasbt.ipcsocket.NativeErrorException: [22] Invalid argument
	at org.scalasbt.ipcsocket.JNAUnixDomainSocketLibraryProvider.bind(UnixDomainSocketLibrary.java:178)
	at org.scalasbt.ipcsocket.UnixDomainServerSocket.bind(UnixDomainServerSocket.java:136)
	... 26 more

Create a new server? y/n (default y) y

[info] welcome to sbt 1.6.1 (Eclipse Adoptium Java 17.0.2)
[info] loading settings for project global-plugins from plugins.sbt ...
[info] loading global plugins from /root/.sbt/1.0/plugins
[info] loading project definition from /ci-project-dir/project
[info] compiling 1 Scala source to /ci-project-dir/project/target/scala-2.12/sbt-1.0/classes ...
[info] Non-compiled module 'compiler-bridge_2.12' for Scala 2.12.15. Compiling...
[info]   Compilation completed in 6.338s.
[info] done compiling
[info] loading settings for project root from build.sbt ...
[info] set current project to Hello (in build file:/ci-project-dir/)
[info] Wrote dependency graph to '/ci-project-dir/target/dependencies-compile.dot'
[success] Total time: 25 s, completed May 25, 2022, 12:20:20 PM

If we respond y to this message, the process continues as expected and generates a dependency list, however, this doesn't work when the command is executed using exec.Command("sbt", args...) in gemnasium-maven, since gemnasium-maven doesn't expect an interactive message requiring input, which causes the command to fail with an exit status 2.

This is a known issue with sbt, documented here. It seems that it's caused when sbt attempts to create a socket on either an NFS-mounted share, or a directory that Docker mounts from a host container using the -v (Bind mount a volume) flag.

As explained in the linked issue, there are at least two workarounds:

  1. Pass the arguments --batch -Dsbt.server.forcestart=true to the sbt command:

    sbt --batch -Dsbt.server.forcestart=true -no-colors dependencyDot
  2. Copy the CI_PROJECT_DIR to another location, for example:

    $ git clone git@gitlab.com:gitlab-org/security-products/analyzers/gemnasium.git
    $ docker run -it --rm -v "$PWD/gemnasium/qa/fixtures/scala-sbt/default:/shared-dir" \
      -e SECURE_LOG_LEVEL=debug registry.gitlab.com/security-products/gemnasium-maven:3 bash
    
    root@e6518e337cc9:~# cp -R /shared-dir /ci-project-dir && cd /ci-project-dir
    root@ce4a97b253fd:/ci-project-dir# sbt -no-colors dependencyDot

I prefer option 1. because it requires less code changes and is easier to implement.

/cc @fcatteau @gonzoyumo @sam.white

Edited by Adam Cohen