What This Is

This guide walks through creating a control catalog using the Gemara project, building on the threats and scope you identified in the Threat Assessment Guide.

In technical terms:

This exercise produces a structured way to develop control objectives and corresponding testable conditions to determine if the objective is met.

Optional Workflow

Complete the Threat Assessment Guide for your scope (e.g., the container management tool SEC.SLAM.CM). You can reference the linked threats and guidelines to support the intent of Controls in the catalog.

Walkthrough

Step 0: Define Scope and References

Reuse the same component or technology as your threat assessment. You will reference that threat catalog so controls can map to the threats you identified.

Leverage existing resources: As with threat catalogs, you can import controls from external catalogs (e.g., FINOS Common Cloud Controls, OSPS Baseline) via mapping-references and list imported controls in your catalog.

We continue with the container management tool example (SEC.SLAM.CM) and assume a threat catalog for it already exists.

Step 1: Setting Up Metadata

Declare your control catalog and mapping references. Key fields:

Field What It Is Why
title Display name for the control catalog (top-level field) Human-readable label used in reports and tooling output
mapping-references with id: CCC Optional pointer to CCC or another control/threat catalog Resolve imported capability and control IDs from the referenced catalog
applicability-categories List of categories (id, title, description) for when controls apply Scope assessment requirements by context (e.g., production, CI/CD) so evaluators know when each requirement applies

Note: Applicability categories must be defined to assign applicability to controls.

Example (YAML):

title: Container Management Tool Security Control Catalog
metadata:
  id: SEC.SLAM.CM
  description: Control catalog for container management tool security; mitigates threats from the SEC.SLAM.CM threat catalog.
  version: 1.0.0
  author:
    id: example
    name: Example
    type: Human
  mapping-references:
    - id: SEC.SLAM.CM
      title: Container Management Tool Security Threat Catalog
      version: "1.0.0"
      url: file://threats.yaml
      description: |
        Threat catalog for the same scope; provides threat IDs for threat-mappings.
    - id: CCC
      title: Common Cloud Controls Core
      version: v2025.10
      url: https://github.com/finos/common-cloud-controls/releases
      description: |
        Foundational repository of reusable security controls, capabilities,
        and threat models maintained by FINOS.
  applicability-categories:
    - id: production
      title: Production
      description: |
        Production container workloads and clusters; controls apply to
        live environments where security posture is enforced.
    - id: all_deployments
      title: All Deployments
      description: |
        Requirements that apply whenever container images are built, pulled, or run—
        regardless of environment (dev, staging, production) or pipeline stage.
    - id: untrusted_networks
      title: Untrusted Networks
      description: |
        Applies when registry or image traffic traverses untrusted networks.
    - id: ci_cd
      title: CI/CD
      description: |
        Applies in continuous integration and deployment pipelines.

Step 2: Define Control Families

Families group controls by theme. The Layer 2 schema requires at least one family when the catalog defines its own controls. Each control’s family field must match the id of one of these groups.

Required fields for each family (see base.cue):

Field Required Description
id Yes Unique identifier referenced by controls
title Yes Short name for the family
description Yes Explanation of what controls in this family address

Example (YAML):

families:
  - id: SEC.SLAM.CM.FAM01
    title: Image Integrity and Supply Chain
    description: |
      Controls that ensure container images are authentic, unmodified,
      and from trusted sources throughout retrieval and use.

Step 3: Import or Define Controls

Note: For how controls are automatically pulled into policy to mitigate high-severity risks, see the FAQ.

Option A — Import Controls: If an external catalog (e.g., CCC) defines controls that address your threats, reference it in the mapping-references and list the control IDs in imports.controls.

Example (YAML):

imports:
  controls
  - reference-id: CCC
    entries:
      - reference-id: CCC.Core.CTL42
        remarks: Image signing and verification

Option B — Define your own controls: For controls specific to your scope, define them under controls. Required and common fields (see layer-2.cue):

