From d190b53b1414ce98e3896f94eaabd86c2ee347d6 Mon Sep 17 00:00:00 2001 From: Robert DeLanghe <1240090+bdelanghe@users.noreply.github.com> Date: Sun, 28 Jun 2026 18:06:39 -0400 Subject: [PATCH] =?UTF-8?q?feat(conformance):=20port=20external-grader=20c?= =?UTF-8?q?ells=20=E2=80=94=20OpenSSF=20Scorecard,=20HSTS=20preload,=20SLS?= =?UTF-8?q?A=20build=20level?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirrors bounded-systems/lone#15 into the kit's vendored port. Three new criteria scored from INDEPENDENT third-party graders — independent by construction, so no `verifiedBy` — all recommended (required:false, non-gating), purely additive. - security.hsts-preload (`hstsPreload`) — met when origin is on the HSTS preload list. - integrity.scorecard (`scorecard`) — met when OpenSSF Scorecard score ≥ 7.0. - integrity.slsa-level (`slsaLevel`) — met when build level ≥ target (default L3); distinct from integrity.slsa-provenance (present/signed/verified). Adds the CRITERIA entries, the ENVELOPE fields, the evaluators, the shared SCORECARD_THRESHOLD, and tests. node test/run.mjs → 12 passed, 0 failed. Co-Authored-By: Claude Opus 4.8 (1M context) --- gates/conformance/conformance.mjs | 24 +++++++++++++++++ gates/conformance/web-build.mjs | 45 +++++++++++++++++++++++++++++++ test/run.mjs | 24 +++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/gates/conformance/conformance.mjs b/gates/conformance/conformance.mjs index b9ad115..43f5adc 100644 --- a/gates/conformance/conformance.mjs +++ b/gates/conformance/conformance.mjs @@ -35,6 +35,9 @@ const met = (detail) => ({ status: "met", detail }); const unmet = (detail) => ({ status: "unmet", detail }); const notAssessed = (detail) => ({ status: "not-assessed", detail }); +/** The OpenSSF Scorecard score at/above which `integrity.scorecard` is `met`. */ +const SCORECARD_THRESHOLD = 7.0; + // Per-criterion evaluator for external evidence. Returns `not-assessed` when the // relevant evidence field is absent; otherwise checks shape/thresholds. const EXTERNAL_EVALUATORS = { @@ -93,6 +96,13 @@ const EXTERNAL_EVALUATORS = { ? met("0 known critical/high vulns") : unmet(`${v.knownCriticalOrHighVulns} known critical/high vuln(s)`); }, + "security.hsts-preload": (e) => { + const v = e.hstsPreload; + if (!v) return notAssessed("no HSTS preload status supplied"); + return v.preloaded + ? met("origin is on the HSTS preload list") + : unmet("origin is not on the HSTS preload list"); + }, "performance.core-web-vitals": (e) => { const samples = e.coreWebVitals; if (!samples || samples.length === 0) { @@ -197,6 +207,20 @@ const EXTERNAL_EVALUATORS = { ? met("SLSA/in-toto provenance present, signed, and verified") : unmet(gaps.join(", ")); }, + "integrity.slsa-level": (e) => { + const v = e.slsaLevel; + if (!v) return notAssessed("no SLSA build level supplied"); + return v.level >= v.target + ? met(`SLSA build Level ${v.level} (target L${v.target})`) + : unmet(`SLSA build Level ${v.level} below target L${v.target}`); + }, + "integrity.scorecard": (e) => { + const v = e.scorecard; + if (!v) return notAssessed("no OpenSSF Scorecard result supplied"); + return v.score >= SCORECARD_THRESHOLD + ? met(`OpenSSF Scorecard ${v.score.toFixed(1)} (≥ ${SCORECARD_THRESHOLD})`) + : unmet(`OpenSSF Scorecard ${v.score.toFixed(1)} below ${SCORECARD_THRESHOLD}`); + }, "integrity.reproducible-build": (e) => { const v = e.reproducibleBuild; if (!v) return notAssessed("no reproducible-build report supplied"); diff --git a/gates/conformance/web-build.mjs b/gates/conformance/web-build.mjs index 96c69c6..5b6b8ff 100644 --- a/gates/conformance/web-build.mjs +++ b/gates/conformance/web-build.mjs @@ -153,6 +153,18 @@ export const CRITERIA = [ evidence: "external", required: true, }, + { + // External grader — Chromium-maintained HSTS preload list. Independent by + // construction, so it needs no `verifiedBy`. Recommended (non-gating). + id: "security.hsts-preload", + area: "security", + label: "HSTS preload", + standard: "RFC 6797 / hstspreload.org", + target: "Origin is on the HSTS preload list (HTTPS enforced before first byte).", + level: "preloaded", + evidence: "external", + required: false, + }, // ── Performance — Core Web Vitals ──────────────────────────────────────── { @@ -336,6 +348,33 @@ export const CRITERIA = [ required: false, tier: 3, }, + // ── Integrity — external graders (independent by construction) ──────────── + { + // OpenSSF Scorecard — automated third-party grader of repo security posture + // (0–10). Independent, so no `verifiedBy`. Recommended (non-gating). + id: "integrity.scorecard", + area: "integrity", + label: "OpenSSF Scorecard", + standard: "OpenSSF Scorecard", + target: "Repository scores ≥ 7.0 on the OpenSSF Scorecard.", + level: "score ≥ 7.0", + evidence: "external", + required: false, + tier: 3, + }, + { + // SLSA build LEVEL achieved (distinct from `integrity.slsa-provenance`, which + // only checks provenance is present/signed/verified). Recommended (non-gating). + id: "integrity.slsa-level", + area: "integrity", + label: "SLSA build level", + standard: "SLSA", + target: "Build achieves the targeted SLSA build level (default L3).", + level: "≥ target (default L3)", + evidence: "external", + required: false, + tier: 3, + }, // ══ COGNITIVE ACCESSIBILITY — W3C COGA ═════════════════════════════════════ // HONEST LABELING: an INTERFACE-COMPLEXITY BUDGET (W3C COGA-derived), explicitly @@ -465,6 +504,8 @@ const ENVELOPE = { // OSV). Decoupled from `asvs` so an objective vuln count can be supplied WITHOUT // also self-grading an ASVS level. vulns: opt(vObject({ knownCriticalOrHighVulns: req(vInt0) })), + // External grader — Chromium HSTS preload list. Independent; no `verifiedBy`. + hstsPreload: opt(vObject({ preloaded: req(vBool) })), coreWebVitals: opt(vArrayOf(vObject(CWV_SAMPLE_SHAPE))), baseline: opt(vObject({ status: req(vEnum("widely", "newly", "limited")), @@ -494,6 +535,10 @@ const ENVELOPE = { feeds: opt(vObject({ atomValid: req(vBool) })), // tier-3 slsaProvenance: opt(vObject({ present: req(vBool), signed: req(vBool), verified: req(vBool) })), + // External grader — SLSA build LEVEL achieved (distinct from slsaProvenance). + slsaLevel: opt(vObject({ level: req(vEnum(0, 1, 2, 3)), target: def(vEnum(1, 2, 3), 3) })), + // External grader — OpenSSF Scorecard score (0–10). Independent; no `verifiedBy`. + scorecard: opt(vObject({ score: req(vNum(0, 10)) })), reproducibleBuild: opt(vObject({ reproducible: req(vBool) })), sbom: opt(vObject({ present: req(vBool), valid: req(vBool), complete: req(vBool), signed: req(vBool) })), contentDigests: opt(vObject({ reprDigestHeaders: req(vBool) })), diff --git a/test/run.mjs b/test/run.mjs index 4687a62..237ed7c 100755 --- a/test/run.mjs +++ b/test/run.mjs @@ -217,6 +217,30 @@ await test("gates/conformance-report: build + render the conformance projection" if (byIdV["security.no-critical-vulns"].status !== "unmet") throw new Error("3 vulns must be unmet, no asvs object required"); if (byIdV["security.asvs"].status !== "not-assessed") throw new Error("absent asvs must be not-assessed"); + // (e) external graders (Scorecard / HSTS / SLSA level) — independent third-party + // grades, assessable on their own, recommended (non-gating). + const statusById = (r) => Object.fromEntries(r.results.map((x) => [x.id, x.status])); + const absent = statusById(buildConformanceReport({ evidence: {} })); + for (const id of ["security.hsts-preload", "integrity.scorecard", "integrity.slsa-level"]) { + if (absent[id] !== "not-assessed") throw new Error(`${id} absent must be not-assessed`); + } + const graders = statusById(buildConformanceReport({ + evidence: { + hstsPreload: { preloaded: true }, + scorecard: { score: 7.0 }, + slsaLevel: { level: 3 }, // target defaults to L3 + }, + })); + if (graders["security.hsts-preload"] !== "met") throw new Error("preloaded HSTS must be met"); + if (graders["integrity.scorecard"] !== "met") throw new Error("Scorecard 7.0 must be met"); + if (graders["integrity.slsa-level"] !== "met") throw new Error("SLSA L3 (target L3) must be met"); + const gradersBad = statusById(buildConformanceReport({ + evidence: { hstsPreload: { preloaded: false }, scorecard: { score: 6.9 }, slsaLevel: { level: 2 } }, + })); + if (gradersBad["security.hsts-preload"] !== "unmet") throw new Error("non-preloaded HSTS must be unmet"); + if (gradersBad["integrity.scorecard"] !== "unmet") throw new Error("Scorecard 6.9 must be unmet"); + if (gradersBad["integrity.slsa-level"] !== "unmet") throw new Error("SLSA L2 below target L3 must be unmet"); + // malformed envelope → throw (lone refuses to guess). let threw = false; try { buildConformanceReport({ evidence: { sbom: { present: "yes" } } }); } catch { threw = true; }