OpenSSF Scorecard¶
This document describes the security practices implemented in this project and how to achieve a perfect OpenSSF Scorecard score.
Current Score¶
Automated Checks (Code)¶
| Check | Implementation |
|---|---|
| Pinned-Dependencies | All GitHub Actions and Docker images pinned to SHA hashes with version comments |
| Token-Permissions | Workflow-level permissions: {} with minimal per-job permissions |
| SAST | CodeQL analysis (codeql.yml) + Gosec security scanner |
| Fuzzing | Native Go fuzz tests (pkg/sops/fuzz_test.go) |
| Signed-Releases | Cosign keyless signatures for all release artifacts |
| Dangerous-Workflow | No pull_request_target with write permissions |
| Binary-Artifacts | No binaries committed to repository |
| Dependency-Update-Tool | Dependabot configured for Go, Docker, and GitHub Actions |
| Vulnerabilities | Automated scanning via Dependabot and CodeQL |
| Security-Policy | SECURITY.md with vulnerability reporting process |
| License | Apache 2.0 (LICENSE) |
| CI-Tests | Comprehensive test suite runs on all PRs |
Manual Configuration Required¶
Branch Protection¶
Configure via Settings → Branches → Add rule for main:
✓ Require pull request before merging
✓ Require 1 approval
✓ Dismiss stale approvals when new commits are pushed
✓ Require review from Code Owners
✓ Require status checks to pass
✓ Require branches to be up to date
→ Add checks: Lint, Test, Build, Docker Build, Security Scan, Analyze
✓ Require conversation resolution
✓ Do not allow bypassing the above settings
OpenSSF Best Practices Badge¶
- Visit https://www.bestpractices.dev
- Add project:
github.com/scalaric/sops-operator - Complete the questionnaire
- Add badge to README
Verifying Release Signatures¶
All release artifacts are signed with Cosign using keyless signing (Fulcio + Rekor).
# Install cosign
brew install cosign
# Download release artifacts
VERSION=v1.0.0
curl -sLO "https://github.com/scalaric/sops-operator/releases/download/${VERSION}/install.yaml"
curl -sLO "https://github.com/scalaric/sops-operator/releases/download/${VERSION}/install.yaml.sig"
curl -sLO "https://github.com/scalaric/sops-operator/releases/download/${VERSION}/install.yaml.pem"
# Verify signature
cosign verify-blob \
--signature install.yaml.sig \
--certificate install.yaml.pem \
--certificate-identity-regexp "https://github.com/scalaric/sops-operator/" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
install.yaml
# Verify container image
cosign verify ghcr.io/scalaric/sops-operator:${VERSION} \
--certificate-identity-regexp "https://github.com/scalaric/sops-operator/" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
Workflow Overview¶
| Workflow | Trigger | Purpose |
|---|---|---|
ci.yml | Push, PR | Lint, test, build, security scan |
codeql.yml | Push, PR, weekly | CodeQL static analysis |
fuzz.yml | Push, PR, daily | Go native fuzz testing |
release.yml | Tag push | Build, sign, and publish release |
scorecard.yml | Push to main, weekly | OpenSSF Scorecard analysis |
dependabot-auto-merge.yml | Dependabot PR | Auto-merge patch/minor updates |
release-please.yml | Push to main | Automated release management |
Pinned Dependencies Guidelines¶
Docker Images in Dockerfile¶
All Docker base images must include SHA256 digests for Scorecard compliance:
# CORRECT - with SHA256 digest
FROM golang:1.25-alpine@sha256:d9b2e14101f27ec8d09674cd01186798d227bb0daec90e032aeb1cd22ac0f029 AS builder
# INCORRECT - will fail Scorecard
FROM golang:1.25-alpine AS builder
To get the SHA256 digest for an image:
The renovate comments before each FROM statement enable automated updates while maintaining pinned digests.
GitHub Actions¶
All GitHub Actions must be pinned to commit SHAs with version comments:
# CORRECT
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
# INCORRECT
- uses: actions/checkout@v4
Local Verification¶
# Run scorecard locally
brew install scorecard
scorecard --repo=github.com/scalaric/sops-operator
# Check specific check
scorecard --repo=github.com/scalaric/sops-operator --checks=Pinned-Dependencies
# Run fuzz tests locally
go test -fuzz=FuzzParseDecryptedYAML -fuzztime=30s ./pkg/sops/
go test -fuzz=FuzzValidateEncryptedYAML -fuzztime=30s ./pkg/sops/