Skip to content

Commit 6e900c9

Browse files
authored
feat: refine action for enhanced security (#40)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent f006868 commit 6e900c9

3 files changed

Lines changed: 160 additions & 99 deletions

File tree

.github/workflows/map-deploy-to-develop-template.yml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ jobs:
2222
contents: read
2323

2424
steps:
25+
- name: Checkout the action from the current branch
26+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
27+
with:
28+
sparse-checkout: action.yml
29+
sparse-checkout-cone-mode: false
30+
path: scancode-action
31+
persist-credentials: false
32+
2533
- name: Checkout repository
2634
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2735
with:
@@ -32,19 +40,19 @@ jobs:
3240
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
3341
with:
3442
name: ${{ inputs['artifact-name'] }}
35-
path: ../scancode-inputs/
43+
path: scancode-inputs/
3644

3745
- name: Prepare D2D inputs
3846
shell: bash
3947
run: |
40-
for file in ../scancode-inputs/*; do
48+
for file in scancode-inputs/*; do
4149
base=$(basename "$file")
42-
mv "$file" "../scancode-inputs/to_$base"
50+
mv "$file" "scancode-inputs/to_$base"
4351
done
44-
git archive --format=tar.gz -o ../scancode-inputs/from.tar.gz HEAD
52+
git archive --format=tar.gz -o scancode-inputs/from.tar.gz HEAD
4553
4654
- name: Run D2D pipeline
47-
uses: aboutcode-org/scancode-action@main
55+
uses: ./scancode-action
4856
with:
4957
pipelines: ${{ inputs.steps && format('map_deploy_to_develop:%s', inputs.steps) || 'map_deploy_to_develop' }}
50-
inputs-path: ../scancode-inputs
58+
inputs-path: scancode-inputs
Lines changed: 57 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,58 @@
1-
name: Run source to binary mapping on boolean.py
1+
# Replace the whl build step by pre-built file
22

3-
on:
4-
workflow_dispatch:
5-
pull_request:
6-
push:
7-
branches:
8-
- main
9-
10-
jobs:
11-
build-python-wheel:
12-
name: Build python wheel
13-
runs-on: ubuntu-24.04
14-
permissions:
15-
contents: read
16-
17-
steps:
18-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
19-
with:
20-
repository: bastikr/boolean.py
21-
persist-credentials: false
22-
23-
- name: Set up Python
24-
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
25-
with:
26-
python-version: 3.12
27-
28-
- name: Install pypa/build and twine
29-
run: python -m pip install --user --upgrade build twine packaging pip setuptools
30-
31-
- name: Build a binary wheel
32-
run: python -m build --wheel --outdir dist/
33-
34-
- name: Upload wheel
35-
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
36-
with:
37-
name: wheel_archives
38-
path: dist/*.whl
39-
40-
map-source-binary:
41-
name: Generate source to binary mapping
42-
needs: build-python-wheel
43-
uses: ./.github/workflows/map-deploy-to-develop-template.yml
44-
with:
45-
artifact-name: wheel_archives
46-
repository: bastikr/boolean.py
47-
steps: "python"
3+
#name: Run source to binary mapping on boolean.py
4+
#
5+
#on:
6+
# workflow_dispatch:
7+
# pull_request:
8+
# push:
9+
# branches:
10+
# - main
11+
#
12+
#jobs:
13+
# build-python-wheel:
14+
# name: Build python wheel
15+
# runs-on: ubuntu-24.04
16+
# permissions:
17+
# contents: read
18+
#
19+
# steps:
20+
# - name: Checkout repository
21+
# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
22+
# with:
23+
# repository: ${{ inputs.repository || github.repository }}
24+
# persist-credentials: false
25+
#
26+
# - name: Checkout the action from the current branch
27+
# uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28+
# with:
29+
# sparse-checkout: action.yml
30+
# sparse-checkout-cone-mode: false
31+
# path: scancode-action
32+
# persist-credentials: false
33+
#
34+
# - name: Set up Python
35+
# uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
36+
# with:
37+
# python-version: 3.12
38+
#
39+
# - name: Install pypa/build and twine
40+
# run: python -m pip install --user --upgrade build twine packaging pip setuptools
41+
#
42+
# - name: Build a binary wheel
43+
# run: python -m build --wheel --outdir dist/
44+
#
45+
# - name: Upload wheel
46+
# uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
47+
# with:
48+
# name: wheel_archives
49+
# path: dist/*.whl
50+
#
51+
# map-source-binary:
52+
# name: Generate source to binary mapping
53+
# needs: build-python-wheel
54+
# uses: ./.github/workflows/map-deploy-to-develop-template.yml
55+
# with:
56+
# artifact-name: wheel_archives
57+
# repository: bastikr/boolean.py
58+
# steps: "python"

action.yml

Lines changed: 89 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -52,63 +52,69 @@ inputs:
5252
runs:
5353
using: "composite"
5454
steps:
55-
- uses: actions/setup-python@v5
55+
- name: Set up Python
56+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
5657
with:
5758
python-version: ${{ inputs.python-version }}
5859

5960
- name: Set up environment
6061
shell: bash
62+
env:
63+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
6164
run: |
62-
echo "SECRET_KEY=$(openssl rand -base64 32)" >> $GITHUB_ENV
63-
echo "SCANCODEIO_DB_NAME=scancodeio" >> $GITHUB_ENV
64-
echo "SCANCODEIO_DB_USER=scancodeio" >> $GITHUB_ENV
65-
echo "SCANCODEIO_DB_PASSWORD=scancodeio" >> $GITHUB_ENV
65+
echo "SECRET_KEY=$(openssl rand -base64 32)" >> "$GITHUB_ENV"
66+
echo "SCANCODEIO_DB_NAME=scancodeio" >> "$GITHUB_ENV"
67+
echo "SCANCODEIO_DB_USER=scancodeio" >> "$GITHUB_ENV"
68+
echo "SCANCODEIO_DB_PASSWORD=scancodeio" >> "$GITHUB_ENV"
6669
# Sanitize project name for artifact usage
67-
SAFE_PROJECT_NAME="${{ inputs.project-name }}"
68-
SAFE_PROJECT_NAME="${SAFE_PROJECT_NAME//[^a-zA-Z0-9._-]/_}"
69-
echo "SAFE_PROJECT_NAME=$SAFE_PROJECT_NAME" >> $GITHUB_ENV
70+
SAFE_PROJECT_NAME="${INPUT_PROJECT_NAME//[^a-zA-Z0-9._-]/_}"
71+
echo "SAFE_PROJECT_NAME=$SAFE_PROJECT_NAME" >> "$GITHUB_ENV"
7072
7173
- name: Detect if ScanCode.io is already installed
7274
shell: bash
7375
run: |
7476
if command -v scanpipe &> /dev/null; then
7577
echo "ScanCode.io already installed."
76-
echo "SCANCODEIO_IS_INSTALLED=true" >> $GITHUB_ENV
78+
echo "SCANCODEIO_IS_INSTALLED=true" >> "$GITHUB_ENV"
7779
else
7880
echo "ScanCode.io not found."
79-
echo "SCANCODEIO_IS_INSTALLED=false" >> $GITHUB_ENV
81+
echo "SCANCODEIO_IS_INSTALLED=false" >> "$GITHUB_ENV"
8082
fi
8183
8284
- name: Start and setup the PostgreSQL service
8385
if: env.SCANCODEIO_IS_INSTALLED != 'true'
8486
shell: bash
8587
run: |
8688
sudo systemctl start postgresql.service
87-
sudo -u postgres createuser --no-createrole --no-superuser --login --inherit --createdb ${{ env.SCANCODEIO_DB_USER }}
88-
sudo -u postgres psql -c "ALTER USER ${{ env.SCANCODEIO_DB_USER }} WITH ENCRYPTED PASSWORD '${{ env.SCANCODEIO_DB_PASSWORD }}'"
89-
sudo -u postgres createdb --owner=scancodeio --encoding=UTF-8 ${{ env.SCANCODEIO_DB_NAME }}
89+
sudo -u postgres createuser --no-createrole --no-superuser --login --inherit --createdb "$SCANCODEIO_DB_USER"
90+
sudo -u postgres psql -c "ALTER USER $SCANCODEIO_DB_USER WITH ENCRYPTED PASSWORD '$SCANCODEIO_DB_PASSWORD'"
91+
sudo -u postgres createdb --owner=scancodeio --encoding=UTF-8 "$SCANCODEIO_DB_NAME"
9092
9193
- name: Generate scancodeio pip install argument
9294
if: env.SCANCODEIO_IS_INSTALLED != 'true'
9395
shell: bash
96+
env:
97+
INPUT_EXTRAS: ${{ inputs.scancodeio-extras }}
9498
run: |
9599
SCANCODEIO_PIP_PACKAGE_ARG="scancodeio"
96-
TRIMMED_EXTRAS="$(echo "${{ inputs.scancodeio-extras }}" | tr -d '[:space:]')"
100+
TRIMMED_EXTRAS="$(echo "$INPUT_EXTRAS" | tr -d '[:space:]')"
97101
if [ -n "$TRIMMED_EXTRAS" ]; then
98102
SCANCODEIO_PIP_PACKAGE_ARG+="[$TRIMMED_EXTRAS]"
99103
fi
100-
echo "SCANCODEIO_PIP_PACKAGE_ARG=${SCANCODEIO_PIP_PACKAGE_ARG}" >> $GITHUB_ENV
104+
echo "SCANCODEIO_PIP_PACKAGE_ARG=${SCANCODEIO_PIP_PACKAGE_ARG}" >> "$GITHUB_ENV"
101105
102106
- name: Install ScanCode.io (only if not already installed)
103107
if: env.SCANCODEIO_IS_INSTALLED != 'true'
104108
shell: bash
109+
env:
110+
INPUT_REPO_BRANCH: ${{ inputs.scancodeio-repo-branch }}
105111
run: |
106-
if [ -z "${{ inputs.scancodeio-repo-branch }}" ]; then
107-
echo "Installing the latest ${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} release from PyPI"
108-
pip install --upgrade "${{ env.SCANCODEIO_PIP_PACKAGE_ARG }}"
112+
if [ -z "$INPUT_REPO_BRANCH" ]; then
113+
echo "Installing the latest ${SCANCODEIO_PIP_PACKAGE_ARG} release from PyPI"
114+
pip install --upgrade "$SCANCODEIO_PIP_PACKAGE_ARG"
109115
else
110-
echo "Installing ${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} from the GitHub branch: ${{ inputs.scancodeio-repo-branch }}"
111-
pip install "${{ env.SCANCODEIO_PIP_PACKAGE_ARG }} @ git+https://github.com/aboutcode-org/scancode.io.git@${{ inputs.scancodeio-repo-branch }}"
116+
echo "Installing ${SCANCODEIO_PIP_PACKAGE_ARG} from the GitHub branch: $INPUT_REPO_BRANCH"
117+
pip install "${SCANCODEIO_PIP_PACKAGE_ARG} @ git+https://github.com/aboutcode-org/scancode.io.git@${INPUT_REPO_BRANCH}"
112118
fi
113119
114120
- name: Run migrations to prepare the database
@@ -118,55 +124,79 @@ runs:
118124

119125
- name: Generate `--pipeline` CLI arguments
120126
shell: bash
127+
env:
128+
INPUT_PIPELINES: ${{ inputs.pipelines }}
121129
run: |
122-
IFS=',' read -ra PIPELINES <<< "${{ inputs.pipelines }}"
130+
IFS=',' read -ra PIPELINES <<< "$INPUT_PIPELINES"
123131
PIPELINE_CLI_ARGS=""
124132
for pipeline in "${PIPELINES[@]}"; do
125133
PIPELINE_CLI_ARGS+=" --pipeline $pipeline"
126134
done
127-
echo "PIPELINE_CLI_ARGS=${PIPELINE_CLI_ARGS}" >> $GITHUB_ENV
135+
echo "PIPELINE_CLI_ARGS=${PIPELINE_CLI_ARGS}" >> "$GITHUB_ENV"
128136
129137
- name: Generate `--input-url` CLI arguments
130138
shell: bash
139+
env:
140+
INPUT_URLS: ${{ inputs.input-urls }}
131141
run: |
132142
INPUT_URL_CLI_ARGS=""
133-
for url in ${{ inputs.input-urls }}; do
134-
INPUT_URL_CLI_ARGS+=" --input-url $url"
143+
for url in $INPUT_URLS; do
144+
if [[ "$url" =~ ^(https?|docker|pkg): ]]; then
145+
INPUT_URL_CLI_ARGS+=" --input-url $url"
146+
else
147+
echo "::warning::Skipping unsupported URL scheme: $url"
148+
fi
135149
done
136-
echo "INPUT_URL_CLI_ARGS=${INPUT_URL_CLI_ARGS}" >> $GITHUB_ENV
150+
echo "INPUT_URL_CLI_ARGS=${INPUT_URL_CLI_ARGS}" >> "$GITHUB_ENV"
137151
138152
- name: Create project
139153
shell: bash
154+
env:
155+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
140156
run: |
141-
scanpipe create-project ${{ inputs.project-name }} \
142-
${{ env.PIPELINE_CLI_ARGS }} \
143-
${{ env.INPUT_URL_CLI_ARGS }}
157+
scanpipe create-project "$INPUT_PROJECT_NAME" \
158+
$PIPELINE_CLI_ARGS \
159+
$INPUT_URL_CLI_ARGS
144160
145161
- name: Set project work directory in the environment
146162
shell: bash
163+
env:
164+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
147165
run: |
148-
project_status=$(scanpipe status --project ${{ inputs.project-name }})
166+
project_status=$(scanpipe status --project "$INPUT_PROJECT_NAME")
149167
work_directory=$(echo "$project_status" | grep -oP 'Work directory:\s*\K[^\n]+')
150-
echo "PROJECT_WORK_DIRECTORY=$work_directory" >> $GITHUB_ENV
168+
echo "PROJECT_WORK_DIRECTORY=$work_directory" >> "$GITHUB_ENV"
151169
152170
- name: Copy input files to project work directory
153171
if: ${{ !inputs.input-urls }}
154172
shell: bash
173+
env:
174+
INPUT_INPUTS_PATH: ${{ inputs.inputs-path }}
175+
WORKSPACE: ${{ github.workspace }}
155176
run: |
156-
SOURCE_PATH="${{ inputs.inputs-path }}"
157-
[[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="${{ github.workspace }}/$SOURCE_PATH"
158-
DESTINATION_PATH="${{ env.PROJECT_WORK_DIRECTORY }}/input/"
177+
SOURCE_PATH="$INPUT_INPUTS_PATH"
178+
[[ "$SOURCE_PATH" != /* ]] && SOURCE_PATH="${WORKSPACE}/$SOURCE_PATH"
179+
180+
# Prevent path traversal outside the workspace
181+
REAL_SOURCE=$(realpath -m "$SOURCE_PATH")
182+
REAL_WORKSPACE=$(realpath "$WORKSPACE")
183+
if [[ "$REAL_SOURCE" != "$REAL_WORKSPACE"* ]]; then
184+
echo "::error::inputs-path resolves outside the workspace. Aborting."
185+
exit 1
186+
fi
187+
188+
DESTINATION_PATH="${PROJECT_WORK_DIRECTORY}/input/"
159189
mkdir -p "$DESTINATION_PATH"
160190
161191
if [ -d "$SOURCE_PATH" ]; then
162192
if [ "$(ls -A "$SOURCE_PATH")" ]; then
163-
echo "Copying contents of directory: $SOURCE_PATH $DESTINATION_PATH"
193+
echo "Copying contents of directory: $SOURCE_PATH -> $DESTINATION_PATH"
164194
cp -r "$SOURCE_PATH"/* "$DESTINATION_PATH"
165195
else
166196
echo "Input directory '$SOURCE_PATH' is empty, nothing to copy."
167197
fi
168198
elif [[ -f "$SOURCE_PATH" ]]; then
169-
echo "Copying file: $SOURCE_PATH $DESTINATION_PATH"
199+
echo "Copying file: $SOURCE_PATH -> $DESTINATION_PATH"
170200
cp "$SOURCE_PATH" "$DESTINATION_PATH"
171201
fi
172202
@@ -176,17 +206,23 @@ runs:
176206
177207
- name: Run the pipelines
178208
shell: bash
179-
run: scanpipe execute --project ${{ inputs.project-name }} --no-color
209+
env:
210+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
211+
run: scanpipe execute --project "$INPUT_PROJECT_NAME" --no-color
180212

181213
- name: Generate outputs
182214
id: scanpipe
183215
shell: bash
184-
run: scanpipe output
185-
--project ${{ inputs.project-name }}
186-
--format ${{ inputs.output-formats }}
216+
env:
217+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
218+
INPUT_OUTPUT_FORMATS: ${{ inputs.output-formats }}
219+
run: |
220+
scanpipe output \
221+
--project "$INPUT_PROJECT_NAME" \
222+
--format $INPUT_OUTPUT_FORMATS
187223
188224
- name: Upload outputs
189-
uses: actions/upload-artifact@v4
225+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
190226
id: artifact-upload-step
191227
with:
192228
# Include the project name in case of multiple runs of the action
@@ -197,13 +233,19 @@ runs:
197233
- name: Check compliance
198234
if: inputs.check-compliance == 'true'
199235
shell: bash
236+
env:
237+
INPUT_PROJECT_NAME: ${{ inputs.project-name }}
238+
INPUT_FAIL_LEVEL: ${{ inputs.compliance-fail-level }}
239+
INPUT_FAIL_ON_VULNS: ${{ inputs.compliance-fail-on-vulnerabilities }}
200240
run: |
201-
cmd="scanpipe check-compliance \
202-
--project ${{ inputs.project-name }} \
203-
--fail-level ${{ inputs.compliance-fail-level }}"
204-
205-
if [[ "${{ inputs.compliance-fail-on-vulnerabilities }}" == "true" ]]; then
206-
cmd="$cmd --fail-on-vulnerabilities"
241+
cmd=(
242+
scanpipe check-compliance
243+
--project "$INPUT_PROJECT_NAME"
244+
--fail-level "$INPUT_FAIL_LEVEL"
245+
)
246+
247+
if [[ "$INPUT_FAIL_ON_VULNS" == "true" ]]; then
248+
cmd+=(--fail-on-vulnerabilities)
207249
fi
208250
209-
eval "$cmd"
251+
"${cmd[@]}"

0 commit comments

Comments
 (0)