UNPKG

@sebastienrousseau/dotfiles

Version:

The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.

196 lines (154 loc) 13.1 kB
--- render_with_liquid: false --- # OpenSSF Scorecard This page records the current OpenSSF Scorecard posture for this repository, the known gaps, and the remediation roadmap. The badge in the README links to the live result; this page is the maintained narrative behind it. ## Live score <!-- BEGIN scorecard-snapshot (auto-generated, do not edit by hand) --> Aggregate score **7.6 / 10** at 2026-05-17T08:11:51Z. | Check | Score | Reason | |---|---:|---| | Binary-Artifacts | 10 | no binaries found in the repo | | Branch-Protection | -1 | internal error: error during branchesHandler.setup: internal error: some github tokens can't read cl | | CI-Tests | 10 | 15 out of 15 merged PRs checked by a CI test -- score normalized to 10 | | CII-Best-Practices | 2 | badge detected: InProgress | | Code-Review | 0 | Found 0/30 approved changesets -- score normalized to 0 | | Contributors | 0 | project has 0 contributing companies or organizations -- score normalized to 0 | | Dangerous-Workflow | 10 | no dangerous workflow patterns detected | | Dependency-Update-Tool | 10 | update tool detected | | Fuzzing | 0 | project is not fuzzed | | License | 9 | license file detected | | Maintained | 10 | 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10 | | Packaging | 10 | packaging workflow detected | | Pinned-Dependencies | 9 | dependency not pinned by hash detected -- score normalized to 9 | | SAST | 10 | SAST tool is run on all commits | | Security-Policy | 10 | security policy file detected | | Signed-Releases | 3 | 1 out of the last 3 releases have a total of 2 signed artifacts. | | Token-Permissions | 10 | GitHub workflow tokens follow principle of least privilege | | Vulnerabilities | 10 | 0 existing vulnerabilities detected | *Refresh: `scripts/qa/scorecard-snapshot.sh` · CI check: `lint/scorecard-snapshot` (planned).* <!-- END scorecard-snapshot --> [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sebastienrousseau/dotfiles/badge)](https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/dotfiles) The badge above is regenerated every Monday at 06:00 UTC and on every push to `master` by `.github/workflows/scorecard.yml`. The SARIF result is uploaded to GitHub Code Scanning (Security tab) and retained as a 30-day workflow artifact. ## Threshold policy | Score | Action | |---|---| | ≥ 8.0 | Healthy. Keep doing what we're doing. | | 7.0 – 7.9 | Acceptable. Tracked. | | < 7.0 | Regression — the workflow auto-opens a tracking issue labelled `type:security + priority:high`. | Regressions are triaged within one Monday cycle: identify the check that dropped, either remediate or file an exception entry below with a rationale and an expiry date. ## Per-check posture (snapshot, master HEAD) The checks below come from OpenSSF Scorecard's published rubric. Tick marks reflect this repo's posture at the time of writing — the *live* badge is authoritative if these diverge. | Check | Status | Notes | |---|---|---| | Branch-Protection | ⚠ | `master` requires signed commits, linear history, required checks (`.github/rulesets/master.json`). Scorecard can't read classic protection rules without a fine-grained PAT, so this check reports as `-1` ("internal error"). | | Code-Review | ⚠ | Single-maintainer repo; PRs are self-merged after CI. Scorecard scores 0/30 here by design — see `Open findings` below. | | Signed-Commits | ✓ | Enforced by pre-push hook (`scripts/git-hooks/pre-push`) and at-push by branch protection (#853 + #857). | | Dependency-Update-Tool | ✓ | Dependabot configured for github-actions / npm / docker / devcontainers / uv. | | Fuzzing | ⚠ | `install.sh` fuzz harness lives under `tests/fuzz/` (closes #881), but it's shell-based and Scorecard's heuristic only recognizes OSS-Fuzz / ClusterFuzzLite / native Go fuzz / libFuzzer / Atheris. None support shell. Property tests under `tests/unit/functions/test_property_*.sh` cover the closest equivalent surface. | | License | ✓ | MIT at repo root (`LICENSE`). | | Maintained | ✓ | Active commit cadence; the [README](../../README.md) lists the current `dotfiles_version`. | | Pinned-Dependencies | ⚠ | Closed 8 of 14 findings this cycle (every Dockerfile base + every workflow action + 2 `curl \| sh` installers + the `npm install -g npm` upgrade step). 5 residual findings stay open by design — see `Open findings`. | | SAST | ✓ | CodeQL (`.github/workflows/codeql.yml`) + Checkov + Grype. | | SBOM | ✓ | Generated per PR by `sbom-diff.yml` and per release by `security-release.yml`. | | Security-Policy | ✓ | `.github/SECURITY.md` + this page + `docs/security/THREAT_MODEL.md`. | | Token-Permissions | ✓ | Top-level `permissions:` blocks restricted to `contents: read`. `write` scopes scoped to the jobs that need them (#886). | | Vulnerabilities | ✓ | Grype gate hard-fails on `high` / `critical` on `master` (#852). | | Webhooks | n/a | No external webhooks configured. | | CI-Tests | ✓ | Linux + macOS Intel + Apple Silicon matrix; optional Windows. | | CII-Best-Practices | ☐ | Not applied yet — see `Open work` below. | | Dangerous-Workflow | ✓ | No `pull_request_target` with checkout-PR-code anti-pattern. | | Packaging | ✓ | `npm publish --provenance` via OIDC (`.github/workflows/npm-publish.yml`); `policy-bundle-release.yml` for the policy artifact. | | Signed-Releases | ⚠ | SLSA provenance + minisig attached via `security-release.yml`; Cosign keyless signing tracked at #876. | ## Open findings The eight items below are surfaced as alerts at <https://github.com/sebastienrousseau/dotfiles/security/code-scanning>. Each row gives the dismissal **reason** and the exact **comment text** to paste when triaging. ### Bucket 1 — Dismiss in the UI (5 items) Scorecard flags every `npm install`, `pip install`, `go install`, and `curl | sh` invocation under the `Pinned-Dependencies` check. The five below either belong to user-facing "update everything" aliases or are false positives in Scorecard's regex. | Path | Reason | Comment to paste | |---|---|---| | `.chezmoitemplates/aliases/legal/legal.aliases.sh:64` | **Won't fix** | User-facing convenience alias — `go install <fortune-style joke command>@latest`. Pinning by SHA would require users to update the alias manually on every upstream change. Intentional. | | `.chezmoitemplates/aliases/update/update.aliases.sh:173` | **Won't fix** | User-facing convenience alias — bulk-update wrapper around `npm`. The alias's purpose is to update everything; pinning defeats it. Intentional. | | `dot_local/bin/executable_update:99` | **Won't fix** | `dot_local/bin/executable_update` is the user-invoked "update everything" command. The literal point of `npm update -g` is to update to whatever's latest. Pinning defeats it. Intentional. | | `scripts/dot/commands/tools.sh:121` | **False positive** | `npm install --package-lock-only --ignore-scripts --silent` generates a lockfile and does NOT fetch packages. Scorecard's regex matches `npm install` blindly; this invocation has no supply-chain surface. | | `install/provision/run_onchange_10-linux-packages.sh.tmpl:369` | **Won't fix** | Already exact-version-pins `aider-chat==0.86.2`. Scorecard wants sha256-hash pinning, which would require a ~2,700-line lockfile covering all 108 transitive deps and re-generated on every aider release — disproportionate maintenance for a single optional provisioning install. | ### Bucket 2 — Architectural (1 item) | Alert | Why architectural | |---|---| | `CodeReviewID` (high) — score 0 | Scorecard requires every merged PR to record an approval review by a different GitHub user than the author. This repo is single-maintainer; PRs are self-merged after CI. The fix path is either (a) onboard a co-maintainer who reviews PRs before merge, or (b) accept the finding. Dismiss as **Won't fix** with comment: "Single-maintainer project — no second reviewer available. CI gates (47 required checks per PR) substitute for human review." | ### Bucket 3 — External action (2 items) | Alert | Action | |---|---| | `FuzzingID` (medium) | Dismiss as **Won't fix** with comment: "Repo is bash + Go-template + Lua. ClusterFuzzLite / OSS-Fuzz / native Go fuzz / libFuzzer / Atheris (the frameworks Scorecard recognises) all target compiled languages, none support shell. The `tests/fuzz/fuzz_install.sh` harness + property tests under `tests/unit/functions/test_property_*.sh` cover the equivalent surface." | | `CIIBestPracticesID` (low) | Apply at <https://www.bestpractices.dev/projects/new>. ~67 self-attested questions, free, 1-2 hours. After silver-tier approval, paste the badge into `README.md` next to the existing Scorecard badge. Most criteria already met (signed commits, CI, security policy, license). | ## Closed this cycle | Date | Score | Alerts open | Change | |---|---|---|---| | 2026-05-14 | 6.5 | 28 | First clean publish after fixing the scorecard.yml `uses:`-only restriction (#885). Findings had been hidden by publish-step 400s until then. | | 2026-05-14 | 6.5 | 11 | Closed 17 of 28: 10× TokenPermissions (#886), 6× Dockerfile bases (#886), 1× gitleaks fixture (#884). | | 2026-05-14 | 6.5 | 9 | Closed 2× `curl \| sh` installers (#888). | | 2026-05-14 | 6.5 | 8 | Closed 1× `npm install -g npm@…` via Node 24 bump (#889). | | 2026-05-17 | 7.6 | 7 | v0.2.502 released; Cosign keyless signing live (#876 implementation landed in `security-release.yml` sbom job). | | 2026-05-17 | 7.6 | 6 | SLSA Release Attestation pipeline unblocked (PR #894 — 6 prior releases had failed identically). v0.2.502 backfilled with `.intoto.jsonl` + `.sig` + `.pem` triplet. `Signed-Releases` should bump from 3 to ~10 on next Scorecard re-scrape. | | 2026-05-17 | 7.6 | — | Added `MAINTAINERS.md` + `GOVERNANCE.md` at repo root. Provides the formal context for the `Code-Review` 0/30 score (solo maintainer) and unblocks the CII Best Practices badge application. | ## Open work - **Apply for the OpenSSF Best Practices Badge** — see Bucket 3 above. All passing-tier criteria are now met (signed commits, CI, security policy, MIT license, MAINTAINERS.md, GOVERNANCE.md, RFC process documented). - **Re-trigger Scorecard after SLSA backfill propagates** — expected `Signed-Releases` 3 → 10. - **`harden-runner` block-mode adoption (#878)** — should tighten the `Token-Permissions` check further. - **Investigate `License` 9/10 false-positive** — repo is MIT (SPDX-compliant), Scorecard's penalty should not apply. - **Investigate `Branch-Protection` `-1`** — scanner internal error; manually verify with `gh api repos/:owner/:repo/branches/master/protection` and document. ### Enabling Branch-Protection + Webhooks checks (one-time PAT setup) Scorecard's `Branch-Protection` and `Webhooks` checks require a fine-grained Personal Access Token with `Administration: read` scope. Without it both checks return `-1` ("internal error"). The workflow already wires this up — only the secret needs to be created. Steps (one-time, repo owner): 1. Go to <https://github.com/settings/personal-access-tokens/new> 2. **Resource owner**: `sebastienrousseau` · **Repository access**: only `sebastienrousseau/dotfiles` 3. **Repository permissions**`Administration: read-only` and `Metadata: read-only` 4. **Expiration**: 1 year (set a calendar reminder to rotate; document the rotation in this file when done) 5. Generate the token, copy it once 6. Add as a secret named `SCORECARD_TOKEN` at <https://github.com/sebastienrousseau/dotfiles/settings/secrets/actions/new> 7. Next Scorecard run (manual via `gh workflow run scorecard.yml` or weekly cron) picks it up automatically 8. Expected effect: `Branch-Protection` `-1` → 10/10 if all rules are correctly configured; `Webhooks` `-1` → 10/10 (no webhooks present). The PAT secret is **optional**. When absent, the workflow falls back to `${{ github.token }}` and Scorecard continues to run, only with those two checks at `-1`. Adding the PAT cannot reduce any other check's score — it's a strict improvement. ## Exceptions | Check | Expiry | Rationale | |---|---|---| | *(none currently)* | *—* | *—* | If you add an exception, include the check name, an expiry date (don't allow indefinite), and the rationale. Re-evaluate every quarter. ## Refreshing this document ```bash # Re-count open alerts: gh api 'repos/sebastienrousseau/dotfiles/code-scanning/alerts?state=open&per_page=50' \ --jq '[.[].rule.id] | group_by(.) | map({rule: .[0], count: length})' # Trigger Scorecard manually: gh workflow run scorecard.yml --ref master ``` If a new category appears, add a row to the matching bucket. If a remediation closes one of the rows above, delete the row. ## References - `.github/workflows/scorecard.yml` — the scanner workflow (split into `analysis` + `track-regression` jobs per #885). - [Scorecard project](https://github.com/ossf/scorecard). - [Scorecard checks reference](https://github.com/ossf/scorecard/blob/main/docs/checks.md). - Tracking issue [#869](https://github.com/sebastienrousseau/dotfiles/issues/869).