diff --git a/.github/workflows/secrets-scan.yml b/.github/workflows/secrets-scan.yml index e759231..434a9e0 100644 --- a/.github/workflows/secrets-scan.yml +++ b/.github/workflows/secrets-scan.yml @@ -1,5 +1,15 @@ # sscsb: CI secret-scanning redundancy (TruffleHog + Gitleaks). # Local hooks block first; this catches anything that slips past (e.g. web UI commits). +# Both jobs scan the commits under review (the PR or push range), not the full history. +# +# Two independent engines, deliberately. TruffleHog VERIFIES a candidate credential +# against the issuing provider, so it distinguishes "this looks like a key" from +# "this key is live right now" (`--results=verified,unknown` keeps the unverifiable +# candidates in scope). Gitleaks runs alongside it: independent probes showed it +# catches generic secrets (e.g. `api_key = ""`) and unverifiable keys that +# TruffleHog's verified/unknown filter still drops — a detection class TruffleHog +# alone does not cover. +# # All actions pinned to full commit SHAs (sscsb actions-audit enforces this). name: Secret Scan on: @@ -23,7 +33,8 @@ jobs: with: fetch-depth: 0 persist-credentials: false - # Upstream README suggests @main; sscsb pins the release SHA instead (v3.95.9). + # Upstream README suggests @main; sscsb pins the release SHA instead (see the + # version comment on the `uses:` line, kept current by Dependabot). - name: TruffleHog scan uses: trufflesecurity/trufflehog@6f3c981e7b77f235fd2702dd74af25fc4b72bf11 # v3.96.0 with: @@ -33,26 +44,92 @@ jobs: runs-on: ubuntu-latest steps: - name: Harden runner - uses: step-security/harden-runner@b09bb98e06d4d774595224525879c09bc6e98c40 # v2.20.1 + uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 with: egress-policy: audit - name: Checkout - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: fetch-depth: 0 persist-credentials: false - # The gitleaks *CLI* (MIT) is used directly rather than - # gitleaks/gitleaks-action, which requires a paid GITLEAKS_LICENSE for - # organization repositories. This runs the same engine the local sscsb - # pre-commit/pre-push hooks use, against the tap's own .gitleaks.toml. - - name: Install gitleaks + + # gitleaks/gitleaks-action is commercially licensed: for organization-owned + # repos it hard-fails before scanning unless a GITLEAKS_LICENSE secret exists + # ("[org] is an organization. License key is required." -- src/index.js). + # This org has no license, so that action never actually scanned anything. + # The gitleaks BINARY is MIT-licensed OSS, so we run it directly. + # actions-audit mandates full-SHA pinning for ACTIONS; the equivalent for a + # downloaded binary is a pinned version plus a checksum verified BEFORE exec. + - name: Install gitleaks (pinned release, checksum-verified before execution) env: GITLEAKS_VERSION: "8.30.1" + GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb" run: | - curl -fsSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \ - -o /tmp/gitleaks.tgz - tar -xzf /tmp/gitleaks.tgz -C /tmp gitleaks - sudo install -m 0755 /tmp/gitleaks /usr/local/bin/gitleaks + set -euo pipefail + tarball="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" + base_url="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}" + workdir="$(mktemp -d)" + + curl --fail --silent --show-error --location --retry 3 --retry-delay 2 \ + -o "${workdir}/${tarball}" "${base_url}/${tarball}" + curl --fail --silent --show-error --location --retry 3 --retry-delay 2 \ + -o "${workdir}/checksums.txt" \ + "${base_url}/gitleaks_${GITLEAKS_VERSION}_checksums.txt" + + # 1. the digest pinned here must be the digest this release publishes + grep -Fxq "${GITLEAKS_SHA256} ${tarball}" "${workdir}/checksums.txt" + # 2. the bytes we downloaded must match that digest -- checked before exec + ( cd "${workdir}" \ + && printf '%s %s\n' "${GITLEAKS_SHA256}" "${tarball}" | sha256sum -c - ) + + install_dir="${RUNNER_TEMP}/gitleaks-bin" + mkdir -p "${install_dir}" + tar -xzf "${workdir}/${tarball}" -C "${install_dir}" gitleaks + chmod +x "${install_dir}/gitleaks" + printf '%s\n' "${install_dir}" >> "${GITHUB_PATH}" + + - name: Gitleaks scan + env: + # Context values are passed as env vars, never interpolated into the + # script body (GitHub Actions expression-injection hardening). + EVENT_NAME: ${{ github.event_name }} + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PUSH_BEFORE_SHA: ${{ github.event.before }} + PUSH_HEAD_SHA: ${{ github.sha }} + run: | + set -euo pipefail gitleaks version - - name: Gitleaks scan (full history) - run: gitleaks git --config .gitleaks.toml --redact --no-banner . + + null_sha="0000000000000000000000000000000000000000" + case "${EVENT_NAME}" in + pull_request) base_sha="${PR_BASE_SHA}"; head_sha="${PR_HEAD_SHA}" ;; + push) base_sha="${PUSH_BEFORE_SHA}"; head_sha="${PUSH_HEAD_SHA}" ;; + *) base_sha=""; head_sha="${PUSH_HEAD_SHA}" ;; + esac + + # Scope = the commits under review. This is exactly the scope the + # licensed action scanned on push/pull_request events + # (src/gitleaks.js: --log-opts=--no-merges --first-parent BASE..HEAD); + # it is a scan-scope choice, not a rule/finding suppression. + if [ -n "${base_sha}" ] && [ "${base_sha}" != "${null_sha}" ] \ + && git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then + log_opts="--no-merges --first-parent ${base_sha}..${head_sha}" + else + # No resolvable base (new branch / force push): scan the head commit. + # No --no-merges here: it could filter out a merge head and leave us + # silently scanning zero commits, which would pass without checking. + log_opts="-1 ${head_sha}" + fi + echo "Scanning commit range: ${log_opts}" + + # --redact keeps any match out of the job log. Exit code is left at the + # gitleaks default (1 when leaks are found), so a leak fails this check. + gitleaks git \ + --config .gitleaks.toml \ + --redact \ + --no-banner \ + --verbose \ + --log-opts="${log_opts}" \ + . + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..20197c7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# sscsb: generated output (SBOMs, receipts, VEX), not policy +.sscsb/out/ diff --git a/.sscsb/best-practices-badge.md b/.sscsb/best-practices-badge.md new file mode 100644 index 0000000..2022711 --- /dev/null +++ b/.sscsb/best-practices-badge.md @@ -0,0 +1,52 @@ +# OpenSSF Best Practices Badge — worksheet for grcengineering/homebrew-grcengineering + +`sscsb` can't register the badge for you (it needs your GitHub OAuth), but it +CAN make earning the **passing** badge a copy-paste exercise: most passing +criteria are already satisfied by the controls sscsb installs. Register, then +paste the evidence below. + +**Register:** https://www.bestpractices.dev/ → "Get Your Project Badge" → +sign in with GitHub → add `https://github.com/grcengineering/homebrew-grcengineering`. + +**Scorecard link:** OpenSSF Scorecard's `CII-Best-Practices` check reads the +badge API for this repo, so earning the badge also lifts your Scorecard score. + +## Passing criteria → evidence in THIS repository + +sscsb generates this table from its stock control list. It has been corrected to +what this repository actually enforces: a tap is a distribution channel with no +build, no releases and no package dependencies of its own, so several stock rows +are genuinely not applicable here rather than pending. A worksheet that claims a +control the repo does not run is worse than no worksheet — it is the kind of +unearned assurance this whole tap exists to prevent. + +| Criterion (passing level) | Evidence here | Status | +|---|---|---| +| Project has an OSS license | `LICENSE` (MIT) | ☑ | +| Public version-controlled source repo | GitHub `grcengineering/homebrew-grcengineering` | ☑ | +| Automated test suite runs in CI | `.github/workflows/tests.yml` (`brew test-bot`: `brew style`, `brew audit`, formula install/test) | ☑ | +| Static analysis (SAST) applied | `sast` (OpenGrep, `.github/workflows/sast-opengrep.yml`) + `codeql` (`actions` and `ruby` extractors) | ☑ | +| Vulnerability scanning of dependencies | n/a — the only dependency surface this repo owns is its GitHub Actions, which are SHA-pinned (`actions-audit`) and updated by Dependabot. There are no lockfiles or package manifests to scan; `vuln-scan` is off for that reason. | ☑ (n/a) | +| No unpatched medium+/high vulns | n/a, same reason as the row above | ☑ (n/a) | +| Secrets not committed; scanned | `secrets` — TruffleHog + Gitleaks at pre-commit, pre-push and in CI on the commits under review (`.github/workflows/secrets-scan.yml`) | ☑ | +| Vulnerability reporting process documented | `SECURITY.md` + private GitHub Security Advisories | ☑ | +| Cryptographic signing of releases | n/a — this tap publishes no releases. What it does instead is the harder half: `formula-integrity.yml` verifies UPSTREAM's Sigstore/SLSA signatures for every artifact a formula points at, pinned to the expected source repo and tag, on every PR, every push to `main`, and weekly. | ☑ (n/a) | +| Delivery over TLS / pinned deps | all actions SHA-pinned (`actions-audit`, `workflow-audit-extended`); all formula URLs are HTTPS with pinned `sha256` | ☑ | +| Change control (PRs, protected branch) | `branch-protection` verifies `main`: required PRs, signed commits, required status checks, no force-push, no deletion | ☑ | +| SBOM published | n/a — no build and no released artifact to describe. Upstream `nthpartyfinder` publishes the SBOM for the bytes this tap installs. | ☑ (n/a) | + +### Known gaps (open, not waved through) + +- **Approving reviews are not required on `main`.** Scorecard scores `Code-Review` + 0 for this repo. The cause is structural, not neglect: a solo maintainer cannot + self-approve, so turning the requirement on would block all work. Remediation is + a second maintainer, then `sscsb harden branch-protection --require-reviews`. +- **The human signing key is device-auth-gated, not hardware-resident.** See + `.sscsb/policy/signers.toml`; `require_hardware_backed = true` stays set in + `.sscsb/config.toml` as the standing target, and the remediation is a YubiKey + `-sk` key. +- **The badge itself is not registered.** Registration needs the maintainer's + GitHub OAuth and cannot be automated from here. + +_Generated by sscs-bootstrapper. Re-run `sscsb init` after deleting this file to +regenerate._ diff --git a/.sscsb/config.toml b/.sscsb/config.toml index b02b4df..e4c6ed1 100644 --- a/.sscsb/config.toml +++ b/.sscsb/config.toml @@ -15,12 +15,25 @@ github_repo = "grcengineering/homebrew-grcengineering" # ── Phase 1 — Local source integrity ── -# Secret scanning hooks: TruffleHog + Gitleaks block secrets at pre-commit and pre-push +# Secret scanning hooks: TruffleHog and Gitleaks both block secrets at pre-commit +# and pre-push. +# +# Both run, deliberately. TruffleHog VERIFIES a candidate credential against the +# issuing provider, so it can tell "this looks like a key" apart from "this key is +# live right now" (`--results=verified,unknown` keeps unverifiable candidates in +# scope). Gitleaks runs alongside it: independent probes showed it catches generic +# secrets (e.g. `api_key = ""`) and unverifiable keys that TruffleHog's +# verified/unknown filter still drops — a detection class TruffleHog alone does +# not cover. [controls.secrets] enabled = true trufflehog = true gitleaks = true pre_push_range_scan = true +# sscsb 0.4.0 writes the sample `.gitleaks.toml` whenever the `secrets` control is +# enabled. With `gitleaks = true` that file is live config for the engine actually +# running here, not an orphan — review and maintain it like any other scanner +# config; don't delete it. # CommitSigningGuard: Hardware-backed, human-only signing enforced on protected branches at pre-push [controls.commit-signing] @@ -36,10 +49,12 @@ allowed_backends = ["github-app", "tpm", "fido2", "kms", "piv", "software"] max_key_age_days = 90 # Five-environment signing model: Machine-wide signing posture: human enclave lane, distinct agent identity, cloud/web/Codespaces guidance +# Lane identities are not config keys in sscsb 0.4.0 — the human key lives in +# .sscsb/policy/signers.toml and the un-probeable lanes (cloud / web / Codespaces) +# are dated attestations in .sscsb/policy/signing-model.toml. Setting `agent` / +# `human_backend` here was silently ignored on every run. [controls.signing-model] enabled = true -agent = "claude-code" -human_backend = "secretive" # Branch protection verification: Verify GitHub protected-branch rules (PRs, no force-push, signatures, checks) [controls.branch-protection] @@ -110,18 +125,62 @@ enabled = false [controls.slsa-provenance] enabled = false -# Provenance verification gates: slsa-verifier + cosign verification required before promote/deploy/publish +# GitHub artifact attestations / GitHub SBOM attestation: DISABLED, and the reason is +# structural rather than a deferral. +# +# Both controls install an `on: release published` workflow that builds something, +# attests the bytes, and verifies the attestation. This repository is a Homebrew TAP: +# it has no build, no tags and no releases (`gh release list` is empty, `git tag` is +# empty), and it never will — it ships Ruby metadata describing artifacts that are +# built, signed and attested in grcengineering/nthpartyfinder. Enabling them here +# would add two workflows that either never fire, or, if a tag were ever cut, attest +# a `git archive` tarball of the tap's own formula files. Attesting a stub is not +# provenance; it is a green check over a claim nobody makes. +# +# The provenance question a tap actually has to answer — "are the bytes this formula +# points at the ones upstream built?" — is answered by formula-integrity.yml, which +# downloads every (url, sha256) pair and verifies it against upstream's keyless +# signing identity with cosign and slsa-verifier, pinned to the expected source repo +# and tag, on every PR, every push to main, and weekly against already-merged +# formulae. The `provenance-verify` control below is the sscsb control that gates it. +# +# Re-enable both the day this repo builds and publishes an artifact of its own. +[controls.github-attestations] +enabled = false + +[controls.sbom-attestation] +enabled = false + +# Provenance verification gates: slsa-verifier + cosign verification required before +# promote/deploy/publish. Enabled — but note that `sscsb init` writes a +# `.github/workflows/deploy-gate.yml` for this control, and that workflow is +# unreachable in a tap: its `workflow_call` entry is only invoked by a `release.yml` +# this repo does not have, and its `workflow_dispatch` entry needs a published +# release tag (this repo has none). It is deliberately not committed; delete it if a +# future `sscsb init` puts it back. The verification that matters here runs in +# formula-integrity.yml against UPSTREAM's artifacts, which is what a distribution +# channel actually has to verify. [controls.provenance-verify] enabled = true +# Without this, `sscsb provenance verify` accepts provenance from ANY builder +# slsa-verifier trusts for the source repo — "something built this" rather than +# "the builder we expect built this". Pinned to the builder that actually produced +# the provenance the tap's formulae point at: read out of +# grcengineering/nthpartyfinder v1.8.3's multiple.intoto.jsonl +# (predicate https://slsa.dev/provenance/v0.2), not assumed. +builder_id = "https://github.com/slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@refs/tags/v2.1.0" # Octo STS federation: Short-lived repo-scoped GitHub credentials replacing long-lived PATs [controls.octo-sts] enabled = false # Harden-Runner: StepSecurity Harden-Runner egress/tamper monitoring in every workflow +# The egress policy itself is a per-workflow input (`with: egress-policy:`), not a +# config key sscsb 0.4.0 reads; setting `egress_policy` here was silently ignored. +# Every workflow in this repo runs harden-runner in `audit` mode — the audit output +# is the input to a future `block` allowlist. [controls.harden-runner] enabled = true -egress_policy = "audit" # Witness (optional): Richer in-toto attestation capture and policy around build steps [controls.witness] diff --git a/.sscsb/osps-baseline.md b/.sscsb/osps-baseline.md new file mode 100644 index 0000000..da1adf8 --- /dev/null +++ b/.sscsb/osps-baseline.md @@ -0,0 +1,48 @@ +# OSPS Baseline assessment — grcengineering/homebrew-grcengineering + +The [OpenSSF Project Security Baseline](https://baseline.openssf.org/) is a set of +minimum, maturity-tiered security requirements. sscsb maps the controls it installs +to the Baseline's requirement families so you can see, and attest to, which the repo +already satisfies. Run `sscsb report` for the live, machine-readable version (the +OSPS column) and `sscsb report --format json` for evidence. + +## Coverage by requirement family + +| OSPS family | Intent | Covered by sscsb controls | +|---|---|---| +| **OSPS-AC** Access Control | protect the primary branch; least-privilege access | `branch-protection`, `commit-signing`, `gittuf` | +| **OSPS-BR** Build & Release | integrity/provenance of source and released assets | `sigstore-signing`, `slsa-provenance`, `github-attestations`, `sbom-attestation`, `provenance-verify`, `model-signing`, `actions-audit` | +| **OSPS-QA** Quality | dependency transparency, review, well-documented code | `sbom`, `renovate`, `package-trust`, `sast` | +| **OSPS-SA** Security Assessment | architecture/security documentation | `security-insights`, `scorecard` | +| **OSPS-VM** Vulnerability Management | reporting process + finding/fixing defects | `vuln-scan`, `codeql`, `fuzzing`, `openvex`, `security-insights` | +| **OSPS-DO** Documentation | user & security docs | `SECURITY.md` (installed), `security-insights` | +| **OSPS-LE** Legal | license present, DCO/CLA | `LICENSE` (confirm) | +| **OSPS-GV** Governance | roles, decision-making | maintainer-authored (`security-insights` roles) | + +## What this table is, and is not, for this repository + +The table above is sscsb's generic control-to-family mapping: it says which sscsb +control WOULD cover each family, not which are enabled here. Several named controls +are deliberately off in this tap because it has no build, no releases and no package +dependencies of its own — `sbom`, `vuln-scan`, `renovate`, `package-trust`, +`sigstore-signing`, `slsa-provenance`, `github-attestations`, `sbom-attestation`, +`fuzzing`, `openvex`, `model-signing`, `gittuf`. `sscsb status` is the live answer; +`.sscsb/config.toml` carries the reason beside each toggle. + +What covers **OSPS-BR** here is not an attestation this repo produces but one it +CHECKS: `formula-integrity.yml` verifies upstream's Sigstore bundle or SLSA +provenance for every artifact a formula points at, pinned to the expected source +repository and tag, on every pull request, every push to `main`, and weekly against +already-merged formulae. For a distribution channel that is the load-bearing +Build & Release control; signing the tap's own Ruby files would attest nothing a +user consumes. + +## Maturity note + +sscsb's controls target the Baseline's **Level 1–2** technical requirements (the +machine-enforceable ones). Level-3 and the Documentation/Legal/Governance families +include human attestations sscsb cannot auto-satisfy — fill those in your +`security-insights.yml` and project docs. + +_Generated by sscs-bootstrapper. Mappings use real OSPS family IDs from +github.com/ossf/security-baseline. Delete + re-run `sscsb init` to regenerate._ diff --git a/.sscsb/policy/allowed_signers b/.sscsb/policy/allowed_signers index 45f5156..eaba490 100644 --- a/.sscsb/policy/allowed_signers +++ b/.sscsb/policy/allowed_signers @@ -1,2 +1,2 @@ # Generated by sscsb from .sscsb/policy/signers.toml — do not edit. -10093271+p4gs@users.noreply.github.com namespaces="git" ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ6+H5pdok/8I/b+254AhexNJmkzfwCI7wnBqi6LLwkKIHLxcjy9ADFYuhK9fvKKshsu9Ld2e0YRs8BbvF4zUHM= Git-Signing@secretive.mbp.local +10093271+p4gs@users.noreply.github.com namespaces="git,sscsb-scan-record" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBxEAReKc/G/sUxY/UbXprOccUKaxhd+sr/7Gbb40u9w github-signing@1password.p4gs diff --git a/.sscsb/policy/signers.toml b/.sscsb/policy/signers.toml index b61ff07..05d0acf 100644 --- a/.sscsb/policy/signers.toml +++ b/.sscsb/policy/signers.toml @@ -10,7 +10,9 @@ # which is exactly the diff an attacker wants merged and exactly the diff that # looks most boring to a reviewer. Requiring a hardware-backed human signature # on every such commit is the control that makes an automated path, or a stolen -# credential, insufficient on its own. +# credential, insufficient on its own. The current key is device-auth-gated rather +# than hardware-resident (see the signer entry below) — that is a recorded gap with +# a named remediation, not a silent one. # # AI agents draft changes here; they do not sign them. The `agent-signing` # control is off, so no `class = "ai"` key is emitted into allowed_signers at @@ -20,8 +22,30 @@ [[signer]] principal = "10093271+p4gs@users.noreply.github.com" class = "human" -# Apple Secure Enclave via Secretive. The private key is non-exportable and -# every signature requires a physical Touch ID tap, so a signed commit here -# carries evidence that a specific human was present at signing time. -hardware_backed = true -ssh_public_key = "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJ6+H5pdok/8I/b+254AhexNJmkzfwCI7wnBqi6LLwkKIHLxcjy9ADFYuhK9fvKKshsu9Ld2e0YRs8BbvF4zUHM= Git-Signing@secretive.mbp.local" +# Active human signer since 2026-08-02: the 1Password-vaulted ed25519 key +# ("GitHub Signing Key (p4gs)"), signed through 1Password's op-ssh-sign and +# registered on GitHub as a signing key. +# +# This file previously listed an Apple Secure Enclave key (ecdsa-sha2-nistp256, +# Git-Signing@secretive.mbp.local) that was RETIRED on 2026-08-02. That left this +# policy unable to validate a single commit signed since — `sscsb hook pre-push` +# rejects with "signature cannot be validated against approved signers (status E)" +# for exactly that reason. An approved-signers list that does not contain the key +# doing the signing is not a strict policy, it is a broken one. +# +# The retired key is deliberately NOT carried here: this file governs which keys +# may LAND a commit, not which historical signatures still verify. Verifying +# pre-August commits is the job of the machine-global ~/.ssh/allowed_signers, +# which keeps the retired key, annotated as retired, for precisely that purpose. +# +# hardware_backed = false is the honest value, and honest is the point. The private +# key is stored encrypted in the 1Password vault and every signature requires a +# device unlock (Touch ID / system auth), which is real presence evidence — but the +# key is not resident on a security key, it is not an `ssh-ed25519-sk` credential, +# and it is exportable from the vault. Declaring it hardware-backed would attest a +# property it does not have. `require_hardware_backed = true` stays set in +# config.toml as the standing target: the remediation is a YubiKey `-sk` key, not a +# truer-sounding flag in this file. +backend = "software" +hardware_backed = false +ssh_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBxEAReKc/G/sUxY/UbXprOccUKaxhd+sr/7Gbb40u9w github-signing@1password.p4gs" diff --git a/.sscsb/policy/signing-model.toml b/.sscsb/policy/signing-model.toml index 45b1010..2ff364a 100644 --- a/.sscsb/policy/signing-model.toml +++ b/.sscsb/policy/signing-model.toml @@ -17,3 +17,31 @@ # [cloud-claude] # github_app_installed = "YYYY-MM-DD" # authorized the Claude GitHub App (not a personal token) # signing_mode = "app-signed" # app-signed | unsigned-drafts + +# ── Why every lane below is still unattested (recorded 2026-09-12) ── +# +# `sscsb verify signing-model` reports DEGRADED for this repository, and that is a +# deliberate, documented state rather than an oversight. An attestation here is a +# dated assertion of fact; writing one that has not happened would turn a control +# into a lie, which is the one failure mode this file exists to prevent. +# +# github-web (vigilant_mode, phishing_resistant_mfa) and codespaces +# (gpg_verification) are settings on the maintainer's GitHub ACCOUNT with no read +# API — sscsb cannot probe them and neither can this repository. Only the account +# holder can run `sscsb signing setup --confirm`, and only after actually +# performing the steps. Nothing in CI or in this repo can close these. +# +# agent-claude-code and cloud-claude both want a DISTINCT AI signing identity +# (a GIT_CONFIG_* env block for the local agent; a repo-level .claude/settings.json +# for cloud containers) so agent commits do not inherit the human's identity. That +# is good advice in general and it is NOT what this maintainer's standing policy +# says: as of 2026-08-02 there is exactly one signer across every repository and +# every machine — the human's 1Password-vaulted key in .sscsb/policy/signers.toml — +# and the separate agent identity was explicitly retired. Converging these two lanes +# would re-create the identity sscsb is asking for by contradicting the policy that +# removed it, so they stay open by decision. +# +# The control that actually keeps an agent off `main` here is not this file: it is +# `agent-signing = false` in config.toml, which emits no class="ai" key into +# allowed_signers at all, plus branch protection requiring signed commits and pull +# requests. An AI signature cannot be made verification-valid on this repo. diff --git a/Casks/nthpartyfinder.rb b/Casks/nthpartyfinder.rb index 4ad7a62..b61a63c 100644 --- a/Casks/nthpartyfinder.rb +++ b/Casks/nthpartyfinder.rb @@ -23,20 +23,21 @@ sha256 arm: "ee50de230c607c6cba9106059d30ac16948348e6511bfcfac3562b005fa13a9b", intel: "a3377ae60110b524b188ba1354d9e0f9ba35c6dd5e7c45e4135534bd6db47c7a" - url "https://github.com/grcengineering/nthpartyfinder/releases/download/v#{version}/nthpartyfinder-#{arch}-apple-darwin.tgz", - verified: "github.com/grcengineering/nthpartyfinder/" + url "https://github.com/grcengineering/nthpartyfinder/releases/download/v#{version}/nthpartyfinder-#{arch}-apple-darwin.tgz" name "Nth Party Finder" desc "CLI tool for identifying Nth party vendor relationships through DNS analysis" homepage "https://grc.engineering/" - # macOS-only: the artifact is a -apple-darwin binary, so `brew readall --os=all` (run by the - # tap's test-bot) requires an explicit macOS declaration — without it the Linux simulation - # leaves sha256 nil and the audit fails. Symbol form (`:big_sur`), not the deprecated string - # comparison form. - depends_on macos: :big_sur + # Stanza order is fixed by Homebrew's `Cask/StanzaOrder` cop: cask, then formula, then macos. + depends_on cask: "google-chrome" depends_on formula: "subfinder" depends_on formula: "whois" - depends_on cask: "google-chrome" + # macOS-only: the artifact is a -apple-darwin binary, so `brew readall --os=all` (run by the + # tap's test-bot) requires an explicit macOS declaration — without it the Linux simulation + # leaves sha256 nil and the audit fails. Plain `:macos`, not a minimum version: Homebrew's + # `Homebrew/OSDependsOn` cop rejects `macos: :big_sur` as redundant: Big Sur is the oldest + # macOS Homebrew still recognises, so that minimum excludes nothing. + depends_on :macos binary "nthpartyfinder" diff --git a/security-insights.yml b/security-insights.yml new file mode 100644 index 0000000..ce181c9 --- /dev/null +++ b/security-insights.yml @@ -0,0 +1,37 @@ +# OpenSSF Security Insights — machine-readable security posture for this project. +# Spec: https://github.com/ossf/security-insights-spec (schema v2). +# sscsb generated this valid starter. Any placeholder values sscsb leaves behind +# need real information filled in — then validate with si-tooling (`si validate`). +# `sscsb verify security-insights` reports Info until every placeholder is gone. +# +# Only the `header` + `project` blocks are emitted (both validate on their own). +# Add the optional `repository:` block (status, core-team, license, security +# posture) when you're ready to attest repository-level details. +header: + schema-version: "2.0.0" + last-updated: "2026-09-12" + last-reviewed: "2026-09-12" + url: "https://github.com/grcengineering/homebrew-grcengineering/blob/main/security-insights.yml" + comment: | + Generated by sscs-bootstrapper. Supply-chain controls (secret scanning, + signing, SBOM, vulnerability scanning, SLSA provenance) are enforced via the + .sscsb config and .github/workflows installed by `sscsb init`. +project: + name: "grcengineering/homebrew-grcengineering" + homepage: "https://github.com/grcengineering/homebrew-grcengineering" + administrators: + - name: "Justin Pagano" + affiliation: "GRC Engineering" + primary: true + repositories: + - name: "grcengineering/homebrew-grcengineering" + comment: "Primary repository this Security Insights file is published in." + url: "https://github.com/grcengineering/homebrew-grcengineering" + vulnerability-reporting: + reports-accepted: true + bug-bounty-available: false + # sscsb installs SECURITY.md; adjust if you relocate the policy. + security-policy: "https://github.com/grcengineering/homebrew-grcengineering/blob/main/SECURITY.md" + comment: "Report privately via GitHub Security Advisories on this repository." + documentation: + detailed-guide: "https://github.com/grcengineering/homebrew-grcengineering/blob/main/SECURITY.md"