From 5f01c5666faf5b337f38398780f0e6734f32975a Mon Sep 17 00:00:00 2001 From: Thomas Boni Date: Wed, 29 Jul 2026 14:43:05 +0200 Subject: [PATCH 1/5] ci: add plumber security scan workflow Add an independent workflow that runs Plumber to scan the GitHub Actions workflows for CI/CD security issues on every push and pull request to main. The report is uploaded to the Security tab as SARIF. The check fails only when the Plumber Score drops below C. Publishing the score to the hosted badge service is left disabled. Signed-off-by: Thomas Boni --- .github/workflows/plumber.yml | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/plumber.yml diff --git a/.github/workflows/plumber.yml b/.github/workflows/plumber.yml new file mode 100644 index 0000000..0ecdb68 --- /dev/null +++ b/.github/workflows/plumber.yml @@ -0,0 +1,37 @@ +--- +name: plumber + +on: + push: + branches: [main] + pull_request: + branches: [main] + workflow_dispatch: + +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + scan: + name: Scan CI/CD workflows + runs-on: ubuntu-latest + permissions: + # To upload the SARIF report to the Security tab + security-events: write + contents: read + # id-token: write # required only when score-push is enabled (see PR description) + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Run Plumber + uses: getplumber/plumber@87ca135cc4566ba8e9065ea95b5d897232cdb208 # v0.4.16 + with: + # Fail the check only when the Plumber Score drops below C. + min-score: "C" + # score-push publishes a public A-E score badge to the hosted + # score service. Kept disabled here; see the PR description for + # the trade-offs before turning it on. + score-push: false From fdb276f3132b3bc185bc716fdd0c77d4e46c6236 Mon Sep 17 00:00:00 2001 From: Thomas Boni Date: Wed, 29 Jul 2026 14:43:05 +0200 Subject: [PATCH 2/5] ci: declare workflow permissions Add an explicit least-privilege permissions block to the linter, test and release workflows so the GITHUB_TOKEN no longer inherits the repository default scope. linter keeps contents: read plus statuses: write for super-linter, test keeps contents: read, and release keeps contents: write for the version bump, push and release steps. Signed-off-by: Thomas Boni --- .github/workflows/linter.yml | 4 ++++ .github/workflows/release.yml | 4 ++++ .github/workflows/test.yml | 3 +++ 3 files changed, 11 insertions(+) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index af5216b..5778cf3 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -3,6 +3,10 @@ name: Linter on: pull_request: branches: [main] +permissions: + contents: read + # super-linter reports the outcome of each linter as a commit status + statuses: write jobs: build: name: Lint Code Base diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bd4bed4..fb53458 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,6 +8,10 @@ on: description: 'Release version' required: true +# The job commits the version bump, pushes it and publishes the release. +permissions: + contents: write + env: JAVA_VERSION: '11' JAVA_DISTRO: 'zulu' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fac48bc..9784ef3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,6 +4,9 @@ on: pull_request: branches: [main] +permissions: + contents: read + env: JAVA_VERSION: '11' JAVA_DISTRO: 'zulu' From 3ac481c15af47ed717e61a751350a9c618d12e63 Mon Sep 17 00:00:00 2001 From: Thomas Boni Date: Wed, 29 Jul 2026 14:43:05 +0200 Subject: [PATCH 3/5] ci: add plumber configuration Add .plumber.yaml based on Plumber's github defaults, with every control kept enabled so none is silently turned off. Code owner approval is not part of this project's branch protection policy, so branchMustBeProtected. codeOwnerApprovalRequired is set to false. Signed-off-by: Thomas Boni --- .plumber.yaml | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 .plumber.yaml diff --git a/.plumber.yaml b/.plumber.yaml new file mode 100644 index 0000000..7a34652 --- /dev/null +++ b/.plumber.yaml @@ -0,0 +1,152 @@ +# Plumber configuration for the sdk-java repository. +# Based on Plumber's built-in defaults (github provider only); every control +# is listed explicitly so none is silently disabled. The only customization is +# the branch protection policy below. +version: "2.0" +github: + controls: + containerImageMustNotUseForbiddenTags: + enabled: true + tags: + - latest + - dev + - development + - staging + - main + - master + containerImagesMustBePinnedByDigest: true + branchMustBeProtected: + enabled: true + namePatterns: + - main + - master + - release/* + - production + - dev + defaultMustBeProtected: true + allowForcePush: false + # This project does not use a CODEOWNERS-based review process, so + # code owner approval is not part of its branch protection policy. + codeOwnerApprovalRequired: false + externalRefsMustNotCollide: + enabled: true + pipelineMustNotEnableDebugTrace: + enabled: true + forbiddenVariables: + - ACTIONS_STEP_DEBUG + - ACTIONS_RUNNER_DEBUG + securityJobsMustNotBeWeakened: + enabled: true + securityJobPatterns: + - '*codeql*' + - '*dependency-review*' + - '*trufflehog*' + - '*gitleaks*' + - '*osv-scanner*' + - '*-sast' + - '*-sast-*' + - '*-scan' + - '*scan*' + - '*-security' + - '*-security-*' + - '*-audit' + - '*-audit-*' + allowFailureMustBeFalse: + enabled: true + rulesMustNotBeRedefined: + enabled: true + whenMustNotBeManual: + enabled: true + pipelineMustNotExecuteUnverifiedScripts: + enabled: true + pipelineMustNotUseDockerInDocker: + enabled: true + detectInsecureDaemon: true + actionsMustBePinnedByCommitSha: + enabled: true + trustedOwners: + - actions + - github + githubActionMustComeFromAuthorizedSources: + enabled: true + trustGithubOfficialActions: true + trustSameOrgActions: true + trustedGithubActions: + - getplumber/plumber + workflowMustNotInjectUserInputInScripts: + enabled: true + workflowMustNotWriteUntrustedContentToGitHubEnv: + enabled: true + workflowMustNotUseDangerousTriggers: + enabled: true + pullRequestTargetMustNotCheckoutHead: + enabled: true + workflowsMustDeclarePermissions: + enabled: true + reusableWorkflowsMustNotInheritSecrets: + enabled: true + workflowMustNotExportEntireSecretsContext: + enabled: true + workflowMustNotGrantPermissionsWriteAll: + enabled: true + actionsMustNotBeArchived: + enabled: true + actionRefsMustExistUpstream: + enabled: true + actionsMustNotCarryKnownCVEs: + enabled: true + actionsMustNotExecuteMutableRemoteCode: + enabled: true + releaseWorkflowsMustNotRestoreUntrustedCache: + enabled: true + publishActions: + - gradle/publish-plugin + cacheActions: + - action: actions/cache + mode: always + - action: actions/cache/restore + mode: always + - action: Swatinem/rust-cache + mode: always + - action: actions/setup-go + mode: default + disableInput: cache + disableValue: false + - action: gradle/actions/setup-gradle + mode: default + disableInput: cache-disabled + disableValue: true + - action: actions/setup-node + mode: opt-in + enableInput: cache + - action: actions/setup-python + mode: opt-in + enableInput: cache + - action: actions/setup-java + mode: opt-in + enableInput: cache + - action: pnpm/action-setup + mode: opt-in + enableInput: cache + - action: docker/build-push-action + mode: opt-in + enableInput: cache-from + enableContains: type=gha + publishScriptPatterns: + - (?i)(npm|pnpm|yarn|bun)\s+publish + - (?i)cargo\s+publish + - (?i)twine\s+upload + - (?i)poetry\s+publish + - (?i)gh\s+release\s+create + - (?i)goreleaser\s+release + - (?i)semantic-release + - (?i)gradlew?\b[^\n]*\bpublish + - (?i)\bmvnw?\b[^\n]*\bdeploy\b + - (?i)dotnet\s+nuget\s+push + - (?i)gem\s+push + - (?i)docker\s+push + publishScriptExcludePatterns: + - (?i)--dry-run + - (?i)publishToMavenLocal + workflowMustIncludeRequiredActions: + enabled: false From 6904da058312feb783ccabdac34aa2a5046383b3 Mon Sep 17 00:00:00 2001 From: Thomas Boni Date: Wed, 29 Jul 2026 14:43:40 +0200 Subject: [PATCH 4/5] ci: enable plumber score push Turn on score-push and grant id-token: write so the workflow publishes this repository's Plumber Score to the hosted score service. This keeps the README badge current; the badge displays the score of the default branch. It makes the repository name and score public. Signed-off-by: Thomas Boni --- .github/workflows/plumber.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/plumber.yml b/.github/workflows/plumber.yml index 0ecdb68..872fd7c 100644 --- a/.github/workflows/plumber.yml +++ b/.github/workflows/plumber.yml @@ -22,7 +22,8 @@ jobs: # To upload the SARIF report to the Security tab security-events: write contents: read - # id-token: write # required only when score-push is enabled (see PR description) + # To publish the Plumber Score via OIDC (score-push, see below) + id-token: write steps: - name: Checkout repository uses: actions/checkout@v4 @@ -31,7 +32,8 @@ jobs: with: # Fail the check only when the Plumber Score drops below C. min-score: "C" - # score-push publishes a public A-E score badge to the hosted - # score service. Kept disabled here; see the PR description for - # the trade-offs before turning it on. - score-push: false + # Publish this repository's Plumber Score to the hosted score + # service so the README badge stays up to date. This makes the + # repository name and its score public. The badge displays the + # score of the default branch. + score-push: true From 7a6b25ee49eae48d68b8253e9f1f9071303079bb Mon Sep 17 00:00:00 2001 From: Thomas Boni Date: Wed, 29 Jul 2026 14:43:40 +0200 Subject: [PATCH 5/5] docs: add plumber score badge to readme Show the repository's Plumber Score at the top of the README. The badge is served by the hosted score service and displays the score of the default branch. Signed-off-by: Thomas Boni --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0ee24e5..e904ccf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # CDEvents Java SDK +[![Plumber Score](https://score.getplumber.io/github.com/cdevents/sdk-java.svg)](https://score.getplumber.io/github.com/cdevents/sdk-java) + Java SDK to produce [CDEvents](https://cdevents.dev). The SDK can be used to create CDEvents and render as CloudEvents to send them to a specific CloudEvents broker