diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4b7d625190949a0651058e989b92325a407114c4..fc2b17d49084c9198eeec5f839654d97a80af3d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,18 @@
-# [4.10.0](https://git.code.tecnalia.dev/smartdatalab/public/ci-cd-components/golang/compare/4.9.2...4.10.0) (2024-08-29)
+## [4.11.1](https://gitlab.com/to-be-continuous/golang/compare/4.11.0...4.11.1) (2024-12-06)
+
+
+### Bug Fixes
+
+* semgrep subdir ([0e26288](https://gitlab.com/to-be-continuous/golang/commit/0e26288dd6b27ce3e4b92ab5c21e6a73d1152902))
+
+# [4.11.0](https://gitlab.com/to-be-continuous/golang/compare/4.10.0...4.11.0) (2024-08-30)
+
+
+### Features
+
+* standard TBC secrets decoding ([89e0f0f](https://gitlab.com/to-be-continuous/golang/commit/89e0f0fb93c2e1a21abcd09977651b567f181ed1))
+
+# [4.10.0](https://gitlab.com/to-be-continuous/golang/compare/4.9.2...4.10.0) (2024-07-05)
 
 
 ### Features
diff --git a/README.md b/README.md
index e887205c3ac1ee96650b2397e04f2490cb54597c..4efd8e7e44c51f24493d50ee557459a848786296 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/golang/gitlab-ci-golang@4.10.0
+  - component: $CI_SERVER_FQDN/to-be-continuous/golang/gitlab-ci-golang@4.11.1
     # 2: set/override component inputs
     inputs:
       image: "registry.hub.docker.com/library/golang:buster" # ⚠ 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/golang'
-    ref: '4.10.0'
+    ref: '4.11.1'
     file: '/templates/gitlab-ci-golang.yml'
 
 variables:
@@ -154,7 +154,7 @@ In addition to a textual report in the console, the test jobs produce the follow
 | Report                                              | Format                                                                             | Usage                                                                                                                 |
 |-----------------------------------------------------|------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
 | `$GO_PROJECT_DIR/reports/go-test.native.txt`        | native Go test report (text)                                                       | N/A                                                                                                                   |
-| `$GO_PROJECT_DIR/reports/go-test.native.json`       | native Go test report (json)                                                       | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/test-coverage/test-execution-parameters/#header-8) |
+| `$GO_PROJECT_DIR/reports/go-test.native.json`       | native Go test report (json)                                                       | [SonarQube integration](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go) |
 | `$GO_PROJECT_DIR/reports/go-test.xunit.xml`         | [xUnit](https://en.wikipedia.org/wiki/XUnit) test report(s)                        | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsjunit)                 |
 | `$GO_PROJECT_DIR/reports/go-coverage.native.out`    | native Go coverage                                                                 | N/A                                                                                                                   |
 | `$GO_PROJECT_DIR/reports/go-coverage.cobertura.xml` | [Cobertura XML](https://gcovr.com/en/stable/output/cobertura.html) coverage report | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report)       |
@@ -177,7 +177,35 @@ In addition to a textual report in the console, this job produces the following
 | Report                                                | Format                                                   | Usage                                                                                                       |
 |-------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
 | `$GO_PROJECT_DIR/reports/go-ci-lint.codeclimate.json` | [Code Climate](https://docs.codeclimate.com/docs/pylint) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscodequality) |
-| `$GO_PROJECT_DIR/reports/go-ci-lint.checkstyle.xml`   | Checkstyle                                               | [SonarQube integration](https://docs.sonarqube.org/latest/analysis/external-issues/)                        |
+| `$GO_PROJECT_DIR/reports/go-ci-lint.checkstyle.xml`   | Checkstyle                                               | [SonarQube integration](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/importing-external-issues/external-analyzer-reports/)                        |
+
+### `go-semgrep` job
+
+This job performs a [Semgrep](https://semgrep.dev/docs/) analysis.
+
+It is bound to the `test` stage, and uses the following variables:
+
+| Input / Variable | Description | Default Value |
+| ---------------- | ----------- | ------------- |
+| `semgrep-disabled` / `GO_SEMGREP_DISABLED` | Set to `true` to disable this job | _none_ |
+| `semgrep-image` / `GO_SEMGREP_IMAGE` | The Docker image used to run [Semgrep](https://semgrep.dev/docs/) | `registry.hub.docker.com/semgrep/semgrep:latest` |
+| `semgrep-args` / `GO_SEMGREP_ARGS` | Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | `--metrics off --disable-version-check` |
+| `semgrep-rules` / `GO_SEMGREP_RULES` | Space-separated list of [Semgrep rules](https://semgrep.dev/docs/running-rules).<br/>Can be both local YAML files or remote rules from the [Segmrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix). | `p/golang p/gosec` |
+| `semgrep-download-rules-enabled` / `GO_SEMGREP_DOWNLOAD_RULES_ENABLED` | Download Semgrep remote rules | `true` |
+
+> :information_source: Semgrep may [collect some metrics](https://semgrep.dev/docs/metrics), especially when using rules from the Semgrep Registry.
+> To protect your privacy and let you run Semgrep in air-gap environments, this template disables all Semgrep metrics by default:
+>
+> * rules from the Semgrep registry are pre-downloaded and passed to Semgrep as local rule files (can be disabled by setting `semgrep-download-rules-enabled` / `GO_SEMGREP_DOWNLOAD_RULES_ENABLED` to `false`),
+> * the `--metrics` option is set to `off`,
+> * the `--disable-version-check` option is set.
+
+In addition to a textual report in the console, this job produces the following reports, kept for one week:
+
+| Report | Format | Usage |
+| ------ | ------ | ----- |
+| `$GO_PROJECT_DIR/reports/golang-semgrep.gitlab.json` | [GitLab's SAST format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | [GitLab integration](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportssast) |
+| `$GO_PROJECT_DIR/reports/golang-semgrep.native.json` | [Semgrep's JSON format](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options) | [DefectDojo integration](https://docs.defectdojo.com/en/connecting_your_tools/parsers/file/semgrep/)<br/>_This report is generated only if DefectDojo template is detected_ |
 
 ### `go-mod-outdated` job
 
@@ -197,7 +225,7 @@ Checking outdated modules can be a long operation and therefore the job is confi
 If you're using the SonarQube template to analyse your Go code, here is a sample `sonar-project.properties` file:
 
 ```properties
-# see: https://docs.sonarqube.org/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go
+# see: https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go
 # set your source directory(ies) here (relative to the sonar-project.properties file)
 sonar.sources=.
 # exclude unwanted directories and files from being analysed
@@ -218,9 +246,9 @@ sonar.go.golangci-lint.reportPaths=reports/go-ci-lint.checkstyle.xml
 
 More info:
 
-* [Go language support](https://docs.sonarqube.org/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go)
-* [test coverage & execution parameters](https://docs.sonarqube.org/latest/analysis/coverage/)
-* [third-party issues](https://docs.sonarqube.org/latest/analysis/external-issues/)
+* [Go language support](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/test-execution-parameters/#go)
+* [test coverage](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/test-coverage-parameters/) & [test execution](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/test-execution-parameters/) parameters
+* [external analyzer reports](https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/importing-external-issues/external-analyzer-reports/)
 
 :warning: an [unsolved issue](https://jira.sonarsource.com/browse/SONARSLANG-450) may prevent SonarQube Go plugin from
 importing your test reports.
@@ -257,4 +285,4 @@ It is bound to the `test` stage, and uses the following variables:
 | --------------------- | -------------------------------------- | ----------------- |
 | `vulncheck-disabled` / `GO_VULNCHECK_DISABLED` | Set to `true` to disable this job | _none_ 
 | `vulncheck-args` / `GO_VULNCHECK_ARGS` | `govulncheck` [command line arguments](https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck#hdr-Flags) | `./...` |
-| `go-govulncheck-job-tags` / `GO_GOVULNCHECK_JOB_TAGS` | Tags to be used for selecting runners for the job | `[]`            |
\ No newline at end of file
+| `go-govulncheck-job-tags` / `GO_GOVULNCHECK_JOB_TAGS` | Tags to be used for selecting runners for the 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 e718114af00d06a3f73c3ad78b9b16998e303b1b..26d334434c04959291acda8e70a41016bca9b5b8 100644
--- a/kicker.json
+++ b/kicker.json
@@ -201,6 +201,35 @@
         }
       ]
     },
+    {
+      "id": "go-semgrep",
+      "name": "Semgrep",
+      "description": "[Semgrep](https://semgrep.dev/docs/) analysis",
+      "disable_with": "GO_SEMGREP_DISABLED",
+      "variables": [
+        {
+          "name": "GO_SEMGREP_IMAGE",
+          "description": "The Docker image used to run [Semgrep](https://semgrep.dev/docs/)",
+          "default": "registry.hub.docker.com/semgrep/semgrep:latest"
+        },
+        {
+          "name": "GO_SEMGREP_ARGS",
+          "description": "Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)",
+          "default": "--metrics off --disable-version-check"
+        },
+        {
+          "name": "GO_SEMGREP_RULES",
+          "description": "Space-separated list of [Semgrep rules](https://semgrep.dev/docs/running-rules).\n\nCan be both local YAML files or remote rules from the [Semgrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix)",
+          "default": "p/golang p/gosec"
+        },
+        {
+          "name": "GO_SEMGREP_DOWNLOAD_RULES_ENABLED",
+          "description": "Download Semgrep remote rules",
+          "type": "boolean",
+          "default": "true"
+        }
+      ]
+    },
     {
       "id": "govulncheck",
       "name": "Govulncheck",
diff --git a/templates/gitlab-ci-golang.yml b/templates/gitlab-ci-golang.yml
index fd16d8e4e92ca7c11433be2f2eb0b04260b03305..7a1d01b3e294bef19aacd5df30ca6f1f3c1b1e75 100644
--- a/templates/gitlab-ci-golang.yml
+++ b/templates/gitlab-ci-golang.yml
@@ -81,6 +81,26 @@ spec:
     ci-lint-args:
       description: '`golangci-lint` [command line arguments](https://github.com/golangci/golangci-lint#command-line-options)'
       default: -E gosec,goimports ./...
+    semgrep-image:
+      description: The Docker image used to run [Semgrep](https://semgrep.dev/docs/)
+      default: registry.hub.docker.com/semgrep/semgrep:latest
+    semgrep-disabled:
+      description: Disable Semgrep
+      type: boolean
+      default: false
+    semgrep-args:
+      description: Semgrep [scan options](https://semgrep.dev/docs/cli-reference#semgrep-scan-command-options)
+      default: --metrics off --disable-version-check
+    semgrep-rules:
+      description: |-
+        Space-separeted list of [Semgrep rules](https://semgrep.dev/docs/running-rules).
+
+        Can be both local YAML files or remote rules from the [Semgrep Registry](https://semgrep.dev/explore) (denoted by the `p/` prefix)
+      default: p/golang p/gosec
+    semgrep-download-rules-enabled:
+      description: Download Semgrep remote rules
+      type: boolean
+      default: true
     mod-outdated-args:
       description: '`god-mod-outdated` [command line arguments](https://github.com/psampaz/go-mod-outdated#usage'
       default: -update -direct
@@ -229,6 +249,11 @@ variables:
   GO_CI_LINT_DISABLED: $[[ inputs.ci-lint-disabled ]]
   GO_SBOM_DISABLED: $[[ inputs.sbom-disabled ]]
   GO_VULNCHECK_DISABLED: $[[ inputs.vulncheck-disabled ]]
+  GO_SEMGREP_IMAGE: $[[ inputs.semgrep-image ]]
+  GO_SEMGREP_DISABLED: $[[ inputs.semgrep-disabled ]]
+  GO_SEMGREP_ARGS: $[[ inputs.semgrep-args ]]
+  GO_SEMGREP_RULES: $[[ inputs.semgrep-rules ]]
+  GO_SEMGREP_DOWNLOAD_RULES_ENABLED: $[[ inputs.semgrep-download-rules-enabled ]]
 
   # Image of cyclonedx-gomod used for SBOM analysis
   GO_SBOM_IMAGE: $[[ inputs.sbom-image ]]
@@ -368,6 +393,77 @@ 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 output_coverage() {
     coverage_out=reports/go-coverage.native.out
     if [[ -f "$coverage_out" ]]
@@ -496,7 +592,33 @@ stages:
     fi
   }
 
+  function setup_semgrep_rules() {
+    if [[ "${GO_SEMGREP_DOWNLOAD_RULES_ENABLED}" == "true" ]]
+    then
+      log_info "Download Semgrep rule files..."
+      for rule in $GO_SEMGREP_RULES
+      do
+        if [[ -r $rule ]]
+        then
+          log_info "... rule file $rule found: skip"
+          SEMGREP_RULES="${SEMGREP_RULES} $rule"
+        else
+          log_info "... rule file $rule not found : download (https://semgrep.dev/c/$rule)"
+          dest_file="semgrep-${rule/p\//}.yml"
+          wget "https://semgrep.dev/c/$rule" -O "$dest_file"
+          SEMGREP_RULES="${SEMGREP_RULES} $dest_file"
+        fi
+      done
+      SEMGREP_RULES="${SEMGREP_RULES:1}"
+      export SEMGREP_RULES
+    else
+      # download not enabled: simply use $GO_SEMGREP_RULES
+      export SEMGREP_RULES="${GO_SEMGREP_RULES}"
+    fi
+  }
+
   unscope_variables
+  eval_all_secrets
 
   # ENDSCRIPT
 
@@ -506,7 +628,7 @@ stages:
   image: $GO_IMAGE
   services:
     - name: "$TBC_TRACKING_IMAGE"
-      command: ["--service", "golang", "4.10.0"]
+      command: ["--service", "golang", "4.11.1"]
   variables:
     # The directory where 'go install' will install a command.
     GOBIN: "$CI_PROJECT_DIR/$GO_PROJECT_DIR/bin"
@@ -641,6 +763,37 @@ go-ci-lint:
     - !reference [.test-policy, rules]
   tags: $[[ inputs.go-ci-lint-job-tags ]]
 
+# SAST: semgrep
+go-semgrep:
+  extends: .go-base
+  image: $GO_SEMGREP_IMAGE
+  # unset cache from parent job
+  cache : {}
+  dependencies: []
+  stage: test
+  before_script:
+    - !reference [.go-scripts]
+    - mkdir -p -m 777 ${GO_PROJECT_DIR}/reports
+    - setup_semgrep_rules
+  script:
+    - >-
+      semgrep ci ${TRACE+--verbose} ${GO_SEMGREP_ARGS} --subdir ${GO_PROJECT_DIR}
+      --gitlab-sast-output=${GO_PROJECT_DIR}/reports/golang-semgrep.gitlab.json
+      ${DEFECTDOJO_SEMGREP_REPORTS:+--json-output=${GO_PROJECT_DIR}/reports/golang-semgrep.native.json}
+  artifacts:
+    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $ĈI_COMMIT_REF_SLUG"
+    when: "always"
+    expire_in: 1 week
+    reports:
+      sast: $GO_PROJECT_DIR/reports/golang-semgrep.gitlab.json
+    paths:
+      - $GO_PROJECT_DIR/reports/golang-semgrep.*
+  rules:
+    # exclude if disable
+    - if: '$GO_SEMGREP_DISABLED == "true"'
+      when: never
+    - !reference [.test-policy, rules]
+
 go-mod-outdated:
   extends: .go-base
   stage: test