diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fbf5af8a..8738d373 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -6,7 +6,7 @@ "args": { "DOCKER_GID": "${env:DOCKER_GID:}", "IMAGE_NAME": "node_24_python_3_14", - "IMAGE_VERSION": "v1.2.0", + "IMAGE_VERSION": "v1.4.4", "USER_UID": "${localEnv:USER_ID:}", "USER_GID": "${localEnv:GROUP_ID:}" } diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..0492a665 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# restrict access to approving workflow changes +.github/workflows/ @NHSDigital/eps-admins diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4cd72bc..24a4c831 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,17 +4,23 @@ on: push: branches: [main] -env: - BRANCH_NAME: ${{ github.ref_name }} - +permissions: {} jobs: get_config_values: - uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@b0172dbdb3af4ae232873106553c316d79d784fc + uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 with: verify_published_from_main_image: true + permissions: + attestations: read + contents: read + packages: read quality_checks: - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 needs: [get_config_values] + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} run_docker_scan: false @@ -23,14 +29,17 @@ jobs: tag_release: needs: [quality_checks, get_config_values] - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 + permissions: + contents: write + id-token: write + packages: write with: dry_run: true pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} branch_name: main publish_packages: packages/cdkConstructs,packages/deploymentUtils tag_format: ${{ needs.get_config_values.outputs.tag_format }} - secrets: inherit package_npm_code: needs: [quality_checks, get_config_values] diff --git a/.github/workflows/package_npm_code.yml b/.github/workflows/package_npm_code.yml index dd008c52..79295e59 100644 --- a/.github/workflows/package_npm_code.yml +++ b/.github/workflows/package_npm_code.yml @@ -6,7 +6,7 @@ on: pinned_image: type: string required: true - +permissions: {} jobs: package_npm_code: runs-on: ubuntu-22.04 @@ -23,7 +23,7 @@ jobs: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with: - ref: ${{ env.BRANCH_NAME }} + persist-credentials: false - name: Install dependencies run: | diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 9913c9a6..8ab14396 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -4,59 +4,42 @@ on: pull_request: branches: [main] -env: - BRANCH_NAME: ${{ github.event.pull_request.head.ref }} - +permissions: {} jobs: get_config_values: - uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@b0172dbdb3af4ae232873106553c316d79d784fc + uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 with: verify_published_from_main_image: false + permissions: + attestations: read + contents: read + packages: read dependabot-auto-approve-and-merge: needs: quality_checks - uses: NHSDigital/eps-common-workflows/.github/workflows/dependabot-auto-approve-and-merge.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/dependabot-auto-approve-and-merge.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 + permissions: + contents: write + pull-requests: write secrets: AUTOMERGE_APP_ID: ${{ secrets.AUTOMERGE_APP_ID }} AUTOMERGE_PEM: ${{ secrets.AUTOMERGE_PEM }} pr_title_format_check: - uses: NHSDigital/eps-common-workflows/.github/workflows/pr_title_check.yml@b0172dbdb3af4ae232873106553c316d79d784fc + uses: NHSDigital/eps-common-workflows/.github/workflows/pr_title_check.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 + permissions: + pull-requests: write quality_checks: - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 needs: [get_config_values] + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} run_docker_scan: false secrets: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - get_issue_number: - runs-on: ubuntu-22.04 - outputs: - issue_number: ${{steps.get_issue_number.outputs.result}} - - steps: - - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd - name: get issue number - id: get_issue_number - with: - script: | - if (context.issue.number) { - // Return issue number if present - return context.issue.number; - } else { - // Otherwise return issue number from commit - return ( - await github.rest.repos.listPullRequestsAssociatedWithCommit({ - commit_sha: context.sha, - owner: context.repo.owner, - repo: context.repo.repo, - }) - ).data[0].number; - } - result-encoding: string - - package_npm_code: needs: [quality_checks, get_config_values] uses: ./.github/workflows/package_npm_code.yml @@ -65,11 +48,14 @@ jobs: tag_release: needs: [get_config_values] - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 + permissions: + contents: write + id-token: write + packages: write with: dry_run: true pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} branch_name: ${{ github.event.pull_request.head.ref }} publish_packages: packages/cdkConstructs,packages/deploymentUtils tag_format: ${{ needs.get_config_values.outputs.tag_format }} - secrets: inherit diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index be3a34cc..f8ee5074 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,17 +5,23 @@ on: schedule: - cron: "0 8 * * 3" -env: - BRANCH_NAME: ${{ github.ref_name }} - +permissions: {} jobs: get_config_values: - uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@b0172dbdb3af4ae232873106553c316d79d784fc + uses: NHSDigital/eps-common-workflows/.github/workflows/get-repo-config.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 with: verify_published_from_main_image: true + permissions: + attestations: read + contents: read + packages: read quality_checks: - uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/quality-checks-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 needs: [get_config_values] + permissions: + contents: read + id-token: write + packages: read with: pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} run_docker_scan: false @@ -24,11 +30,14 @@ jobs: tag_release: needs: [quality_checks, get_config_values] - uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@352f15f692c23b18f67215ad858f27b06a878717 + uses: NHSDigital/eps-common-workflows/.github/workflows/tag-release-devcontainer.yml@c8f899f30a6a726859b0277faa73cd9ff7f4de20 + permissions: + contents: write + id-token: write + packages: write with: dry_run: false pinned_image: ${{ needs.get_config_values.outputs.pinned_image }} branch_name: main publish_packages: packages/cdkConstructs,packages/deploymentUtils tag_format: ${{ needs.get_config_values.outputs.tag_format }} - secrets: inherit diff --git a/.github/workflows/sync_copilot.yml b/.github/workflows/sync_copilot.yml index 4cf9edce..d264d468 100644 --- a/.github/workflows/sync_copilot.yml +++ b/.github/workflows/sync_copilot.yml @@ -4,7 +4,7 @@ on: workflow_dispatch: schedule: - cron: "0 6 * * 1" - +permissions: {} jobs: sync-copilot-instructions: runs-on: ubuntu-22.04 diff --git a/.gitignore b/.gitignore index 9cab097d..d211217a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ _site/ vendor .trivy_out/ *.tgz +.sbom/ diff --git a/.grype.yaml b/.grype.yaml new file mode 100644 index 00000000..b2d95da6 --- /dev/null +++ b/.grype.yaml @@ -0,0 +1,10 @@ +ignore: + # picomatch + - vulnerability: GHSA-c2c7-rcm5-vvqj + # flatted + - vulnerability: GHSA-rf6f-7fwh-wjgh + # minimatch + - vulnerability: GHSA-3ppc-4f35-3m26 + - vulnerability: GHSA-7r86-cg39-jmmj + - vulnerability: GHSA-23c5-xmqv-rm74 + - vulnerability: GHSA-25h7-pfq9-p65f diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f265b9d..b52cd9f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,6 +23,14 @@ repos: - repo: local hooks: + - id: grype-scan-local + name: Grype scan local changes + entry: make + args: ["grype-scan-local"] + language: system + pass_filenames: false + always_run: true + - id: check-commit-signing name: Check commit signing description: Ensures that commits are GPG signed diff --git a/.trivyignore.yaml b/.trivyignore.yaml deleted file mode 100644 index 34f78521..00000000 --- a/.trivyignore.yaml +++ /dev/null @@ -1,82 +0,0 @@ -vulnerabilities: - - id: CVE-2025-64756 - statement: downstream dependency for glob - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-23745 - statement: downstream dependency for tar - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-23950 - statement: downstream dependency for tar - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-24842 - statement: downstream dependency for tar - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-25547 - statement: downstream dependency for @isaacs/brace-expansion - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-0775 - statement: downstream dependency for npmcli - waiting for new npm release - expired_at: 2026-06-01 - - id: CVE-2026-24049 - statement: downstream dependency for wheel - waiting for new python release - expired_at: 2026-06-01 - - id: CVE-2025-47907 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-58183 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-61729 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-61726 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-61728 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-61730 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2025-68121 - statement: downstream dependency for asdf/go - waiting for new asdf release - expired_at: 2026-06-01 - - id: CVE-2026-26278 - statement: fast-xml-parser node module - expired_at: 2026-06-01 - - id: CVE-2026-26996 - statement: minimatch node module - expired_at: 2026-06-01 - - id: CVE-2026-26960 - statement: tar node module - expired_at: 2026-06-01 - - id: CVE-2026-27903 - statement: Minimatch subdependency needed for aws-cdk-lib and jest. - expired_at: 2026-06-01 - - id: CVE-2026-27904 - statement: Minimatch subdependency needed for aws-cdk-lib and jest. - expired_at: 2026-06-01 - - id: CVE-2026-27606 - statement: Minimatch subdependency needed for aws-cdk-lib and jest. - expired_at: 2026-06-01 - - id: CVE-2026-29786 - statement: node-tar requrired dependency, and not a relelveant attack vector - expired_at: 2026-06-01 - - id: CVE-2026-31802 - statement: node-tar requrired dependency, and not a relelveant attack vector - expired_at: 2026-06-01 - - id: CVE-2026-25679 - statement: asdf go stdlib - expired_at: 2026-06-01 - - id: CVE-2026-27142 - statement: asdf go stdlib - expired_at: 2026-06-01 - - id: CVE-2026-27142 - statement: asdf go stdlib - expired_at: 2026-06-01 - - id: CVE-2026-32141 - statement: flatted - expired_at: 2026-06-01 - - id: CVE-2026-33036 - statement: fast-xml-parser vulnerability accepted as risk - dependency of aws-sdk/client-dynamodb and redocly - expired_at: 2026-04-01 diff --git a/Makefile b/Makefile index 892ce1c6..88b62e28 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ install: install-python install-hooks install-node install-node: - npm ci + npm ci --ignore-scripts true install-python: poetry install diff --git a/trivy.yaml b/trivy.yaml deleted file mode 100644 index eb243375..00000000 --- a/trivy.yaml +++ /dev/null @@ -1 +0,0 @@ -ignorefile: ".trivyignore.yaml" diff --git a/zizmor.yml b/zizmor.yml new file mode 100644 index 00000000..f7bf6a98 --- /dev/null +++ b/zizmor.yml @@ -0,0 +1,5 @@ +rules: + unpinned-images: + # these workflows use unpinned images because they are using a full image passed in that contains the tag + ignore: + - package_npm_code.yml:14:13