diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5b19ed45377b29ac49ee6e20fed4d6307986a956..7259e7ca3d3a6d9b5ef62394092ac659ae2199ea 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -4,14 +4,16 @@
     -   id: check-added-large-files
     -   id: check-merge-conflict
 -   repo: https://www.shore.co.il/git/shell-pre-commit/
-    sha: v0.3.0
+    sha: v0.4.0
     hooks:
     -   id: shell-lint
         files: bundle_certs
+    -   id: shellcheck
+        files: bundle_certs
 -   repo: local
     hooks:
     -   id: test
         name: make test
         language: system
-        entry: make test
+        entry: make test test_source
         files: bundle_certs|Makefile
diff --git a/.travis.yml b/.travis.yml
index e3a68d0d63f88e8c3fae720b253e0d0209d30c08..08f8e1c3b67f6f871e5b335e9c64c5c2165f4fcb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,6 @@
 ---
 language: python
-python: "2.7"
+python: "3.5"
 dist: trusty
 sudo: false
 group: beta
@@ -11,11 +11,14 @@ cache:
 
 addons:
   apt:
+    sources:
+      - sourceline: 'deb http://archive.ubuntu.com/ubuntu trusty-backports main universe multiverse'
     packages:
       - mawk
       - openssl
       - curl
       - build-essential
+      - shellcheck
 
 install:
   - pip install pre_commit
diff --git a/Makefile b/Makefile
index bb54b4a6e13151fd616a5a2e5d2734fd484c57cb..8015254f5e03851cf259885d306402e3dbfbd330 100644
--- a/Makefile
+++ b/Makefile
@@ -54,3 +54,6 @@ test: .testcerts/bundle.crt .testcerts/root.crt .testcerts/server.key
 clean:
 	- kill "$$(cat .server.pid)"
 	git clean -fdx
+
+test_source:
+	/bin/sh -c '. ./bundle_certs'
diff --git a/bundle_certs b/bundle_certs
index 0d22ca466dc208635d703de92bdc3e805bf14306..19d64805d984b5b62c76f2a719aa3ac0e08b5d27 100755
--- a/bundle_certs
+++ b/bundle_certs
@@ -1,7 +1,9 @@
-#!/bin/sh -e
-# Check if the script is being sourced or not.
-[ "$_" != "$0" ] && expr "$-" : ".*i.*" > /dev/null && sourced=1
+#!/bin/sh
+# shellcheck disable=SC2039
 
+# Check if the script is being sourced or not.
+# shellcheck disable=SC2142
+alias is_sourced='[ "$_" != "$0" ] && expr "$-" : ".*i.*" > /dev/null'
 
 # Returns the subject hash of the certificate path provided.
 alias subject_hash='openssl x509 -noout -subject_hash -in'
@@ -16,7 +18,7 @@ find_root_cert () {
     for filename in "$@"
     do
         if [ -f "$filename" ] && \
-            [ "$(subject_hash $filename)" = "$(issuer_hash $filename)" ]
+            [ "$(subject_hash "$filename")" = "$(issuer_hash "$filename")" ]
         then
             echo "$filename"
             break
@@ -34,8 +36,8 @@ find_cert_by_issuer_hash () {
     for filename in "$@"
     do
         if [ -f "$filename" ] && \
-            [ "$(issuer_hash $filename)" = "$certhash" ] && \
-            [ "$(issuer_hash $filename)" != "$(subject_hash $filename)" ]
+            [ "$(issuer_hash "$filename")" = "$certhash" ] && \
+            [ "$(issuer_hash "$filename")" != "$(subject_hash "$filename")" ]
         then
             echo "$filename"
             break
@@ -49,12 +51,12 @@ unbundle_cert () {
     # filenames are the subject hash for each certificate).
     local certificate
     mkdir -p certs
-    awk '/-----BEGIN[A-Z0-9 ]*CERTIFICATE-----/ {n++} \
+    awk '/-----BEGIN[A-Z0-9 ]*CERTIFICATE-----/ {n++}
         n > 0 {print > ("certs/cert" (1+n))}' "$1"
     for certificate in certs/cert*
     do
         [ -f "$certificate" ] || continue
-        mv "$certificate" "certs/$(subject_hash $certificate)"
+        mv "$certificate" "certs/$(subject_hash "$certificate")"
     done
 }
 
@@ -65,28 +67,33 @@ bundle_certs () {
         [ -f "$filename" ] && unbundle_cert "$filename"
     done
     cd certs
-    issuer="$(find_root_cert *)"
+    issuer="$(find_root_cert "*")"
     if [ -z "$issuer" ]
     then
         echo "Failed to find root certificate." > /dev/stderr
         exit 1
     fi
-    issued="$(find_cert_by_issuer_hash $issuer *)"
+    issued="$(find_cert_by_issuer_hash "$issuer" "*")"
     while [ -n "$issued" ]
     do
         ordered_certs="$issued $ordered_certs"
         issuer="$issued"
-        issued="$(find_cert_by_issuer_hash $issuer *)"
+        issued="$(find_cert_by_issuer_hash "$issuer" "*")"
     done
-    cat $ordered_certs
+    cat "$ordered_certs"
     cd ..
     rm -r certs
 }
 
 
-if [ ! "$sourced" ] && [ $# -eq 0 ]
+if ! is_sourced
 then
-    echo "Usage: $0 filename [filename2 [filename3 ...]]" > /dev/stderr
-    exit 1
+    set -eu
+    if [ $# -eq 0 ]
+    then
+        echo "Usage: $0 filename [filename2 [filename3 ...]]" > /dev/stderr
+        exit 1
+    else
+        bundle_certs "$@"
+    fi
 fi
-[ ! "$sourced" ] && bundle_certs "$@"