Field Required Description
id Yes Unique identifier (e.g., ORG.PROJ.COMPONENT.CTL##)
title Yes Short name describing the control
objective Yes Unified statement of intent for the control
family Yes id of a family in this catalog (or in a referenced catalog for imports)
assessment-requirements Yes List of verifiable conditions; each has id, text, applicability
threats No Links to threat catalog(s) and threat IDs this control mitigates
state Yes Lifecycle: Active (default), Draft, Deprecated, Retired

Each assessment requirement (see layer-2.cue) must have:

Field Required Description
id Yes Unique within the control (e.g., SEC.SLAM.CM.CTL01.AR01)
text Yes Verifiable condition (typically a MUST statement)
applicability Yes List of strings describing when this requirement applies

Example (YAML):

controls:
  - id: SEC.SLAM.CM.CTL01
    title: Use Immutable Image References by Digest
    objective: |
      Require signature validation so that only legitimate, trusted images are
      accepted; then pin each image to an immutable digest (e.g., sha256)
      after the check so that what is used matches what was verified and
      TOCTOU (time-of-check to time-of-use) attacks are prevented.
    threats:
      - reference-id: SEC.SLAM.CM
        entries:
          - reference-id: SEC.SLAM.CM.THR01
          - reference-id: SEC.SLAM.CM.THR03
          - reference-id: SEC.SLAM.CM.THR04
      - reference-id: CCC
        entries:
          - reference-id: CCC.Core.TH14
  - id: SEC.SLAM.CM.CTL02
    title: Require TLS/SSL with Certificate Pinning
    objective: |
      Mitigate MITM Container Image Interception by protecting registry traffic and verifying artifact integrity: use
      TLS/SSL with certificate pinning for all registry communication, use VPNs on untrusted networks to reduce interception risk, and verify artifact signatures or hashes so that tampered or redirected content is detected even if the channel is compromised.
    threats:
      - reference-id: SEC.SLAM.CM
        entries:
          - reference-id: SEC.SLAM.CM.THR02
      - reference-id: CCC
        entries:
          - reference-id: CCC.Core.TH02
    family: SEC.SLAM.CM.FAM01
    state: Active
    assessment-requirements:
      - id: SEC.SLAM.CM.CTL02.AR01
        text: |
          The system MUST use TLS/SSL for all registry communication and MUST pin to the expected server certificate or public key (or certificate chain) for the registry.
        applicability: ["all_deployments"]
        state: Active
      - id: SEC.SLAM.CM.CTL02.AR02
        text: |
          On untrusted networks, the system or deployment pipeline MUST use a VPN or other trusted path for registry traffic, or MUST restrict
          image pulls to environments where the network is trusted.
        applicability: ["untrusted_networks", "ci_cd"]
        state: Active
      - id: SEC.SLAM.CM.CTL02.AR03
        text: |
          The system MUST verify artifact signatures or hashes (e.g. signature verification, digest check) before use so that tampered or redirected artifacts are rejected.
        applicability: ["all_deployments"]
        state: Active

Step 4: Validate Against the Layer 2 Schema

Validate the final catalog with CUE:

Validation commands:

go install cuelang.org/go/cmd/cue@latest
cue vet -c -d '#ControlCatalog' github.com/gemaraproj/gemara@latest your-control-catalog.yaml

Fix any reported errors (e.g., missing required fields, invalid family reference, or malformed threats) so the catalog is schema-consistent.

Step 5: Assemble the Full Catalog and Validate

Combine metadata, mapping-references, families, imported-controls (if any), and controls into a single YAML document. A complete, schema-valid catalog for the SEC.SLAM.CM scenario is in control-catalog.yaml in this directory.

Complete example (SEC.SLAM.CM):

title: Container Management Tool Security Control Catalog

metadata:
  id: SEC.SLAM.CM
  description: |
    Control catalog for container management tool security; mitigates threats
    from the SEC.SLAM.CM threat catalog.
  version: 1.0.0
  author:
    id: example
    name: Example
    type: Human
  mapping-references:
    - id: SEC.SLAM.CM
      title: Container Management Tool Security Threat Catalog
      version: "1.0.0"
      url: https://example.org/catalogs/SEC.SLAM.CM-threats.yaml
      description: |
        Threat catalog for the same scope; provides threat IDs for threat-mappings.
    - id: CCC
      title: Common Cloud Controls Core
      version: v2025.10
      url: https://github.com/finos/common-cloud-controls/releases
      description: |
        Foundational repository of reusable security controls, capabilities,
        and threat models maintained by FINOS.
  applicability-categories:
    - id: production
      title: Production
      description: |
        Production container workloads and clusters; controls apply to
        live environments where security posture is enforced.
    - id: all_deployments
      title: All Deployments
      description: |
        Requirements that apply whenever container images are built, pulled, or run—
        regardless of environment (dev, staging, production) or pipeline stage.
    - id: untrusted_networks
      title: Untrusted Networks
      description: |
        Applies when registry or image traffic traverses untrusted networks.
    - id: ci_cd
      title: CI/CD
      description: |
        Applies in continuous integration and deployment pipelines.

families:
  - id: SEC.SLAM.CM.FAM01
    title: Image Integrity and Supply Chain
    description: |
      Controls that ensure container images are authentic, unmodified, and from trusted sources throughout retrieval and use.

imports:
  controls:
  - reference-id: CCC
    entries:
      - reference-id: CCC.Core.CTL42
        remarks: Image signing and verification

controls:
  - id: SEC.SLAM.CM.CTL01
    title: Use Immutable Image References by Digest
    objective: |
      Require signature validation so that only legitimate, trusted images are accepted; then pin each image to an immutable digest (e.g., sha256) after the check so that what is used matches what was verified and TOCTOU (time-of-check to time-of-use) attacks are prevented.
    threats:
      - reference-id: SEC.SLAM.CM
        entries:
          - reference-id: SEC.SLAM.CM.THR01
          - reference-id: SEC.SLAM.CM.THR03
          - reference-id: SEC.SLAM.CM.THR04
      - reference-id: CCC
        entries:
          - reference-id: CCC.Core.TH14
  - id: SEC.SLAM.CM.CTL02
    title: Require TLS/SSL with Certificate Pinning
    objective: |
      Mitigate MITM Container Image Interception by protecting registry traffic and verifying artifact integrity: use
      TLS/SSL with certificate pinning for all registry communication, use VPNs on untrusted networks to reduce interception risk, and verify artifact signatures or hashes so that tampered or redirected content is detected even if the channel is compromised.
    threats:
      - reference-id: SEC.SLAM.CM
        entries:
          - reference-id: SEC.SLAM.CM.THR02
      - reference-id: CCC
        entries:
          - reference-id: CCC.Core.TH02
    family: SEC.SLAM.CM.FAM01
    state: Active
    assessment-requirements:
      - id: SEC.SLAM.CM.CTL02.AR01
        text: |
          The system MUST use TLS/SSL for all registry communication and MUST pin to the expected server certificate or public key (or certificate chain) for the registry.
        applicability: ["all_deployments"]
        state: Active
      - id: SEC.SLAM.CM.CTL02.AR02
        text: |
          On untrusted networks, the system or deployment pipeline MUST use a VPN or other trusted path for registry traffic, or MUST restrict image pulls to environments where the network is trusted.
        applicability: ["untrusted_networks", "ci_cd"]
        state: Active
      - id: SEC.SLAM.CM.CTL02.AR03
        text: |
          The system MUST verify artifact signatures or hashes (e.g. signature verification, digest check) before use so that tampered or redirected artifacts are rejected.
        applicability: ["all_deployments"]
        state: Active

Validate from the repo root:

cue vet -c -d '#ControlCatalog' ./layer-2.cue ./metadata.cue ./mapping.cue ./base.cue docs/tutorials/controls/control-catalog.yaml

Fix any reported errors (e.g., missing required fields, invalid family reference, or malformed threats) so the catalog is schema-consistent.

Summary: From Threat Assessment to Control Catalog

From threat assessment Use in control catalog
Scope / catalog id (e.g. SEC.SLAM.CM) Same id in control catalog metadata
Threat IDs (e.g. SEC.SLAM.CM.THR01, CCC.Core.TH14) threats on each control that mitigates those threats
Understanding of what goes wrong Control objectives and assessment requirements that prevent or detect it

What’s Next

Use the control catalog in downstream Gemara layers: for example, map controls to Layer 1 guidelines via guidelines, or use the catalog in Layer 5 evaluations to record which assessment requirements have been verified.

See the Gemara Layer 2 schema documentation for the full specification and optional fields (e.g., state, replaced-by, guidelines).