diff --git a/.chainguard/source.yaml b/.chainguard/source.yaml index 06eb69aa9..4f5bd2a8e 100644 --- a/.chainguard/source.yaml +++ b/.chainguard/source.yaml @@ -8,8 +8,11 @@ spec: identities: - subjectRegExp: .+@gmail.com$ # Allow commits signed with Gmail accounts, not ideal, for testing purposes only. issuer: https://github.com/login/oauth + - issuer: https://token.actions.githubusercontent.com + # again, not ideal, for testing purposes only. + subjectRegExp: https://github.com/Pinguteca/eShop/.github/workflows/.+$ ctlog: url: https://rekor.sigstore.dev - key: - # Allow commits signed by GitHub. + # Allow commits signed by GitHub, e.g. the UI kms: https://github.com/web-flow.gpg \ No newline at end of file diff --git a/.github/actions.lock.json b/.github/actions.lock.json index 9b566d94c..b35d08c8a 100644 --- a/.github/actions.lock.json +++ b/.github/actions.lock.json @@ -1,6 +1,6 @@ { "version": 1, - "generated": "2026-01-11T21:02:15.616Z", + "generated": "2026-02-01T23:20:49.722Z", "actions": { "step-security/harden-runner": [ { @@ -24,6 +24,12 @@ "sha": "3e8a2a226fad9e1ecbf2d359b8a7697554a4ac6d", "integrity": "sha256-696e56578f4dd56549ae896605cf415b78f3432bb0cbd42890a48975f84d3503", "dependencies": [] + }, + { + "version": "18e5e3427cf9d6bcfbefe60dca48e40292f000c5", + "sha": "18e5e3427cf9d6bcfbefe60dca48e40292f000c5", + "integrity": "sha256-61939c587c8882b626cc98e46cfb424dfdc4f26cd9b9dd51721016cab919fba9", + "dependencies": [] } ], "calibreapp/image-actions": [ @@ -94,11 +100,19 @@ "dependencies": [] } ], - "gjtorikian/gh-actions-lockfile": [ + "dorny/paths-filter": [ { - "version": "24be31e941fc36df78f82762cd45c28b4cbcaedd", - "sha": "24be31e941fc36df78f82762cd45c28b4cbcaedd", - "integrity": "sha256-6a3612083812bfbf22ef48e284a93dbf82766dea50126f85d2160ae092018087", + "version": "de90cc6fb38fc0963ad72b210f1f284cd68cea36", + "sha": "de90cc6fb38fc0963ad72b210f1f284cd68cea36", + "integrity": "sha256-07c63522e75cd14669d8202d83e0823a170f8d05a89a488729eb60446f9f7af4", + "dependencies": [] + } + ], + "pnpm/action-setup": [ + { + "version": "41ff72655975bd51cab0327fa583b6e92b6d3061", + "sha": "41ff72655975bd51cab0327fa583b6e92b6d3061", + "integrity": "sha256-ff9db052ccf236e3d7520da06ef8fdd687abdb9b4c1b470031a96912fa937a68", "dependencies": [] } ], @@ -110,6 +124,14 @@ "dependencies": [] } ], + "gjtorikian/gh-actions-lockfile": [ + { + "version": "24be31e941fc36df78f82762cd45c28b4cbcaedd", + "sha": "24be31e941fc36df78f82762cd45c28b4cbcaedd", + "integrity": "sha256-6a3612083812bfbf22ef48e284a93dbf82766dea50126f85d2160ae092018087", + "dependencies": [] + } + ], "actions/configure-pages": [ { "version": "983d7736d9b0ae728b81ab479565c72886d7745b", diff --git a/.github/workflows/img-optimization.yml b/.github/workflows/img-optimization.yml index 214be3a22..60b4ddf35 100644 --- a/.github/workflows/img-optimization.yml +++ b/.github/workflows/img-optimization.yml @@ -5,7 +5,7 @@ # - at 11 PM every Sunday in anything gets missed with any of the above scenarios # For Pull Requests, the images are added to the PR. # For other scenarios, a new PR will be opened if any images are compressed. -name: Compress images +name: Strip metadata and optimize images with Calibre on: pull_request: types: [reopened, ready_for_review, review_requested] @@ -78,7 +78,7 @@ jobs: with: # For non-Pull Requests, run in compressOnly mode and we'll PR after. compressOnly: ${{ github.event_name != 'pull_request' }} - minPctChange: "10" + minPctChange: "0" jpegQuality: "85" jpegProgressive: true pngQuality: "80" diff --git a/.github/workflows/svg-optimization.yml b/.github/workflows/svg-optimization.yml new file mode 100644 index 000000000..a4d512090 --- /dev/null +++ b/.github/workflows/svg-optimization.yml @@ -0,0 +1,102 @@ +name: Sanitize, strip metadata and optimize SVGs +on: + pull_request: + types: [reopened, ready_for_review, review_requested] + branches: [master, main, develop] + paths: + - "**.svg" + - "svgo.config.mjs" + # TODO: adjust workflow for on-demand runs and scheduling + workflow_dispatch: + schedule: + - cron: "00 23 * * 0" + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + svgOptimization: + name: Sanitize and optimize SVGs + runs-on: ubuntu-latest + timeout-minutes: 20 + + permissions: + contents: write # to write commits + id-token: write # Enable OIDC for Gitsign + + steps: + - name: Harden Runner + uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0 + with: + egress-policy: audit + disable-telemetry: "true" + disable-sudo: "true" # runs on container so same issue as zizmor + - name: Optimize Git config for CI + run: | + # Disable compression for faster network transfer. + git config --global core.compression 0 + # Turn off fsync + git config --global core.fsync -all + - name: Checkout Branch + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + ref: ${{ github.event.pull_request.head.sha }} + persist-credentials: true + sparse-checkout: | + **.svg + svgo.config.mjs + sparse-checkout-cone-mode: false + filter: "blob:none" + # TODO: skip for on-demand and scheduled runs + - name: Detect changed SVGs + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: svg_changes + with: + # order for choosing the correct base ref: + # PR base branch (when running on pull_request) + # fallback to current branch name + base: ${{ github.event.pull_request.base.ref || github.ref_name }} + list-files: shell + # Filter only added or modified svg files + filters: | + svg: + - added|modified: '**/*.svg' + - name: Setup Gitsign for commit signing + if: steps.svg_changes.outputs.svg == 'true' + uses: chainguard-dev/actions/setup-gitsign@18e5e3427cf9d6bcfbefe60dca48e40292f000c5 # v1.5.13 + - name: Install pnpm + if: steps.svg_changes.outputs.svg == 'true' + uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 + with: + version: 10 + standalone: false + - name: Use Node.js + if: steps.svg_changes.outputs.svg == 'true' + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 + with: + node-version: 24.12.0 + - name: Install SVGO + if: steps.svg_changes.outputs.svg == 'true' + run: | + # 21 days in minutes to avoid installing potentially compromised versions + pnpm config set -g minimumReleaseAge 30240 + pnpm install -g svgo@4 + - name: Sanitize, strip metadata and optimize SVGs + if: steps.svg_changes.outputs.svg == 'true' + env: + STEPS_SVG_CHANGES_OUTPUTS_SVG_FILES: ${{ steps.svg_changes.outputs.svg_files }} + run: | + echo "### :white_check_mark: **SVGO optimization results**" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + svgo --no-color --multipass --final-newline --eol lf --config svgo.config.mjs ${STEPS_SVG_CHANGES_OUTPUTS_SVG_FILES} >> $GITHUB_STEP_SUMMARY + - uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 + if: steps.svg_changes.outputs.svg == 'true' + with: + commit_message: | + chore(svg): sanitize and optimize SVGO + + changed files: ${{ steps.svg_changes.outputs.svg_files }} + file_pattern: "**.svg" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5939c4d31..106e36013 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,3 +62,13 @@ repos: pass_filenames: true types: [png] stages: ["pre-push"] + - repo: local + hooks: + - id: svgo + name: SVGO optimization + description: Optimize SVG files using SVGO. + language: node + entry: svgo + args: ["--multipass", "--quiet", "--config", "--final-newline", "--eol", "lf", "svgo.config.mjs"] + types: [svg] + stages: ["pre-push"] diff --git a/ghalint.yaml b/ghalint.yaml index 7200427e9..f944d7391 100644 --- a/ghalint.yaml +++ b/ghalint.yaml @@ -8,3 +8,6 @@ excludes: - policy_name: checkout_persist_credentials_should_be_false workflow_file_path: .github/workflows/verify-gha-integrity.yml job_name: update-lockfile + - policy_name: checkout_persist_credentials_should_be_false + workflow_file_path: .github/workflows/svg-optimization.yml + job_name: svgOptimization \ No newline at end of file diff --git a/hush.svg b/hush.svg new file mode 100644 index 000000000..a4343a0c7 --- /dev/null +++ b/hush.svg @@ -0,0 +1 @@ +Onload test diff --git a/src/ClientApp/Resources/Images/test3.svg b/src/ClientApp/Resources/Images/test3.svg new file mode 100644 index 000000000..28f974346 --- /dev/null +++ b/src/ClientApp/Resources/Images/test3.svg @@ -0,0 +1 @@ + diff --git a/svgo.config.mjs b/svgo.config.mjs new file mode 100644 index 000000000..c4caf7809 --- /dev/null +++ b/svgo.config.mjs @@ -0,0 +1,56 @@ +export default { + multipass: true, + js2svg: { pretty: false, indent: 0 }, + plugins: [ + { + name: 'preset-default', + params: { + overrides: { + }, + }, + }, + // sanitze SVGs by removing potentially dangerous elements/attributes + // remove