From 59b8acc3dc50eb322dbbe95252e668c5f1d18c6f Mon Sep 17 00:00:00 2001 From: nirmal-joishi-a0 <89918087+nirmal-joishi-a0@users.noreply.github.com> Date: Tue, 13 Oct 2026 12:43:52 +0530 Subject: [PATCH 1/3] chore: add MalwareScan workflow --- .github/workflows/rl.yml | 117 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .github/workflows/rl.yml diff --git a/.github/workflows/rl.yml b/.github/workflows/rl.yml new file mode 100644 index 000000000..68ac031a5 --- /dev/null +++ b/.github/workflows/rl.yml @@ -0,0 +1,117 @@ +name: RL Scan +run-name: rl-scan + +# Reusable malware-scan workflow — call this from your release or CI pipeline via +# workflow_call. The trigger lives in the calling workflow; the build steps are +# defined here as a placeholder that you replace with your own toolchain setup, +# compilation, and packaging steps before merging. +# +# Caller pattern (minimal): +# jobs: +# release-and-scan: +# uses: ./.github/workflows/rl.yml +# with: +# artifact-name: my-artifact +# artifact-path: dist/my-artifact.tgz +# version: ${{ github.event.release.tag_name }} +# secrets: inherit +# +# Artifact contract +# ───────────────── +# artifact-path MUST be a concrete file path — the action's internal existence +# check uses [ -f ], which does NOT expand globs. A missing artifact fails the job. +# +# Required org secrets (configured at org level in auth0/): +# RLSECURE_LICENSE — ReversingLabs license key +# RLSECURE_SITE_KEY — ReversingLabs site key +# SIGNAL_HANDLER_TOKEN — scan-service telemetry auth +# SIGNAL_HANDLER_DOMAIN — scan-service endpoint domain +# PRODSEC_TOOLS_ARN — AWS role ARN for ProdSec tools +# PRODSEC_TOOLS_USER — ProdSec Python tools repo user +# PRODSEC_TOOLS_TOKEN — ProdSec Python tools repo token +# PRODSEC_PYTHON_TOOLS_REPO — ProdSec Python tools repo URL + +on: + workflow_call: + inputs: + artifact-name: + description: Name assigned to the artifact (used for RL reporting) + type: string + required: true + artifact-path: + description: Concrete file path of the built artifact on the runner — no globs + type: string + required: true + version: + description: Version string for the artifact (e.g. release tag) + type: string + required: true + secrets: + RLSECURE_LICENSE: + required: true + RLSECURE_SITE_KEY: + required: true + SIGNAL_HANDLER_TOKEN: + required: true + SIGNAL_HANDLER_DOMAIN: + required: true + PRODSEC_TOOLS_ARN: + required: true + PRODSEC_TOOLS_USER: + required: true + PRODSEC_TOOLS_TOKEN: + required: true + PRODSEC_PYTHON_TOOLS_REPO: + required: true + +jobs: + # ── Malware scan via ReversingLabs composite action ───────────────────────── + rl-scan: + name: RL Scan + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write # required for AWS OIDC federation (PRODSEC_TOOLS_ARN) + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + # ── Build the artifact ──────────────────────────────────────────────────── + # Replace this placeholder with ALL steps required to produce the artifact, + # including: runtime/toolchain setup (e.g. actions/setup-node, setup-go, + # setup-dotnet), dependency installation, compilation, and packaging (e.g. + # tar, zip, docker save). The final step must place the artifact at the + # path passed as inputs.artifact-path. The rl-scan action uses [ -f ] to + # verify the file exists — a missing or incorrect path fails the job. + - name: Build artifact # TODO: replace with your toolchain setup + build + package steps + run: | + echo "TODO: replace this step with your build commands" + echo " The built file must be at: ${{ inputs.artifact-path }}" + + - name: Run RL malware scan + id: rl-scan-conclusion + uses: auth0/devsecops-tooling/.github/actions/rl-scan@e29f26478db18ff0bcbe4bc447a8fbd54fbeec9e + with: + # ── Artifact inputs ───────────────────────────────────────────────── + artifact-name: ${{ inputs.artifact-name }} + artifact-path: ${{ inputs.artifact-path }} + version: ${{ inputs.version }} + # ── Required secrets ──────────────────────────────────────────────── + RLSECURE_LICENSE: ${{ secrets.RLSECURE_LICENSE }} + RLSECURE_SITE_KEY: ${{ secrets.RLSECURE_SITE_KEY }} + SIGNAL_HANDLER_TOKEN: ${{ secrets.SIGNAL_HANDLER_TOKEN }} + SIGNAL_HANDLER_DOMAIN: ${{ secrets.SIGNAL_HANDLER_DOMAIN }} + PRODSEC_TOOLS_ARN: ${{ secrets.PRODSEC_TOOLS_ARN }} + PRODSEC_TOOLS_USER: ${{ secrets.PRODSEC_TOOLS_USER }} + PRODSEC_TOOLS_TOKEN: ${{ secrets.PRODSEC_TOOLS_TOKEN }} + PRODSEC_PYTHON_TOOLS_REPO: ${{ secrets.PRODSEC_PYTHON_TOOLS_REPO }} + + - name: Gate on scan result + if: always() + env: + SCAN_STATUS: ${{ steps.rl-scan-conclusion.outputs.scan-status }} + run: | + if [ "$SCAN_STATUS" != "success" ]; then + echo "::error title=Malware::RL scan did not pass (status: ${SCAN_STATUS:-none})" + exit 1 + fi From 846cb6f03634d639839e8be42cab576c27e3f25a Mon Sep 17 00:00:00 2001 From: Kunal Dawar Date: Mon, 19 Oct 2026 23:47:43 +0530 Subject: [PATCH 2/3] chore(security): scan released binaries with ReversingLabs Download each published release archive and scan it with the rl-scan action, once per OS and architecture. The scan job runs after GoReleaser and nothing depends on it, so a failed scan does not block the release. --- .github/workflows/release.yml | 24 ++++++++++ .github/workflows/rl.yml | 89 ++++++++++++++++++++--------------- 2 files changed, 76 insertions(+), 37 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2eb6f0812..d5668bbe2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,6 +58,30 @@ jobs: overwrite: true retention-days: 5 + # Scan every published archive. Nothing depends on this job, so a failed scan fails + # its own run but does not block the release or the Homebrew and Scoop updates. + rl-scan: + name: RL Scan + needs: goreleaser + strategy: + fail-fast: false + matrix: + asset-suffix: + - Darwin_arm64.tar.gz + - Darwin_x86_64.tar.gz + - Linux_arm64.tar.gz + - Linux_x86_64.tar.gz + - Windows_arm64.zip + - Windows_x86_64.zip + permissions: + contents: read + id-token: write + uses: ./.github/workflows/rl.yml + with: + tag: ${{ github.ref_name }} + asset-suffix: ${{ matrix.asset-suffix }} + secrets: inherit + homebrew: name: Homebrew Tap needs: goreleaser diff --git a/.github/workflows/rl.yml b/.github/workflows/rl.yml index 68ac031a5..7d390fe81 100644 --- a/.github/workflows/rl.yml +++ b/.github/workflows/rl.yml @@ -1,25 +1,31 @@ name: RL Scan -run-name: rl-scan +run-name: rl-scan ${{ inputs.asset-suffix }} -# Reusable malware-scan workflow — call this from your release or CI pipeline via -# workflow_call. The trigger lives in the calling workflow; the build steps are -# defined here as a placeholder that you replace with your own toolchain setup, -# compilation, and packaging steps before merging. +# Reusable malware-scan workflow for the release pipeline. It downloads one +# published release archive and scans it with the ReversingLabs rl-scan action from +# auth0/devsecops-tooling. The caller runs it once per archive. # -# Caller pattern (minimal): +# Caller pattern: # jobs: -# release-and-scan: +# rl-scan: +# needs: goreleaser +# permissions: +# contents: read +# id-token: write # uses: ./.github/workflows/rl.yml # with: -# artifact-name: my-artifact -# artifact-path: dist/my-artifact.tgz -# version: ${{ github.event.release.tag_name }} +# tag: ${{ github.ref_name }} +# asset-suffix: Linux_x86_64.tar.gz # secrets: inherit # +# The calling job must grant id-token: write, because this workflow requests it for +# AWS OIDC federation (PRODSEC_TOOLS_ARN). +# # Artifact contract # ───────────────── -# artifact-path MUST be a concrete file path — the action's internal existence -# check uses [ -f ], which does NOT expand globs. A missing artifact fails the job. +# The scanned file is auth0-cli__, where is the tag +# without its leading "v". The action checks it with [ -f ], so a missing asset fails +# the job. # # Required org secrets (configured at org level in auth0/): # RLSECURE_LICENSE — ReversingLabs license key @@ -34,16 +40,12 @@ run-name: rl-scan on: workflow_call: inputs: - artifact-name: - description: Name assigned to the artifact (used for RL reporting) - type: string - required: true - artifact-path: - description: Concrete file path of the built artifact on the runner — no globs + tag: + description: Release tag to scan, for example v1.38.0 type: string required: true - version: - description: Version string for the artifact (e.g. release tag) + asset-suffix: + description: Archive suffix after the version, for example Linux_x86_64.tar.gz type: string required: true secrets: @@ -67,35 +69,48 @@ on: jobs: # ── Malware scan via ReversingLabs composite action ───────────────────────── rl-scan: - name: RL Scan + name: RL Scan ${{ inputs.asset-suffix }} runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read id-token: write # required for AWS OIDC federation (PRODSEC_TOOLS_ARN) steps: - - name: Checkout - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Resolve archive name + id: asset + env: + TAG: ${{ inputs.tag }} + ASSET_SUFFIX: ${{ inputs.asset-suffix }} + run: | + NAME="auth0-cli_${TAG#v}_${ASSET_SUFFIX}" + echo "name=${NAME}" >> "$GITHUB_OUTPUT" + echo "path=dist/${NAME}" >> "$GITHUB_OUTPUT" - # ── Build the artifact ──────────────────────────────────────────────────── - # Replace this placeholder with ALL steps required to produce the artifact, - # including: runtime/toolchain setup (e.g. actions/setup-node, setup-go, - # setup-dotnet), dependency installation, compilation, and packaging (e.g. - # tar, zip, docker save). The final step must place the artifact at the - # path passed as inputs.artifact-path. The rl-scan action uses [ -f ] to - # verify the file exists — a missing or incorrect path fails the job. - - name: Build artifact # TODO: replace with your toolchain setup + build + package steps + # ── Fetch the artifact ──────────────────────────────────────────────────── + # GoReleaser uploads the archives straight to the GitHub release, so the scan + # target is downloaded from there. A failed download does not stop the job here: + # the rl-scan action reports the missing file and the gate step below fails. + - name: Download release archive + continue-on-error: true + env: + GH_TOKEN: ${{ github.token }} + TAG: ${{ inputs.tag }} + ASSET_NAME: ${{ steps.asset.outputs.name }} run: | - echo "TODO: replace this step with your build commands" - echo " The built file must be at: ${{ inputs.artifact-path }}" + mkdir -p dist + gh release download "$TAG" \ + --repo "$GITHUB_REPOSITORY" \ + --pattern "$ASSET_NAME" \ + --dir dist - name: Run RL malware scan id: rl-scan-conclusion - uses: auth0/devsecops-tooling/.github/actions/rl-scan@e29f26478db18ff0bcbe4bc447a8fbd54fbeec9e + uses: auth0/devsecops-tooling/.github/actions/rl-scan@e29f26478db18ff0bcbe4bc447a8fbd54fbeec9e # main with: # ── Artifact inputs ───────────────────────────────────────────────── - artifact-name: ${{ inputs.artifact-name }} - artifact-path: ${{ inputs.artifact-path }} - version: ${{ inputs.version }} + artifact-name: ${{ steps.asset.outputs.name }} + artifact-path: ${{ steps.asset.outputs.path }} + version: ${{ inputs.tag }} # ── Required secrets ──────────────────────────────────────────────── RLSECURE_LICENSE: ${{ secrets.RLSECURE_LICENSE }} RLSECURE_SITE_KEY: ${{ secrets.RLSECURE_SITE_KEY }} From 0e9de4b4d6152b02d0a888f191cff2bc7228c11f Mon Sep 17 00:00:00 2001 From: Kunal Dawar Date: Mon, 19 Oct 2026 23:53:18 +0530 Subject: [PATCH 3/3] chore(security): clarify rl.yml caller comment --- .github/workflows/rl.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rl.yml b/.github/workflows/rl.yml index 7d390fe81..6f6234843 100644 --- a/.github/workflows/rl.yml +++ b/.github/workflows/rl.yml @@ -3,9 +3,10 @@ run-name: rl-scan ${{ inputs.asset-suffix }} # Reusable malware-scan workflow for the release pipeline. It downloads one # published release archive and scans it with the ReversingLabs rl-scan action from -# auth0/devsecops-tooling. The caller runs it once per archive. +# auth0/devsecops-tooling. It scans one archive per call, so release.yml calls it +# from a matrix with one entry for each OS and architecture. # -# Caller pattern: +# Caller pattern (single archive; release.yml uses a matrix of all six): # jobs: # rl-scan: # needs: goreleaser