diff --git a/.github/workflows/betterleaks.yml b/.github/workflows/betterleaks.yml new file mode 100644 index 0000000..e3ee2df --- /dev/null +++ b/.github/workflows/betterleaks.yml @@ -0,0 +1,133 @@ +name: Betterleaks + +on: + push: + pull_request: + +permissions: + contents: read + +jobs: + scan: + name: Scan for secrets + runs-on: ubuntu-latest + env: + SMTP_URL: ${{ secrets.SMTP_URL }} + SMTP_PORT: ${{ secrets.SMTP_PORT || '25' }} + SMTP_EMAIL: ${{ secrets.SMTP_EMAIL }} + SMTP_PASSWORD: ${{ secrets.SMTP_PASSWORD }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Run Betterleaks + id: betterleaks + continue-on-error: true + uses: dortort/betterleaks-action@v0.1.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + scan-mode: dir + scan-path: . + config: .gitleaks.toml + report-format: json + report-path: betterleaks-report.json + redact: "true" + no-color: "true" + no-banner: "true" + fail-on-leak: "true" + + - name: Upload Betterleaks report + if: always() + uses: actions/upload-artifact@v4 + with: + name: betterleaks-report + path: betterleaks-report.json + if-no-files-found: ignore + + - name: Build Betterleaks email summary + id: leak_summary + if: steps.betterleaks.outcome == 'failure' + shell: bash + run: | + if [[ -s betterleaks-report.json ]]; then + jq -r ' + def one_line: + tostring + | gsub("[\r\n]+"; " ") + | if length > 240 then .[0:240] + "..." else . end; + + .[:20][] + | "- " + (.RuleID // "unknown-rule") + + " at " + (.File // "unknown-file") + + ":" + ((.StartLine // 0) | tostring) + + "\n match: " + ((.Match // .Secret // "REDACTED") | one_line) + ' betterleaks-report.json > betterleaks-email-summary.txt + + count="$(jq 'length' betterleaks-report.json)" + if (( count > 20 )); then + { + echo "" + echo "... and $((count - 20)) more finding(s). Download the artifact for full details." + } >> betterleaks-email-summary.txt + fi + else + echo "No JSON report was generated. Download the workflow logs for details." > betterleaks-email-summary.txt + fi + + { + echo "text<> "$GITHUB_OUTPUT" + + - name: Resolve committer email + id: committer + if: steps.betterleaks.outcome == 'failure' + shell: bash + run: | + committer_email="$(git log -1 --format='%ce')" + author_email="$(git log -1 --format='%ae')" + email="$committer_email" + if [[ -z "$email" || "$email" == *"noreply.github.com"* ]]; then + email="$author_email" + fi + if [[ "$email" =~ ^[^[:space:]@]+@[^[:space:]@]+\.[^[:space:]@]+$ && "$email" != *"noreply.github.com"* ]]; then + echo "email=$email" >> "$GITHUB_OUTPUT" + else + echo "No deliverable committer email found; skipping Betterleaks email notification." + echo "email=" >> "$GITHUB_OUTPUT" + fi + + - name: Email committer on Betterleaks failure + if: steps.betterleaks.outcome == 'failure' && steps.committer.outputs.email != '' && env.SMTP_URL != '' && env.SMTP_EMAIL != '' + uses: dawidd6/action-send-mail@v18 + with: + server_address: ${{ env.SMTP_URL }} + server_port: ${{ env.SMTP_PORT }} + secure: ${{ env.SMTP_PORT == '465' }} + username: ${{ env.SMTP_EMAIL }} + password: ${{ env.SMTP_PASSWORD }} + from: ${{ env.SMTP_EMAIL }} + to: ${{ steps.committer.outputs.email }} + subject: "[Betterleaks] Secret scan failed in ${{ github.repository }}" + body: | + Betterleaks detected one or more potential secrets. + + Repository: ${{ github.repository }} + Branch: ${{ github.ref_name }} + Commit: ${{ github.sha }} + Workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + + Findings: + ${{ steps.leak_summary.outputs.text }} + + Download the betterleaks-report artifact from the workflow run for details. + + - name: Fail if Betterleaks found leaks + if: steps.betterleaks.outcome == 'failure' + run: | + echo "Betterleaks detected one or more secrets. Download the betterleaks-report artifact from this workflow run for details." + exit 1 diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..4f89ba0 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,100 @@ +title = "Betterleaks config" + +[extend] +useDefault = true + +[[rules]] +id = "secret-literal-assignment" +description = "Secret-like literal assignment in source, YAML, env and config files" +regex = '''(?i)([A-Za-z0-9_.-]*(?:password|passwd|pwd|api[_-]?key|apikey|access[_-]?key|secret[_-]?access[_-]?key|private[_-]?key|client[_-]?secret|consumer[_-]?key|consumer[_-]?secret|(?:auth|access|refresh|session|api|bearer|id|jwt|csrf|xsrf|oauth)[_-]?token|translate[_-]?auth|translation[_-]?auth|auth[_-]?password|auth[_-]?key|auth[_-]?credentials|database[_-]?url|connection[_-]?string)[A-Za-z0-9_.-]*)[ \t]*[:=][ \t]*["'']?([^"''[:space:]#{}$.][^"''\n#{}]{2,})["'']?''' +secretGroup = 2 +keywords = [ + "password", + "passwd", + "pwd", + "api_key", + "apikey", + "access_key", + "private_key", + "client_secret", + "consumer_key", + "consumer_secret", + "auth_token", + "access_token", + "refresh_token", + "session_token", + "api_token", + "bearer_token", + "id_token", + "jwt_token", + "csrf_token", + "xsrf_token", + "oauth_token", + "translate_auth", + "translation_auth", + "auth_password", + "auth_key", + "auth_credentials", + "database_url", + "connection_string" +] +tags = ["literal-secret"] + +[[rules]] +id = "env-short-secret-assignment" +description = "Uppercase env-style PASS/TOKEN/SECRET assignment" +regex = '''\b((?:PASS|TOKEN|SECRET|[A-Z0-9_]*(?:_PASS|_TOKEN|_SECRET|PASS_|TOKEN_|SECRET_)[A-Z0-9_]*))[ \t]*[:=][ \t]*["'']?([^"''[:space:]#{}$.][^"''\n#{}]{2,})["'']?''' +secretGroup = 2 +keywords = [ + "PASS", + "TOKEN", + "SECRET" +] +tags = ["env", "literal-secret"] + +[[rules]] +id = "standalone-sk-token" +description = "Standalone sk-* token not attached to a secret-like variable name" +regex = '''(?i)\b(sk-[A-Za-z0-9][A-Za-z0-9_-]{20,})\b''' +secretGroup = 1 +entropy = 2.5 +keywords = ["sk-"] +tags = ["standalone-token", "generic"] + +[[rules]] +id = "dotenv-only-jest-setup" +description = ".env may only contain the committed Jest setup lines" +path = '''(?i)(^|/)\.env$''' +regex = '''(?m)^(.+)$''' +secretGroup = 1 +tags = ["file", "dotenv"] +[[rules.allowlists]] +regexTarget = "match" +regexes = [ + '''^JEST_USE_SETUP=(ON|OFF) # Jest configuration variables: ON, OFF\r?$''', +] + +[[rules]] +id = "forbidden-secret-file" +description = "Forbidden secret-bearing file committed to repository" +path = '''(?i)(^|/)(\.env\..*|\.npmrc|\.pypirc|id_rsa|id_ed25519|.*\.(pem|key|p12|pfx|jks|kubeconfig))$''' +regex = '''(?s).{1,}''' +tags = ["file", "secret-file"] + +[[allowlists]] +description = "Allow Jenkins SonarQube token environment variable reference" +regexTarget = "match" +regexes = [ + '''SONAR_AUTH_TOKEN''', +] + +[[allowlists]] +description = "Allow local development RelStorage password defaults" +paths = [ + '''(?i)(^|/)develop/etc/(relstorage|alpha)\.conf$''', +] +regexTarget = "match" +regexes = [ + '''password='zope''', +] + diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d14363..87e8ec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,326 @@ # Changelog +## [6.1.4-53](https://github.com/eea/msfd-backend/releases/tag/6.1.4-53) - 2026-08-25T23:50:54Z + +### Dependency updates + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 11.1 ~ 11.2 + + +## [6.1.4-52](https://github.com/eea/msfd-backend/releases/tag/6.1.4-52) - 2026-08-22T00:05:12Z + +### Dependency updates + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 11.0 ~ 11.1 + + +## [6.1.4-47](https://github.com/eea/msfd-backend/releases/tag/6.1.4-47) - 2026-08-08T01:12:50Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-15 ~ 6.1.4-16 + +##### eeacms/plone-backend:[6.1.4-16](https://github.com/eea/plone-backend/releases/tag/6.1.4-16) +###### Internal + +- fix: arm64 image builds on github actions - [Alin Voinea - [`35cd2ff`](https://github.com/eea/plone-backend/commit/35cd2ff11bafcc6b19b5fb2425903f94acbee89b)] + +### Dependency updates + +#### New packages + +##### [eea.restapi](https://github.com/eea/eea.restapi): 2.9 + +### Internal + +- Add eea.restapi package version 2.9 to constraints - [Laszlo Cseh - [`53d048c`](https://github.com/eea/msfd-backend/commit/53d048cb6ced8dec00d1404840073e89cae038c3)] +- Add eea.restapi to requirements - [Laszlo Cseh - [`a03c2c8`](https://github.com/eea/msfd-backend/commit/a03c2c84cc239fce1ce792797588656e4ac26e3e)] + +## [6.1.4-40](https://github.com/eea/msfd-backend/releases/tag/6.1.4-40) - 2026-07-29T01:08:48Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-12 ~ 6.1.4-13 + +##### eeacms/plone-backend:[6.1.4-13](https://github.com/eea/plone-backend/releases/tag/6.1.4-13) +###### Dependency updates + +###### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.2 ~ 6.3 + +* Change: Fix publication_type taxonomy vocabulary - refs #305522 + [avoinea] + +### Dependency updates + +##### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.2 ~ 6.3 + +* Change: Fix publication_type taxonomy vocabulary - refs #305522 + [avoinea] + + +## [6.1.4-38](https://github.com/eea/msfd-backend/releases/tag/6.1.4-38) - 2026-07-23T23:59:23Z + +### Dependency updates + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 9.9 ~ 10.0 + + +## [6.1.4-37](https://github.com/eea/msfd-backend/releases/tag/6.1.4-37) - 2026-07-21T23:56:16Z + +### Internal + +- chore: revert Move image build to Jenkins - [Laszlo Cseh - [`6c1cdef`](https://github.com/eea/msfd-backend/commit/6c1cdef90242bfa5bb3cc0e2f3af8c542e31fc2a)] + +## [6.1.4-31](https://github.com/eea/msfd-backend/releases/tag/6.1.4-31) - 2026-07-15T23:57:19Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-11 ~ 6.1.4-12 + +##### eeacms/plone-backend:[6.1.4-12](https://github.com/eea/plone-backend/releases/tag/6.1.4-12) +###### Dependency updates + +###### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.1 ~ 6.2 + +* Change: Replace the generated Publication type taxonomy field with the + dedicated ``publication_type`` behavior and migrate its catalog and + search configuration. + [dobri1408] + +### Dependency updates + +##### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.1 ~ 6.2 + +* Change: Replace the generated Publication type taxonomy field with the + dedicated ``publication_type`` behavior and migrate its catalog and + search configuration. + [dobri1408] + +### Internal + +- fix: Add betterleaks github action - refs #304517 - [dobri1408 - [`c9744c1`](https://github.com/eea/msfd-backend/commit/c9744c11b046fe740d83547cd2e8d885569142d7)] + +## [6.1.4-30](https://github.com/eea/msfd-backend/releases/tag/6.1.4-30) - 2026-07-14T01:03:22Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-10 ~ 6.1.4-11 + +##### eeacms/plone-backend:[6.1.4-11](https://github.com/eea/plone-backend/releases/tag/6.1.4-11) +###### Dependency updates + +###### [eea.api.controlpanel](https://github.com/eea/eea.api.controlpanel/releases): 1.3 ~ 1.4 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.api.glossary](https://pypi.org/project/eea.api.glossary/#changelog): 1.6 ~ 1.7 + +###### [eea.api.layout](https://github.com/eea/eea.api.layout/releases): 3.4 ~ 3.5 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.banner](https://github.com/eea/eea.banner/releases): 1.7 ~ 1.8 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.0 ~ 6.1 + +* Feature: Add the Publication type taxonomy, search configuration, + content-type behavior activation and CSV content migration report. + [refs #305522] + +###### [eea.geolocation](https://github.com/eea/eea.geolocation/releases): 4.0 ~ 4.1 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.kitkat](https://github.com/eea/eea.kitkat/releases): 8.4 ~ 8.5 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.schema.slate](https://github.com/eea/eea.schema.slate/releases): 1.3 ~ 1.4 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.sentry](https://github.com/eea/eea.sentry/releases): 3.1 ~ 3.2 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.2 ~ 13.3 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +###### [eea.zotero](https://github.com/eea/eea.zotero/releases): 1.5 ~ 1.6 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +### Dependency updates + +##### [eea.api.dataconnector](https://github.com/eea/eea.api.dataconnector/releases): 12.8 ~ 12.9 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +##### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 6.0 ~ 6.1 + +* Feature: Add the Publication type taxonomy, search configuration, + content-type behavior activation and CSV content migration report. + [refs #305522] + +##### [eea.plotly](https://github.com/eea/eea.plotly/releases): 2.4 ~ 2.5 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +##### [eea.progress.workflow](https://github.com/eea/eea.progress.workflow/releases): 3.2 ~ 3.3 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + +##### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.2 ~ 13.3 + +* Change: fix: SonarQube report - refs #305404 + [avoinea] + + +## [6.1.4-29](https://github.com/eea/msfd-backend/releases/tag/6.1.4-29) - 2026-07-11T23:52:37Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-9 ~ 6.1.4-10 + +##### eeacms/plone-backend:[6.1.4-10](https://github.com/eea/plone-backend/releases/tag/6.1.4-10) +###### Dependency updates + +###### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.1 ~ 13.2 + +* Fix: Delegate to collective.exportimport's image serializers when one of its + export markers is present on the request. + [claudiaifrim - refs #304938] + +### Dependency updates + +##### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.1 ~ 13.2 + +* Fix: Delegate to collective.exportimport's image serializers when one of its + export markers is present on the request. + [claudiaifrim - refs #304938] + + +## [6.1.4-26](https://github.com/eea/msfd-backend/releases/tag/6.1.4-26) - 2026-07-08T00:00:07Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-8 ~ 6.1.4-9 + +##### eeacms/plone-backend:[6.1.4-9](https://github.com/eea/plone-backend/releases/tag/6.1.4-9) +###### Dependency updates + +###### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.0 ~ 13.1 + +* Fix: Normalize internal backend URLs (e.g. backend:8080) saved in volto blocks + by SSR to avoid broken links. Add unit tests for URL normalizer. + [razvanMiu - refs #305419] + +### Dependency updates + +##### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 13.0 ~ 13.1 + +* Fix: Normalize internal backend URLs (e.g. backend:8080) saved in volto blocks + by SSR to avoid broken links. Add unit tests for URL normalizer. + [razvanMiu - refs #305419] + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 9.2 ~ 9.3 + + +## [6.1.4-25](https://github.com/eea/msfd-backend/releases/tag/6.1.4-25) - 2026-07-05T23:57:26Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-7 ~ 6.1.4-8 + +##### eeacms/plone-backend:[6.1.4-8](https://github.com/eea/plone-backend/releases/tag/6.1.4-8) +###### Internal + +- use postgres 14 - [valentinab25 - [`a94bc84`](https://github.com/eea/plone-backend/commit/a94bc84848c3928f235c3667030b8041a20a06be)] + + +## [6.1.4-24](https://github.com/eea/msfd-backend/releases/tag/6.1.4-24) - 2026-07-01T23:46:40Z + +### Dependency updates + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 9.0 ~ 9.2 + + +## [6.1.4-23](https://github.com/eea/msfd-backend/releases/tag/6.1.4-23) - 2026-06-25T16:25:08Z + +### Plone + +#### Upgrade [eeacms/plone-backend](https://github.com/eea/plone-backend): 6.1.4-6 ~ 6.1.4-7 + +##### eeacms/plone-backend:[6.1.4-7](https://github.com/eea/plone-backend/releases/tag/6.1.4-7) +###### Dependency updates + +###### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 5.5 ~ 6.0 + +* Feature: Add IGeoCoverageField marker interface on geo_coverage field + for scoped serializer adapter registration in eea.volto.policy + [avoinea - refs #296992] + +###### [eea.geolocation](https://github.com/eea/eea.geolocation/releases): 3.0 ~ 4.0 + +* Feature: Add grouped geographic coverage helper methos + [tedw87 - refs #296992] +* Change: Drop Python 2.7 and Plone 4 support. + [avoinea - refs #296992] +* Fix: Replace lossy latin-1 encoding with explicit PATH_SEPARATOR stripping + in taxonomy value normalization + [avoinea - refs #296992] +* Feature: Add RAM caching (plone.memoize) to geotags, biotags and country + mappings taxonomy parsing + [avoinea - refs #296992] + +###### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 12.7 ~ 13.0 + +* Feature: Scope geo_coverage serializer to IGeoCoverageField marker interface + instead of all JSON fields. Add eea.geolocation as explicit dependency. + [avoinea - refs #296992] +* Feature: Serialize grouped geographic coverage + [tedw87 - refs #296992] + +### Dependency updates + +##### [eea.coremetadata](https://github.com/eea/eea.coremetadata/releases): 5.5 ~ 6.0 + +* Feature: Add IGeoCoverageField marker interface on geo_coverage field + for scoped serializer adapter registration in eea.volto.policy + [avoinea - refs #296992] + +##### [eea.volto.policy](https://github.com/eea/eea.volto.policy/releases): 12.7 ~ 13.0 + +* Feature: Scope geo_coverage serializer to IGeoCoverageField marker interface + instead of all JSON fields. Add eea.geolocation as explicit dependency. + [avoinea - refs #296992] +* Feature: Serialize grouped geographic coverage + [tedw87 - refs #296992] + + +## [6.1.4-22](https://github.com/eea/msfd-backend/releases/tag/6.1.4-22) - 2026-06-24T17:21:04Z + +### Dependency updates + +##### [wise.msfd](https://pypi.org/project/wise.msfd/#changelog): 8.9 ~ 9.0 + + ## [6.1.4-21](https://github.com/eea/msfd-backend/releases/tag/6.1.4-21) - 2026-06-18T01:06:03Z ### Plone diff --git a/Dockerfile b/Dockerfile index ac07c18..9f319d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM eeacms/plone-backend:6.1.4-6 +FROM eeacms/plone-backend:6.1.4-18 ENV GRAYLOG_FACILITY=wise-plone ENV SECURITY_POLICY_IMPLEMENTATION=C diff --git a/Jenkinsfile b/Jenkinsfile index 0415c83..b0616a6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -39,7 +39,7 @@ pipeline { } steps{ node(label: 'docker') { - withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'), string(credentialsId: 'msfd-backend-trigger', variable: 'TRIGGER_MAIN_URL'), usernamePassword(credentialsId: 'jekinsdockerhub', usernameVariable: 'DOCKERHUB_USER', passwordVariable: 'DOCKERHUB_PASS')]) { + withCredentials([string(credentialsId: 'eea-jenkins-token', variable: 'GITHUB_TOKEN'), string(credentialsId: 'msfd-backend-trigger', variable: 'TRIGGER_MAIN_URL'), usernamePassword(credentialsId: 'jekinsdockerhub', usernameVariable: 'DOCKERHUB_USER', passwordVariable: 'DOCKERHUB_PASS')]) { //betterleaks:allow sh '''docker pull eeacms/gitflow; docker run -i --rm --name="$BUILD_TAG" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" -e DOCKERHUB_REPO="eeacms/msfd-backend" -e GIT_TOKEN="$GITHUB_TOKEN" -e DOCKERHUB_USER="$DOCKERHUB_USER" -e DOCKERHUB_PASS="$DOCKERHUB_PASS" -e TRIGGER_MAIN_URL="$TRIGGER_MAIN_URL" -e DEPENDENT_DOCKERFILE_URL="" -e GITFLOW_BEHAVIOR="RUN_ON_TAG" eeacms/gitflow''' } diff --git a/README.md b/README.md index 4ac8ab0..78a3b7d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,62 @@ # msfd-backend Plone 6 backend for the WISE-Marine assessment module + +## Secret Scanning + +This repository uses the Betterleaks GitHub Action to scan the current +repository content on every push and pull request. The scan uses the rules in +`.gitleaks.toml` and uploads a `betterleaks-report` artifact when a finding is +detected. + +If the optional SMTP secrets are configured, failed scans also send an email to +the last commit committer. The workflow expects these repository or +organization secrets: + +- `SMTP_URL` +- `SMTP_PORT` (optional, defaults to `25`) +- `SMTP_EMAIL` +- `SMTP_PASSWORD` (optional if the SMTP server does not require authentication) + +Port `465` is sent with direct TLS; other ports use the default SMTP handshake. +The email includes a short finding summary from the redacted Betterleaks report, +including the redacted matched line from each finding. + +There are three common outcomes: + +1. **Everything is OK.** The `Betterleaks / Scan for secrets` check is green and + no action is needed. Regular references to runtime values are OK, for example: + + ```js + const tokenFromCookie = req.universalCookies.get('auth_token'); + ``` + +2. **A real secret was found.** The check is red and the workflow log asks you to + download the `betterleaks-report` artifact. Open the artifact from the GitHub + Actions run and check the reported file, line and rule. Remove the committed + value, move it to the proper secret store, and rotate it if it was exposed. + A report entry looks like this: + + ```json + { + "RuleID": "secret-literal-assignment", + "File": "src/config.js", + "StartLine": 12, + "Secret": "[REDACTED]" + } + ``` + +3. **The finding is a false positive.** Keep the value only if it is clearly not + sensitive, such as a test fixture, placeholder, or public example. Add + `betterleaks:allow` on the same line and include a short explanation in the + pull request. + + ```js + const testPassword = 'admin'; //betterleaks:allow + ``` + + ```yaml + password: "admin" #betterleaks:allow + ``` + +Do not add `betterleaks:allow` to real credentials. diff --git a/constraints.txt b/constraints.txt index 8b0ce3c..de2079e 100644 --- a/constraints.txt +++ b/constraints.txt @@ -34,12 +34,11 @@ # plone.api - managed by Plone 6 constraints # EEA packages with versions -eea.api.dataconnector==12.8 -eea.restapi==2.9 -eea.plotly==2.4 -eea.coremetadata==5.5 -eea.volto.policy==12.7 -eea.progress.workflow==3.2 +eea.api.dataconnector==13.0 +eea.plotly==2.5 +eea.coremetadata==6.4 +eea.volto.policy==13.7 +eea.progress.workflow==3.3 eea.api.visualizationutils==1.4 # WISE packages diff --git a/develop/docker-compose.yml b/develop/docker-compose.yml index 1f93bd5..3379a23 100644 --- a/develop/docker-compose.yml +++ b/develop/docker-compose.yml @@ -22,7 +22,7 @@ services: POSTGRES_DBPASS: zope POSTGRES_DBUSER: zope POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres + POSTGRES_PASSWORD: postgres #betterleaks:allow TZ: Europe/Bucharest volumes: - postgres_dump:/postgresql.backup @@ -37,7 +37,7 @@ services: - postgres environment: PGADMIN_DEFAULT_EMAIL: "alin@eaudeweb.ro" - PGADMIN_DEFAULT_PASSWORD: "alin" + PGADMIN_DEFAULT_PASSWORD: "alin" #betterleaks:allow mailtrap: image: eaudeweb/mailtrap diff --git a/requirements.txt b/requirements.txt index 92ac0b4..9660dcb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,6 @@ # EEA packages eea.api.dataconnector -eea.restapi eea.plotly eea.coremetadata eea.volto.policy diff --git a/test/tests/no-hard-coded-passwords/run.sh b/test/tests/no-hard-coded-passwords/run.sh index 9f326b4..eba6919 100755 --- a/test/tests/no-hard-coded-passwords/run.sh +++ b/test/tests/no-hard-coded-passwords/run.sh @@ -2,7 +2,7 @@ set -e IFS=$'\n' -userPasswds=( $(docker run --rm --user 0:0 --entrypoint cut "$1" -d: -f1-2 /etc/passwd) ) +userPasswds=( $(docker run --rm --user 0:0 --entrypoint cut "$1" -d: -f1-2 /etc/passwd) ) #betterleaks:allow userShadows=() if grep -qE ':x$' <<<"${userPasswds[*]}"; then userShadows=( $(docker run --rm --user 0:0 --entrypoint cut "$1" -d: -f1-2 /etc/shadow || true) ) diff --git a/test/tests/plone-relstorage/run.sh b/test/tests/plone-relstorage/run.sh index 67db532..39cac63 100755 --- a/test/tests/plone-relstorage/run.sh +++ b/test/tests/plone-relstorage/run.sh @@ -11,11 +11,11 @@ PLONE_TEST_TRIES=40 # Start Postgres zname="relstorage-container-$RANDOM-$RANDOM" zpull="$(docker pull postgres:12-alpine)" -zid="$(docker run -d --name "$zname" -e POSTGRES_USER=plone -e POSTGRES_PASSWORD=plone -e POSTGRES_DB=plone postgres:12-alpine)" +zid="$(docker run -d --name "$zname" -e POSTGRES_USER=plone -e POSTGRES_PASSWORD=plone -e POSTGRES_DB=plone postgres:12-alpine)" #betterleaks:allow # Start Plone as RelStorage Client pname="plone-container-$RANDOM-$RANDOM" -pid="$(docker run -d --name "$pname" --link=$zname:db -e RELSTORAGE_DSN="dbname='plone' user='plone' host='db' password='plone'" "$image")" +pid="$(docker run -d --name "$pname" --link=$zname:db -e RELSTORAGE_DSN="dbname='plone' user='plone' host='db' password='plone'" "$image")" #betterleaks:allow # Tear down trap "docker rm -vf $pid $zid > /dev/null" EXIT