diff --git a/CHANGELOG.md b/CHANGELOG.md
index f51354913a7ba33f67dc6d43d69aad82ee3ec25c..5f173fa106a34d4687534208cd8b9501125009ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,24 @@
+## [3.5.2](https://gitlab.com/to-be-continuous/bash/compare/3.5.1...3.5.2) (2024-09-29)
+
+
+### Bug Fixes
+
+* bats libs not downloaded behind a proxy ([c0d51df](https://gitlab.com/to-be-continuous/bash/commit/c0d51df73f35705f839afffb85415c4b6eed7115))
+
+## [3.5.1](https://gitlab.com/to-be-continuous/bash/compare/3.5.0...3.5.1) (2024-09-29)
+
+
+### Bug Fixes
+
+* support glob patterns in ShellCheck files ([4fee4c7](https://gitlab.com/to-be-continuous/bash/commit/4fee4c723602f01235d038c9f9b8b41d15e79577))
+
+# [3.5.0](https://gitlab.com/to-be-continuous/bash/compare/3.4.1...3.5.0) (2024-08-30)
+
+
+### Features
+
+* standard TBC secrets decoding ([d9568c9](https://gitlab.com/to-be-continuous/bash/commit/d9568c97298ba0f186d56b77404d4c9b06e021be))
+
 ## [3.4.1](https://gitlab.com/to-be-continuous/bash/compare/3.4.0...3.4.1) (2024-05-05)
 
 
diff --git a/README.md b/README.md
index 21b30af7863f67fdf14b91eb8028640392925937..f318362efa4396378ed3334d0bf1e50a41767f15 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Add the following to your `.gitlab-ci.yml`:
 ```yaml
 include:
   # 1: include the component
-  - component: $CI_SERVER_FQDN/to-be-continuous/bash/gitlab-ci-bash@3.4.1
+  - component: $CI_SERVER_FQDN/to-be-continuous/bash/gitlab-ci-bash@3.5.2
     # 2: set/override component inputs
     inputs:
       bats-enabled: true # ⚠ this is only an example
@@ -28,7 +28,7 @@ Add the following to your `.gitlab-ci.yml`:
 include:
   # 1: include the template
   - project: 'to-be-continuous/bash'
-    ref: '3.4.1'
+    ref: '3.5.2'
     file: '/templates/gitlab-ci-bash.yml'
 
 variables:
@@ -46,7 +46,7 @@ This job performs a static analysis of your shell scripts using [ShellCheck](htt
 | ----------------------- | -------------------------------------- | ----------------- |
 | `shellcheck-disabled` / `BASH_SHELLCHECK_DISABLED` | Set to `true` to disable ShellCheck                                                | _none_ (enabled) |
 | `shellcheck-image` / `BASH_SHELLCHECK_IMAGE` | The Docker image used to run [ShellCheck](https://github.com/koalaman/shellcheck) | `registry.hub.docker.com/koalaman/shellcheck-alpine:stable` |
-| `shellcheck-files` / `BASH_SHELLCHECK_FILES` | Shell file(s) pattern to analyse                                                  | `**/*.sh`            |
+| `shellcheck-files` / `BASH_SHELLCHECK_FILES` | Shell file(s) or pattern(s) to analyse                                                   | `**/*.sh`            |
 | `shellcheck-opts` / `BASH_SHELLCHECK_OPTS` | ShellCheck [options](https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md) | _none_ |
 
 ### `bash-bats` job
diff --git a/bumpversion.sh b/bumpversion.sh
index 329e866dac988c049574a0a9f26ba89979c523a8..708faf434d2459d63b2bdaceada5eb32b0fd39eb 100755
--- a/bumpversion.sh
+++ b/bumpversion.sh
@@ -27,7 +27,7 @@ if [[ "$curVer" ]]; then
   log_info "Bump version from \\e[33;1m${curVer}\\e[0m to \\e[33;1m${nextVer}\\e[0m (release type: $relType)..."
 
   # replace in README
-  sed -e "s/ref: *'$curVer'/ref: '$nextVer'/" -e "s/ref: *\"$curVer\”/ref: \”$nextVer\”/" -e "s/component: *\(.*\)@$curVer/component: \1@$nextVer/" README.md > README.md.next
+  sed -e "s/ref: *'$curVer'/ref: '$nextVer'/" -e "s/ref: *\"$curVer\"/ref: \"$nextVer\"/" -e "s/component: *\(.*\)@$curVer/component: \1@$nextVer/" README.md > README.md.next
   mv -f README.md.next README.md
 
   # replace in template and variants
diff --git a/kicker.json b/kicker.json
index fcb04595070c259753a45936c539accc51a501dd..d612ef5fe24f6a1b5398fcd5b2e3b7c9580e4fa7 100644
--- a/kicker.json
+++ b/kicker.json
@@ -20,7 +20,7 @@
         },
         {
           "name": "BASH_SHELLCHECK_FILES",
-          "description": "Shell file(s) pattern to analyse",
+          "description": "Shell file(s) or pattern(s) to analyse",
           "default": "**/*.sh"
         },
         {
diff --git a/templates/gitlab-ci-bash.yml b/templates/gitlab-ci-bash.yml
index 357de82c6fbd44b4c4a5135c219fd39110eac0cf..b3094a8163ae703ed9b0f6c4f28da644540da9cc 100644
--- a/templates/gitlab-ci-bash.yml
+++ b/templates/gitlab-ci-bash.yml
@@ -23,7 +23,7 @@ spec:
       description: The Docker image used to run [ShellCheck](https://github.com/koalaman/shellcheck)
       default: registry.hub.docker.com/koalaman/shellcheck-alpine:stable
     shellcheck-files:
-      description: Shell file(s) pattern to analyse
+      description: Shell file(s) or pattern(s) to analyse
       default: '**/*.sh'
     shellcheck-opts:
       description: ShellCheck [options](https://github.com/koalaman/shellcheck/blob/master/shellcheck.1.md)
@@ -137,15 +137,15 @@ stages:
   set -e
 
   function log_info() {
-      echo -e "[\\e[1;94mINFO\\e[0m] $*"
+      >&2 echo -e "[\\e[1;94mINFO\\e[0m] $*"
   }
 
   function log_warn() {
-      echo -e "[\\e[1;93mWARN\\e[0m] $*"
+      >&2 echo -e "[\\e[1;93mWARN\\e[0m] $*"
   }
 
   function log_error() {
-      echo -e "[\\e[1;91mERROR\\e[0m] $*"
+      >&2 echo -e "[\\e[1;91mERROR\\e[0m] $*"
   }
 
   function install_ca_certs() {
@@ -248,6 +248,99 @@ stages:
     log_info "... done"
   }
 
+  # evaluate and export a secret
+  # - $1: secret variable name
+  function eval_secret() {
+    name=$1
+    value=$(eval echo "\$${name}")
+    case "$value" in
+    @b64@*)
+      decoded=$(mktemp)
+      errors=$(mktemp)
+      if echo "$value" | cut -c6- | base64 -d > "${decoded}" 2> "${errors}"
+      then
+        # shellcheck disable=SC2086
+        export ${name}="$(cat ${decoded})"
+        log_info "Successfully decoded base64 secret \\e[33;1m${name}\\e[0m"
+      else
+        fail "Failed decoding base64 secret \\e[33;1m${name}\\e[0m:\\n$(sed 's/^/... /g' "${errors}")"
+      fi
+      ;;
+    @hex@*)
+      decoded=$(mktemp)
+      errors=$(mktemp)
+      if echo "$value" | cut -c6- | sed 's/\([0-9A-F]\{2\}\)/\\\\x\1/gI' | xargs printf > "${decoded}" 2> "${errors}"
+      then
+        # shellcheck disable=SC2086
+        export ${name}="$(cat ${decoded})"
+        log_info "Successfully decoded hexadecimal secret \\e[33;1m${name}\\e[0m"
+      else
+        fail "Failed decoding hexadecimal secret \\e[33;1m${name}\\e[0m:\\n$(sed 's/^/... /g' "${errors}")"
+      fi
+      ;;
+    @url@*)
+      url=$(echo "$value" | cut -c6-)
+      if command -v curl > /dev/null
+      then
+        decoded=$(mktemp)
+        errors=$(mktemp)
+        if curl -s -S -f --connect-timeout 5 -o "${decoded}" "$url" 2> "${errors}"
+        then
+          # shellcheck disable=SC2086
+          export ${name}="$(cat ${decoded})"
+          log_info "Successfully curl'd secret \\e[33;1m${name}\\e[0m"
+        else
+          log_warn "Failed getting secret \\e[33;1m${name}\\e[0m:\\n$(sed 's/^/... /g' "${errors}")"
+        fi
+      elif command -v wget > /dev/null
+      then
+        decoded=$(mktemp)
+        errors=$(mktemp)
+        if wget -T 5 -O "${decoded}" "$url" 2> "${errors}"
+        then
+          # shellcheck disable=SC2086
+          export ${name}="$(cat ${decoded})"
+          log_info "Successfully wget'd secret \\e[33;1m${name}\\e[0m"
+        else
+          log_warn "Failed getting secret \\e[33;1m${name}\\e[0m:\\n$(sed 's/^/... /g' "${errors}")"
+        fi
+      else
+        fail "Couldn't get secret \\e[33;1m${name}\\e[0m: no http client found"
+      fi
+      ;;
+    esac
+  }
+
+  function eval_all_secrets() {
+    encoded_vars=$(env | grep -v '^scoped__' | awk -F '=' '/^[a-zA-Z0-9_]*=@(b64|hex|url)@/ {print $1}')
+    for var in $encoded_vars
+    do
+      eval_secret "$var"
+    done
+  }
+
+  function maybe_install_packages() {
+    if command -v apt-get > /dev/null
+    then
+      # Debian
+      if ! dpkg --status "$@" > /dev/null
+      then
+        apt-get update
+        apt-get install --no-install-recommends --yes --quiet "$@"
+      fi
+    elif command -v apk > /dev/null
+    then
+      # Alpine
+      if ! apk info --installed "$@" > /dev/null
+      then
+        apk add --no-cache "$@"
+      fi
+    else
+      log_error "... didn't find any supported package manager to install $*"
+      exit 1
+    fi
+  }
+
   function install_bats_libs() {
     export BATS_LIBRARIES_DIR=/opt/bats/libexec
 
@@ -256,6 +349,13 @@ stages:
       return
     fi
 
+    if [[ "$https_proxy" || "$HTTPS_PROXY" ]]
+    then
+      # BusyBox wget doesn't support proxies and TLS/SSL at the same time: need to use offical full-featured wget instead
+
+      maybe_install_packages wget
+    fi
+
     # install Bats libraries
     for lib in $BASH_BATS_LIBRARIES
     do
@@ -267,7 +367,7 @@ stages:
       target=$(mktemp)
 
       # 1: download
-      log_info " ... download"
+      log_info " ... download with wget"
       wget -O "$target" "$lib_url"
 
       # 2: unzip
@@ -283,12 +383,29 @@ stages:
       fi
     done
 
-    # debug log
-    log_info " ... DONE"
-    ls -lart "$BATS_LIBRARIES_DIR"
+    if [ -n "${TRACE}" ]; then
+      # debug log
+      log_info " ... DONE"
+      ls -lart "$BATS_LIBRARIES_DIR"
+    fi
+  }
+
+  function glob_expand() {
+    for f in "$@"; do
+      if [[ "$f" == *[*?[]* ]]; then
+          # expand pattern with * or ? or [
+          find . -path "$f" -type f
+      elif [[ -f "$f" ]]; then
+        echo "$f"
+      else
+        log_error "File not found: $f"
+        exit 1
+      fi
+    done
   }
 
   unscope_variables
+  eval_all_secrets
 
   # ENDSCRIPT
 
@@ -296,7 +413,7 @@ stages:
   stage: build
   services:
     - name: "$TBC_TRACKING_IMAGE"
-      command: ["--service", "bash", "3.4.1"]
+      command: ["--service", "bash", "3.5.2"]
   before_script:
     - !reference [.bash-scripts]
     - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
@@ -308,7 +425,8 @@ bash-shellcheck:
     entrypoint: [""]
   script:
     - export LC_ALL=C.UTF-8
-    - shellcheck $BASH_SHELLCHECK_OPTS $BASH_SHELLCHECK_FILES
+    - shellcheck $BASH_SHELLCHECK_OPTS $(glob_expand $BASH_SHELLCHECK_FILES)
+
   rules:
     - if: '$BASH_SHELLCHECK_DISABLED == "true"'
       when: never