From 0923f2c8bc8dd0f64a0f2b91445d4fbbd1e6d75a Mon Sep 17 00:00:00 2001 From: Eddie Knight Date: Fri, 7 Aug 2026 05:33:37 -0500 Subject: [PATCH] fix: require audit results to reference declared criteria Signed-off-by: Eddie Knight --- auditlog.cue | 8 ++++ test/schema_test.go | 1 + .../bad-audit-log-undeclared-criteria.yaml | 48 +++++++++++++++++++ test/test-data/good-audit-log.yaml | 3 ++ 4 files changed, 60 insertions(+) create mode 100644 test/test-data/bad-audit-log-undeclared-criteria.yaml diff --git a/auditlog.cue b/auditlog.cue index ab9505b0..42709af1 100644 --- a/auditlog.cue +++ b/auditlog.cue @@ -4,6 +4,8 @@ @status("experimental") package gemara +import "list" + @go(gemara) // AuditLog records results from an audit performed against a target resource @@ -25,6 +27,12 @@ package gemara if results != _|_ { _uniqueResultIds: {for i, r in results {(r.id): i}} + let _validCriteriaIds = [for c in criteria {c."reference-id"}] + + // Unify the valid ID list with a list.Contains constraint to require each result scores against declared criteria + for i, r in results { + _criteriaValidation: "\(i)": _validCriteriaIds & list.Contains(r."criteria-reference"."reference-id") + } } } diff --git a/test/schema_test.go b/test/schema_test.go index d7e88708..7a7be0f0 100644 --- a/test/schema_test.go +++ b/test/schema_test.go @@ -122,6 +122,7 @@ func TestSchemaValidation(t *testing.T) { // AuditLog — negative {"audit log missing summary criteria and results", "./test-data/bad-audit-log.yaml", "#AuditLog", true, ""}, {"audit log evidence source with invalid digest format", "./test-data/bad-audit-log-invalid-digest.yaml", "#AuditLog", true, ""}, + {"audit result referencing undeclared criteria", "./test-data/bad-audit-log-undeclared-criteria.yaml", "#AuditLog", true, ""}, // CapabilityCatalog — negative {"capability with invalid group", "./test-data/bad-capability-invalid-group.yaml", "#CapabilityCatalog", true, ""}, diff --git a/test/test-data/bad-audit-log-undeclared-criteria.yaml b/test/test-data/bad-audit-log-undeclared-criteria.yaml new file mode 100644 index 00000000..df0b85e8 --- /dev/null +++ b/test/test-data/bad-audit-log-undeclared-criteria.yaml @@ -0,0 +1,48 @@ +metadata: + id: audit-log-undeclared-criteria + type: AuditLog + gemara-version: "1.1.0" + version: "1.0.0" + description: "Invalid audit log: result scored against criteria the audit never declared" + author: + id: lead-auditor + name: "Auditor" + type: Human + mapping-references: + - id: security-policy + title: "Information Security Policy" + version: "2.1.0" + - id: OSPS + title: "Open Source Project Security Baseline" + version: "2025.1" + url: "https://baseline.openssf.org" + +target: + id: gemara-repo + name: "gemaraproj/gemara" + type: Software + uri: "https://github.com/gemaraproj/gemara" + environment: production + +owner: + responsible: + - name: "Auditor" + affiliation: "External Audit Firm" + accountable: + - name: "Project Lead" + affiliation: "OpenSSF" + +summary: "Criteria declaration test." + +criteria: + - reference-id: security-policy + +results: + - id: AR-AC-01 + title: "MFA enforcement verified" + type: Strength + description: "Scored against OSPS, which is not declared in criteria." + criteria-reference: + reference-id: OSPS + entries: + - reference-id: OSPS-AC-01 diff --git a/test/test-data/good-audit-log.yaml b/test/test-data/good-audit-log.yaml index e017b0cf..4d3c3df0 100644 --- a/test/test-data/good-audit-log.yaml +++ b/test/test-data/good-audit-log.yaml @@ -51,6 +51,9 @@ summary: "Access control and quality controls are strong. Documentation controls criteria: - reference-id: security-policy + remarks: "Organizational policy establishing the audit's scope." + - reference-id: OSPS + remarks: "Baseline whose controls each result is scored against." results: - id: AR-AC-01