diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d92b5037f0e18d0291065c56a5f96b2eb2917f5b..1e3186bf5158b5bd0a4e78dec9327a8679f3b3d1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,11 +10,6 @@ unit-tests:
 
 vulnerability-scan:
   stage: "test"
-  # It would be nice to target this a bit more specifically.  If we upgrade to
-  # a newer GitLab (13.11?) then we can select exit codes that are allowed.
-  # For now we're stuck with true/false though.
-  # https://whetstone.privatestorage.io/help/ci/yaml/README.md#allow_failure
-  allow_failure: true
   script:
     - "ci-tools/vulnerability-scan security-report.txt"
   artifacts:
diff --git a/ci-tools/vulnerability-scan b/ci-tools/vulnerability-scan
index 94cfd3f84cf83f700c250ee047f6c16e975a5e02..0a3a7762c7e86eae1259469d4da4ee81646bd748 100755
--- a/ci-tools/vulnerability-scan
+++ b/ci-tools/vulnerability-scan
@@ -37,4 +37,18 @@ fi
 # config.  vulnix exit status indicates what vulnix thinks happened.  If we
 # upgrade to a newer GitLab then we can make GitLab pipeline behavior vary
 # based on this.
+#
+# For now, allow 0 (no errors), 1 (only whitelisted errors), and 2
+# (non-whitelisted errors).  3 indicates unexpected error so we let that
+# propagate.
+set +e
 nix-shell -p vulnix --run 'vulnix ./scan-target/' | tee "$OUTPUT"
+vulnix_status=$?
+set -e
+
+echo "vulnix status: $vulnix_status"
+if [ $vulnix_status -eq 3 ]; then
+    exit $vulnix_status
+else
+    exit 0
+fi