{
 "@context": {
  "skos": "http://www.w3.org/2004/02/skos/core#",
  "dcterms": "http://purl.org/dc/terms/",
  "owl": "http://www.w3.org/2002/07/owl#",
  "xsd": "http://www.w3.org/2001/XMLSchema#",
  "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
  "rdfs": "http://www.w3.org/2000/01/rdf-schema#",
  "foaf": "http://xmlns.com/foaf/0.1/",
  "cc": "http://creativecommons.org/ns#",
  "ost": "https://ostering.com/ns/taxonomy#"
 },
 "@graph": [
  {
   "@id": "https://ostering.com/taxonomies/software-factory/",
   "@type": "skos:ConceptScheme",
   "dcterms:title": {
    "@value": "Software Factory Threat Taxonomy",
    "@language": "en-GB"
   },
   "dcterms:alternative": {
    "@value": "The Factory Is the Target: A Threat Taxonomy for the Software Supply Chain",
    "@language": "en-GB"
   },
   "dcterms:description": {
    "@value": "231 entries in 18 groups. Each entry states a threat as a property of a component or a design decision, with the mitigation principle a sound design follows and concrete design measures. The reference for the card game Software Factory; the reference (skos:notation) is shared with the game and is a stable identifier, not a severity.",
    "@language": "en-GB"
   },
   "dcterms:creator": {
    "@id": "https://ostering.com/#brett-crawley"
   },
   "dcterms:publisher": {
    "@id": "https://ostering.com/"
   },
   "dcterms:issued": {
    "@value": "2026-10-26",
    "@type": "xsd:date"
   },
   "owl:versionInfo": "1.0",
   "dcterms:license": {
    "@id": "https://creativecommons.org/licenses/by-nc-nd/4.0/"
   },
   "cc:license": {
    "@id": "https://creativecommons.org/licenses/by-nc-nd/4.0/"
   },
   "dcterms:rights": {
    "@value": "© 2026 Jonathan Brett Crawley. This taxonomy is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International licence (CC BY-NC-ND 4.0), with the additional permissions below. Permission needed, by use: Sharing the whole taxonomy non-commercially (OWASP, universities, conferences, individuals): No; Threat modeling with it, including for paying clients: No; Internal use and training inside any organisation: No; Quoting entries, with credit, in paid courses, reports and talks: No; Shipping the taxonomy in a product: a tool's built-in library, a printed deck, a reprint for sale: Yes, ask me. Additional permissions: In addition to the rights the licence gives, and whether or not the use is commercial, the copyright holder grants you permission to: (1) use the taxonomy to threat model systems you build, operate or assess, including for paying clients; (2) use it internally, and for training, inside any organisation; (3) quote individual entries, with credit, in paid courses, reports, findings and talks. Any other commercial use, including shipping the taxonomy or a substantial part of it in a product (a tool's built-in library, a printed deck, a reprint for sale), needs written permission. Ask me on LinkedIn. These additional permissions are given alongside the licence. They add to what the licence allows and do not take anything away from it.",
    "@language": "en-GB"
   },
   "dcterms:rightsHolder": {
    "@id": "https://ostering.com/#brett-crawley"
   },
   "cc:attributionName": "Jonathan Brett Crawley",
   "cc:attributionURL": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "dcterms:source": {
    "@id": "https://ostering.com/"
   },
   "skos:hasTopConcept": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/#brett-crawley",
   "@type": "foaf:Person",
   "foaf:name": "Jonathan Brett Crawley",
   "foaf:homepage": {
    "@id": "https://ostering.com/"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "WS",
   "skos:prefLabel": {
    "@value": "Workstation and Agents",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The developer's machine holds credentials to everything downstream and runs more unvetted code than any server. These cards cover IDEs, extensions, dev containers, local tooling, and the AI assistants and agents that now act with a developer's authority.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "IDEs, extensions, dev containers, local credentials, AI coding assistants and agents, pre-commit hooks",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-2"
    }
   ],
   "ost:position": 1,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·A",
   "skos:prefLabel": {
    "@value": "Credential Hoard",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The workstation holds long-lived tokens for version control, registries, cloud and CI in dotfiles, keychains and CLI configs, and one piece of malware can collect them all.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Credentials on a developer machine are short-lived, bound to the device, and never sufficient on their own to publish or reach production.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Replace static tokens in dotfiles and CLI configs with short-lived credentials issued through single sign-on, refreshed by a credential helper rather than stored as files.",
      "@language": "en-GB"
     },
     {
      "@value": "Bind developer credentials to the device with hardware-backed keys, such as a platform authenticator or security key, so a copied token file does not work elsewhere.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep publish, protected-branch push and production rights out of developer credentials entirely, and grant them only to pipeline identities (see ID).",
      "@language": "en-GB"
     },
     {
      "@value": "Tie every developer credential to the identity provider session, so disabling one user revokes them all, and rehearse that revocation against a time target.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: CircleCI session theft (2023); Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/639.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/522.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/313.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/639.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/522.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·K",
   "skos:prefLabel": {
    "@value": "Agent with Developer Authority",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An AI coding agent runs commands, edits files and calls tools with the developer's credentials, and content it reads (issues, READMEs, dependencies, web pages) can instruct it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An agent acts under its own narrowly scoped identity, and any action with effect outside its sandbox needs a person's explicit approval.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run the agent in a container or VM with its own short-lived, least-privilege credentials, never the developer's session, keychain or SSH agent.",
      "@language": "en-GB"
     },
     {
      "@value": "Require per-action human approval for shell commands, writes outside the workspace and tool calls that change remote state, with an allow list for read-only actions.",
      "@language": "en-GB"
     },
     {
      "@value": "Treat repository text, issues, tool output and web content as data that cannot widen the agent's permissions or its approved tool set, whatever it says.",
      "@language": "en-GB"
     },
     {
      "@value": "Limit the agent's network egress to an allow list of model endpoints, the package proxy and the hosting platform, and log every outbound request.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Nx s1ngularity (2025); hackerbot-claw CLAUDE.md injection (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/248.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/248.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1427.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1427.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/441.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·Q",
   "skos:prefLabel": {
    "@value": "Malicious Extension",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "IDE extensions run with the user's privileges, update automatically from a marketplace and are rarely reviewed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Only reviewed extensions from approved sources run in the IDE, at versions the organisation chose and can withdraw.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict extension installation to an approved marketplace or an internal mirror, enforced through managed IDE policy on every developer device.",
      "@language": "en-GB"
     },
     {
      "@value": "Allow-list extensions by publisher and identifier, pin their versions, and turn off automatic updates so each new version is reviewed before rollout.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep secrets out of files the editor can open, and monitor extension host network traffic for destinations outside the expected set.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: GlassWorm on Open VSX (2025).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/698.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/698.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·J",
   "skos:prefLabel": {
    "@value": "Untrusted Workspace Execution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Opening or cloning a repository runs code: editor tasks, dev container definitions, git hooks, language servers, build files evaluated on open.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Opening or cloning a repository runs nothing until a person has decided to trust it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce restricted mode for untrusted workspaces through managed editor settings, so tasks, debug launchers and workspace-recommended extensions do not run on open.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable automatic execution of repository-supplied hooks and build file evaluation by language servers until the workspace is explicitly trusted.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin dev container base images and features by digest, and allow them only from the internal registry.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Contagious Interview repositories (2025–26).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/511.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/35.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1188.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/511.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·10",
   "skos:prefLabel": {
    "@value": "Hallucinated Dependency",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An assistant suggests a package name that does not exist, and an attacker registers it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A new dependency enters the code base only after its existence, identity and age have been checked against an approved source.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Fail the build when a manifest names a package that is absent from the approved list or that the internal proxy has never served before.",
      "@language": "en-GB"
     },
     {
      "@value": "Surface added and changed dependencies as a distinct section of the pull request, and require approval from a dependency owner for each new one.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure the dependency proxy to hold packages whose first publication is younger than a set number of days (see FW).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Package hallucination study (Spracklen et al., 2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/616.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1426.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·9",
   "skos:prefLabel": {
    "@value": "Local Bypass of Controls",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A developer can build, sign or publish from their own machine, skipping every control in the pipeline.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Releases can only come out of the pipeline, and a consumer can tell a pipeline artifact from any other.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Issue publishing and signing credentials only to pipeline identities through OIDC trusted publishing and keyless signing, so no person ever holds them.",
      "@language": "en-GB"
     },
     {
      "@value": "Generate SLSA provenance on an isolated build platform and make every consumer and deploy gate reject artifacts without valid provenance (see PV).",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on any registry publish or transparency log entry whose identity is not a registered release workflow.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/443.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/424.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·8",
   "skos:prefLabel": {
    "@value": "Toolchain Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Local compilers, SDKs, CLIs and package managers differ from the pipeline's and are installed from unverified sources, such as piping a script to a shell.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Developer and pipeline toolchains come from the same verified source at the same versions.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Define the toolchain once as code, such as a pinned dev container image or a version manager file, and build both local and pipeline environments from it.",
      "@language": "en-GB"
     },
     {
      "@value": "Install tools only through a package manager or internal mirror that verifies checksums or signatures, and remove pipe-to-shell installers from setup scripts.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin each tool installer's checksum in the toolchain definition, and alert the platform team when an upstream download no longer matches it.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·7",
   "skos:prefLabel": {
    "@value": "Pre-Commit Blind Spot",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets and unsafe changes leave the machine because local checks are optional, skippable or absent.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Anything that must not reach the repository is blocked by the server, and local checks only give earlier feedback.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable server-side secret push protection on every repository and reject pushes that contain detected secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Mirror every local pre-commit check as a required status check on protected branches, so skipping it locally changes nothing.",
      "@language": "en-GB"
     },
     {
      "@value": "Distribute local hooks through a managed hook framework installed by default, and measure how often they are skipped.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/207.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/602.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/540.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/207.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/602.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·6",
   "skos:prefLabel": {
    "@value": "Agent Context Leakage",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Assistants send source, secrets and internal context to third-party models, or retain them in logs.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An assistant receives only context the organisation has cleared for it, sends it only to approved destinations, and keeps it under known retention.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Exclude secret files, environment files and credential paths from assistant indexing with an organisation-managed ignore policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Route assistant traffic only to approved model endpoints with agreed retention terms, and block other model endpoints at the network.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan prompts and attached context for secrets before they leave the machine, and redact or block any match.",
      "@language": "en-GB"
     },
     {
      "@value": "Store assistant logs and transcripts on organisation-controlled storage with defined retention and access control.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/201.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/201.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/532.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·5",
   "skos:prefLabel": {
    "@value": "Agent-Authored Change",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Code an assistant wrote is merged with less scrutiny, carrying vulnerabilities, encumbered snippets or attacker-steered logic.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Generated code meets at least the review bar of human code, and a named person is accountable for every change that merges.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Mark agent-authored commits and pull requests with a commit trailer or a bot identity, and display the mark in the review view.",
      "@language": "en-GB"
     },
     {
      "@value": "Record the person who requested each agent change as its accountable owner, and require approval from a second code owner before merge.",
      "@language": "en-GB"
     },
     {
      "@value": "Run SAST, secret, licence and snippet-matching scans as required checks, with rules tuned to insecure patterns common in generated code.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/444.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1426.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/444.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1426.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·4",
   "skos:prefLabel": {
    "@value": "Remote Environment Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Cloud workspaces, port forwards and tunnels expose a development environment, and its credentials, to the network.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A remote development environment is reachable only by its owner through authenticated, expiring access, and holds no more credential than a laptop would.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require identity provider authentication on every forwarded port and tunnel, and forbid public or anonymous port visibility by organisation policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Expire tunnels and port forwards automatically after a short idle period and when the session ends.",
      "@language": "en-GB"
     },
     {
      "@value": "Issue cloud workspace credentials per user and per session, and prevent other users from opening, sharing or snapshotting a workspace that holds them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/121.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/306.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/613.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/668.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/306.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·3",
   "skos:prefLabel": {
    "@value": "Cloned Secrets at Rest",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Local clones, caches and shell history hold secrets and private source that leave with a lost device or a synced backup.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Source and credentials on a device stay protected at rest and can be removed when the device is lost or retired.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce full-disk encryption and remote wipe through device management, and allow private repositories to be cloned only from managed devices using conditional access.",
      "@language": "en-GB"
     },
     {
      "@value": "Store tokens in the operating system keychain rather than plain files, and configure shells to keep commands that carry secrets out of history.",
      "@language": "en-GB"
     },
     {
      "@value": "Exclude source directories, tool caches and credential files from personal cloud backup and file sync.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/507.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/675.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/507.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/313.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/313.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/530.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/#ws-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
   },
   "skos:notation": "WS·2",
   "skos:prefLabel": {
    "@value": "Configuration Sprawl",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "User-level config files redirect registries, hooks or credentials and differ from machine to machine.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Where tools fetch from and what they run is set centrally, and neither a user file nor a repository can silently redirect it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Distribute package manager, registry and git configuration through device management, and lock the registry setting to the internal proxy.",
      "@language": "en-GB"
     },
     {
      "@value": "Ignore repository-level configuration that changes registries, hooks or credential helpers unless a person approves it for that repository.",
      "@language": "en-GB"
     },
     {
      "@value": "Report each machine's effective tool configuration to a central inventory, and alert on registries or hooks outside the approved set.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/154.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/15.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/427.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/75.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/15.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "VC",
   "skos:prefLabel": {
    "@value": "Version Control",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The repository is the system of record for intent: every later control assumes that what is in it is what its owners meant. These cards cover repositories, branches, tags, review, identities and the hosting platform itself.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Repositories, branches, tags, review, forks, the hosting platform, its apps and bots",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-2"
    }
   ],
   "ost:position": 2,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·A",
   "skos:prefLabel": {
    "@value": "Protected Branch Bypass",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Admins, bots, apps or rule exceptions can push to a release branch or merge without the required review.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Review requirements on release branches apply to every actor, and any exception is narrow, owned and visible.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce branch protection through rulesets that also bind administrators, and remove bypass rights from apps and bots that lack a named owner and reason.",
      "@language": "en-GB"
     },
     {
      "@value": "Require approval from a code owner other than the most recent pusher, so an author cannot approve their own change.",
      "@language": "en-GB"
     },
     {
      "@value": "Provision exactly one platform account per person from the identity provider, and audit approvals made by bots or service accounts.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on every use of a bypass permission and on every change to the ruleset itself.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Required reviews bypass via GitHub Actions (Cider, 2021).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/863.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/863.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·K",
   "skos:prefLabel": {
    "@value": "Mutable Tags and Refs",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Tags and branches that consumers treat as releases can be moved or force-pushed to different commits.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A published release reference always resolves to the same content, and consumers depend on content identity rather than names.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Protect release tags with rulesets that block update, deletion and force-push, and use immutable releases where the platform offers them.",
      "@language": "en-GB"
     },
     {
      "@value": "Reference dependencies, actions and deploy targets by full commit SHA or content digest instead of tag or branch name.",
      "@language": "en-GB"
     },
     {
      "@value": "Raise an alert from the audit log stream on any tag move or force-push to a protected ref.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: tj-actions/changed-files (2025); trivy-action (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/445.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/669.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/445.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/471.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·Q",
   "skos:prefLabel": {
    "@value": "Platform Account Takeover",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A maintainer or organisation owner account is taken over through phishing, weak MFA, session theft or a reset flaw, giving control of every repository it owns.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Write and admin access depends on credentials that resist phishing and session theft, and high-impact actions need fresh proof of identity.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce phishing-resistant MFA, such as passkeys or FIDO2 security keys, through SSO for every member with write or admin rights.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep platform sessions short and bound to managed devices with conditional access at the identity provider.",
      "@language": "en-GB"
     },
     {
      "@value": "Require re-authentication for sensitive actions, including visibility changes, deploy key creation, repository transfer and ruleset edits.",
      "@language": "en-GB"
     },
     {
      "@value": "Harden account recovery so that email access alone cannot reset an account, and notify organisation owners of every recovery event.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Gentoo GitHub organisation (2018).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/98.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/593.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1390.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/640.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/613.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/98.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1390.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·J",
   "skos:prefLabel": {
    "@value": "Over-Privileged Apps and Tokens",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Installed apps, bots, deploy keys and personal access tokens hold broad, long-lived write access across many repositories.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every app and token holds the narrowest repository scope and permissions it needs, for a limited time, with a known owner.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Replace classic personal access tokens and broad deploy keys with fine-grained expiring tokens or app installations scoped to named repositories.",
      "@language": "en-GB"
     },
     {
      "@value": "Require organisation approval for new app installations and fine-grained tokens, and enforce a maximum token lifetime.",
      "@language": "en-GB"
     },
     {
      "@value": "Maintain an owned inventory of apps, tokens and deploy keys, review it on a fixed schedule, and revoke anything unused since the last review.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Stolen Heroku and Travis CI OAuth tokens (2022).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/21.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/266.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·10",
   "skos:prefLabel": {
    "@value": "Malicious Maintainer",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A contributor builds trust over time, gains maintainer rights, then introduces malicious change.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Release power is granted gradually, never held by one person alone, and exercised under review that does not rest on trust in an individual.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Grant maintainer rights through a documented process, with a probation period before the new maintainer can tag or publish releases.",
      "@language": "en-GB"
     },
     {
      "@value": "Require two-person review for releases and for changes to build, release and pipeline files, enforced by code owners and rulesets.",
      "@language": "en-GB"
     },
     {
      "@value": "Add a mandatory second reviewer to changes from recently promoted maintainers for a defined period.",
      "@language": "en-GB"
     },
     {
      "@value": "Review maintainer and release rights on a schedule and remove those held by inactive accounts.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: xz Utils, CVE-2024-3094 (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/443.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/443.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/506.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/506.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·9",
   "skos:prefLabel": {
    "@value": "Review Subversion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A change that looks benign in review hides behaviour: invisible or bidirectional Unicode, very large or generated diffs, binary test fixtures.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "What reviewers see is what the build uses, and content that cannot be meaningfully reviewed is regenerated or refused.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Render invisible and bidirectional Unicode visibly in the review view, and fail a required check on unexpected control characters in source.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild generated files and binary fixtures from source in the pipeline, and fail the check when the committed copy differs.",
      "@language": "en-GB"
     },
     {
      "@value": "Set a maximum diff size for a single approval, and require changes above it to be split before review.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Trojan Source, CVE-2021-42574 (2021); xz Utils test files (2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/267.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/451.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1007.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/636.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/451.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·8",
   "skos:prefLabel": {
    "@value": "Commit Identity Spoofing",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Author and committer fields are unverified, so a commit can claim to be anyone, and signature checks are optional.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Any authorship a decision relies on is cryptographically verified and bound to a person through the identity provider.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce signed commits on protected branches through rulesets.",
      "@language": "en-GB"
     },
     {
      "@value": "Bind signing keys to accounts by registering them with the platform, or use keyless commit signing with Sigstore tied to the identity provider.",
      "@language": "en-GB"
     },
     {
      "@value": "Base auto-merge and ownership decisions on the authenticated pusher or verified signer, never on the free-text author field.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/692.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/692.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·7",
   "skos:prefLabel": {
    "@value": "Repojacking",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A renamed or deleted organisation or repository name is re-registered, and anything that references the old name fetches from the new owner.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "References to external repositories resolve to a verified owner and content, not to whoever holds the name today.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Reference external repositories and actions by full commit SHA, and mirror the critical ones into the organisation.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure fetch tooling to fail on repository redirects instead of following them silently.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan build and workflow files for references to renamed or deleted owners, and keep the organisation's own retired names registered.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Repojacking research (2020 onward).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/695.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/706.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/695.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/706.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·6",
   "skos:prefLabel": {
    "@value": "Secrets in History",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A credential committed once survives deletion in history, forks, caches and mirrors.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A secret that reaches version control is treated as compromised, and pushes that carry secrets are stopped at the server.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable server-side secret push protection on every repository, with bypass limited to named reviewers and logged.",
      "@language": "en-GB"
     },
     {
      "@value": "Revoke and rotate any secret found in history at once, and treat history rewriting as clean-up rather than remediation.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict forking of private repositories, and limit read access to history and forks to people who need it.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/540.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/798.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/540.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·5",
   "skos:prefLabel": {
    "@value": "Visibility Leak",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Private code becomes reachable through a visibility change, a fork, or data from deleted and private forks that the network still serves.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Private code stays private unless a deliberate, approved change says otherwise, including every copy held in forks.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict repository visibility changes to organisation owners, and alert on every change.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable forking of private and internal repositories by organisation policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Assume any commit ever pushed into a public fork network stays fetchable by hash, and rotate secrets and review content whenever a repository was ever public.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Cross Fork Object Reference (Truffle Security, 2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/87.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/87.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/527.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/527.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/459.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·4",
   "skos:prefLabel": {
    "@value": "Hosting Platform Vulnerability",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A self-hosted VCS server is internet-facing and holds every repository and runner registration token.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A self-hosted platform presents a small attack surface, is patched quickly, and does not hand over every downstream credential when breached.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Apply security releases to the server within a defined window, and report patch compliance to the platform owner.",
      "@language": "en-GB"
     },
     {
      "@value": "Place the server behind a VPN or identity-aware proxy rather than exposing it directly to the internet.",
      "@language": "en-GB"
     },
     {
      "@value": "Use ephemeral runners with short-lived registration and federated identity, so the server stores few credentials worth stealing.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Bitbucket Server CVE-2022-36804 (2022).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/88.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/668.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/88.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1395.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·3",
   "skos:prefLabel": {
    "@value": "Audit Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Changes to protection rules, webhooks, apps and membership are not logged, retained or reviewed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every change to the controls that guard repositories is recorded outside the platform and reviewed.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Stream audit logs to a separate log store that platform administrators cannot modify or delete.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on changes to rulesets, webhooks, app installations, membership and visibility.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain audit logs for at least the organisation's detection and investigation window, and test that a year-old event can still be retrieved.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/571.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/268.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/version-control/#vc-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
   },
   "skos:notation": "VC·2",
   "skos:prefLabel": {
    "@value": "Webhook Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Webhooks deliver events to endpoints that are unauthenticated or attacker-changeable, or carry private data.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Webhook deliveries are authenticated, go only to approved endpoints, and carry no more than the receiver needs.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Limit who can add or change webhooks to repository and organisation administrators, and alert on every change.",
      "@language": "en-GB"
     },
     {
      "@value": "Sign every delivery with a per-webhook secret and verify the HMAC signature at the receiver before processing.",
      "@language": "en-GB"
     },
     {
      "@value": "Send minimal payloads over TLS, and let the receiver fetch further detail with its own scoped credential.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/194.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/154.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/923.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/940.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/201.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/194.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/923.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "PD",
   "skos:prefLabel": {
    "@value": "Pipeline Definition",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A pipeline definition is code that runs with more privilege than the people who edit it. These cards cover workflow files, triggers, expressions, reusable templates, and the third-party actions, orbs and plugins they call.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Workflow files, triggers, expressions, reusable workflows, third-party actions and plugins",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-2"
    }
   ],
   "ost:position": 3,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·A",
   "skos:prefLabel": {
    "@value": "Poisoned Pipeline Execution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Anyone who can change a workflow file, or a file it runs (scripts, makefiles, test config), in a branch or pull request gets the pipeline to execute their code with its privileges.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Code from an untrusted change runs only without secrets or write access, and protected runs execute definitions taken from protected branches.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run pull request builds from forks and unprotected branches with a read-only token and no secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Load the workflow definition and the scripts it calls from the protected branch for every protected run, never from the change under test.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign code owners to workflow files, build scripts and test configuration, so changes to them need review by the pipeline owners.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: OWASP CICD-SEC-4; Trivy pull_request_target (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/678.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/678.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·K",
   "skos:prefLabel": {
    "@value": "Privileged Trigger on Untrusted Input",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Triggers such as pull_request_target or workflow_run run with secrets and write tokens while checking out or processing a fork's code.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A run that holds secrets or write tokens never executes or interprets code supplied by an untrusted contributor.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Forbid privileged triggers such as pull_request_target and workflow_run from checking out or running the contributor's commit, enforced by a workflow linter.",
      "@language": "en-GB"
     },
     {
      "@value": "Split the work into an unprivileged job that builds the change and a privileged job that consumes only inert, validated outputs from it.",
      "@language": "en-GB"
     },
     {
      "@value": "Require maintainer approval before workflows run for first-time and outside contributors.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Trivy pull_request_target (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/234.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/234.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·Q",
   "skos:prefLabel": {
    "@value": "Expression Injection",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Untrusted text (pull request titles, branch names, issue bodies, commit messages) is interpolated into shell commands by the pipeline's expression syntax.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Event data never becomes executable code, whatever its content.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pass event fields into steps through environment variables and reference them quoted in the script, never through inline expressions.",
      "@language": "en-GB"
     },
     {
      "@value": "Make a workflow linter that flags untrusted context fields in run blocks a required check on every repository.",
      "@language": "en-GB"
     },
     {
      "@value": "Validate fields such as branch names and versions against an allowed pattern before any step uses them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Ultralytics branch-name injection (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/88.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/78.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/88.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/78.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·J",
   "skos:prefLabel": {
    "@value": "Unpinned Third-Party Step",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Workflows reference actions, orbs or plugins by a mutable tag or branch, so the publisher, or whoever compromises the publisher, decides what runs.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every third-party step runs code the organisation has reviewed, at an identity its publisher cannot change.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin actions, orbs and plugins to a full commit SHA, and enforce the requirement through organisation policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Allow only listed actions and publishers through the organisation's action settings.",
      "@language": "en-GB"
     },
     {
      "@value": "Review an action's code before first use and on every pin update, with a dependency update bot proposing each update as a reviewable pull request.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: tj-actions (2025); trivy-action (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·10",
   "skos:prefLabel": {
    "@value": "Transitive Step Dependency",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A pinned action itself pulls unpinned actions, container images or scripts at run time.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Pinning covers everything a step executes, not only the step itself.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin the container images used by actions and composite actions by digest, and reject actions that reference nested actions by tag.",
      "@language": "en-GB"
     },
     {
      "@value": "Generate an inventory of every action, image and script a workflow executes from the resolved run graph, and diff it on each change.",
      "@language": "en-GB"
     },
     {
      "@value": "Fork or vendor third-party actions that fetch unpinned content at run time, and pin the internal copy.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: reviewdog to tj-actions chain, link likely (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/446.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·9",
   "skos:prefLabel": {
    "@value": "Remote Script Execution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Pipeline steps download and run scripts from URLs without checking their integrity.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No pipeline step executes fetched code unless its integrity has been checked against a value the organisation controls.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Vendor remote scripts into the repository so the pipeline runs the reviewed copy.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify a pinned checksum or signature before executing any script that must still be fetched, and fail the step on mismatch.",
      "@language": "en-GB"
     },
     {
      "@value": "Detect download-and-execute patterns with a workflow linter run as a required check.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Codecov Bash Uploader (2021).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/185.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·8",
   "skos:prefLabel": {
    "@value": "Insufficient Flow Control",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "One identity can take a change from commit to production with no independent approval.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No single identity can take a change from commit to production, and approval is enforced where deployment happens.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require approval from someone other than the author before merge, enforced by rulesets.",
      "@language": "en-GB"
     },
     {
      "@value": "Protect the deployment environment with required reviewers, so the deploy job itself waits for an independent approval.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict manual dispatch of deploy workflows to named roles, and record who started each run and with which inputs.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: OWASP CICD-SEC-1; Amazon Q Developer extension (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/443.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/841.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/443.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/654.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·7",
   "skos:prefLabel": {
    "@value": "Environment Tampering Between Steps",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A step can change the environment, path or configuration that later steps and jobs inherit.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each step starts from an environment it can trust, and state passed between steps and jobs is explicit and validated.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Place untrusted steps in a separate job from trusted ones, so they cannot write to the shared environment, path or output files.",
      "@language": "en-GB"
     },
     {
      "@value": "Pass data between jobs only through declared outputs or artifacts, and validate it in the consuming job.",
      "@language": "en-GB"
     },
     {
      "@value": "Feed dynamic pipeline generators only from trusted sources, and validate generated definitions against a schema before running them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/13.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/38.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/454.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/427.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/13.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/454.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·6",
   "skos:prefLabel": {
    "@value": "Shared Template Blast Radius",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A reusable workflow or pipeline library used by hundreds of repositories is changed with weak review, and the change reaches every pipeline at once.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A change to a shared template is reviewed and released as a change to every consumer, and consumers adopt it deliberately.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require platform team code owner review and two approvals for every change to a shared template.",
      "@language": "en-GB"
     },
     {
      "@value": "Have consumers reference templates by full commit SHA or an immutable version, updated through reviewed pull requests.",
      "@language": "en-GB"
     },
     {
      "@value": "Roll template changes out in stages, starting with a small group of consumers and watching for failures before wider release.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/445.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/445.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·5",
   "skos:prefLabel": {
    "@value": "Parameter Injection",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Runs started by hand or by API accept inputs (versions, targets, script fragments) that change what is built or deployed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A run accepts inputs only from authorised people, only from a known set of values, and records what it received.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict who can start runs by hand or by API to named roles holding scoped tokens.",
      "@language": "en-GB"
     },
     {
      "@value": "Declare inputs with types and allowed values, and never interpolate free-text input into a script.",
      "@language": "en-GB"
     },
     {
      "@value": "Record every input in the run's provenance and audit log (see PV).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/77.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/77.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/15.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/15.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/78.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·4",
   "skos:prefLabel": {
    "@value": "Comment and Bot Triggers",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Runs start on comments, labels or bot events that an outsider or an automation can produce.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A comment, label or bot event starts a run only after the actor's permission has been verified, not just the text.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Check the actor's repository permission through the platform API before a workflow acts on a comment or label command.",
      "@language": "en-GB"
     },
     {
      "@value": "Give comment-triggered runs on outsider changes the same unprivileged context as fork pull requests.",
      "@language": "en-GB"
     },
     {
      "@value": "Treat bot-authored pull requests as untrusted unless the bot is listed and its change touches only expected files.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: hackerbot-claw campaign (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/1.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/1.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/862.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/862.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·3",
   "skos:prefLabel": {
    "@value": "Conditional Skip",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Security steps run only on certain branches, paths or commit messages, which an author can arrange to avoid.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Required security checks run on every change that can reach a protected branch, and a missing result blocks the merge.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Mark security checks as required in rulesets, so a skipped or absent check blocks merge.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove path, branch and commit-message conditions from security steps, or report an explicit failure whenever a condition skips them.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable skip markers for required workflows by organisation policy.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/#pd-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
   },
   "skos:notation": "PD·2",
   "skos:prefLabel": {
    "@value": "Definition Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Pipelines are copied between repositories and diverge, so insecure patterns persist unseen.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every pipeline is known, and security policy reaches it centrally rather than through copies.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build an inventory of every pipeline definition across the organisation from the hosting platform's API, and refresh it on a schedule.",
      "@language": "en-GB"
     },
     {
      "@value": "Enforce mandatory checks through organisation-level required workflows or rulesets that do not depend on each repository's file.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan definitions for deprecated and insecure patterns on a schedule, and open an issue for each finding with an owner.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "RN",
   "skos:prefLabel": {
    "@value": "Runners",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The runner is where untrusted code and the factory's secrets share a machine. These cards cover CI controllers, hosted and self-hosted build agents, caches, artifacts passed between jobs, and the isolation between them.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Hosted and self-hosted build agents, caches, artifacts passed between jobs, isolation",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-2"
    }
   ],
   "ost:position": 4,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·A",
   "skos:prefLabel": {
    "@value": "Persistent Runner",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A self-hosted runner reused across jobs lets one job leave a backdoor for the next, including jobs from other repositories or untrusted pull requests.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No state from one job is visible to the next, and untrusted code never runs on hosts that serve trusted jobs.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Use ephemeral just-in-time runners that accept a single job and are destroyed when it ends.",
      "@language": "en-GB"
     },
     {
      "@value": "Prevent public repositories and fork pull requests from scheduling jobs on self-hosted runners.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild runner hosts from a known image, and verify in a test job that nothing written by an earlier job is present.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: PyTorch runners (Stawinski and Khan, 2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/124.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/124.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/459.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·K",
   "skos:prefLabel": {
    "@value": "CI Controller Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The CI server is reachable from the internet and holds every pipeline's credentials, so one vulnerability in it exposes them all.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The CI controller is hard to reach, quickly patched, and holds few credentials worth stealing.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Put the controller behind an identity-aware proxy or VPN, exposing only a webhook receiver that verifies signatures.",
      "@language": "en-GB"
     },
     {
      "@value": "Patch the controller and its plugins within a defined window, and remove plugins that no pipeline uses.",
      "@language": "en-GB"
     },
     {
      "@value": "Replace credentials stored in the controller with federated short-lived identities issued per job (see ID).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: TeamCity CVE-2024-27198 (2024); Jenkins CVE-2024-23897 (2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/115.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/6.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/668.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/115.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1395.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·Q",
   "skos:prefLabel": {
    "@value": "Cache Poisoning",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A low-privilege job writes to a build or dependency cache that a privileged job later restores.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A trusted job restores only cache content written by jobs of equal or higher trust, and verifies it before use.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Scope cache keys by branch and trust level, so untrusted runs cannot write entries that protected branches read.",
      "@language": "en-GB"
     },
     {
      "@value": "Build releases with an empty cache, or restore only caches written by protected-branch runs.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify restored dependencies against lockfile hashes before the build uses them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Ultralytics cache poisoning (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/141.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/141.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/349.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/349.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·J",
   "skos:prefLabel": {
    "@value": "Memory and Process Scraping",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Any step on the runner can read the memory or environment of the runner process and of other steps, and so every secret the job holds.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A secret is present only in the step that needs it, and no step running untrusted code shares a host with it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run untrusted steps in separate jobs on separate runners from steps that hold secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Fetch each secret inside the step that uses it through a short-lived federated credential, rather than exposing it to the whole job.",
      "@language": "en-GB"
     },
     {
      "@value": "Start the runner agent as a distinct unprivileged user, and restrict process tracing so steps cannot read its memory or environment.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: tj-actions (2025); Trivy (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/545.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/545.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/214.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/526.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·10",
   "skos:prefLabel": {
    "@value": "Artifact Poisoning Between Jobs",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An artifact produced by an untrusted run is consumed by a trusted run without verification.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An artifact crosses a trust boundary only with verified origin and integrity, and is unpacked where it cannot overwrite trusted files.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record a digest and the producing run for each artifact, and verify both in the consuming trusted job.",
      "@language": "en-GB"
     },
     {
      "@value": "Handle artifacts from untrusted runs as data only, never as code, scripts or configuration for the trusted job.",
      "@language": "en-GB"
     },
     {
      "@value": "Extract artifacts into a dedicated directory outside the workspace, and reject archives containing absolute paths or traversal entries.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Artifact poisoning (Legit Security, 2022).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/184.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/349.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/345.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/184.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/349.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·9",
   "skos:prefLabel": {
    "@value": "Runner Network Reach",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Runners sit on networks with routes to production, internal services or the cloud metadata endpoint.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A runner can reach only what its job needs, and runners for untrusted code are isolated from release and production networks.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Place runners in dedicated network segments with no routes to production or internal services.",
      "@language": "en-GB"
     },
     {
      "@value": "Block the cloud metadata endpoint from jobs, or require IMDSv2 with a hop limit of one.",
      "@language": "en-GB"
     },
     {
      "@value": "Separate runners for untrusted pull requests from release runners at the network level, and test the separation from each side.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·8",
   "skos:prefLabel": {
    "@value": "Open Egress",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Runners have unrestricted internet egress, so stolen data leaves unnoticed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Runners send traffic only to known destinations, and any other attempt is blocked and visible.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Route runner egress through a proxy that allows only listed registries, mirrors and the hosting platform.",
      "@language": "en-GB"
     },
     {
      "@value": "Log DNS queries and HTTP egress per job, tagged with the repository and run.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on connection attempts to destinations outside the allow list.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "skos:example": {
    "@value": "Seen in: Trivy (2026).",
    "@language": "en-GB"
   },
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·7",
   "skos:prefLabel": {
    "@value": "Rogue Runner Registration",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A leaked registration token or loose runner group lets an attacker attach their own machine as a runner and receive jobs and secrets.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Only machines the platform provisioned can join as runners, and every new registration is visible.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Register runners through provisioning automation with short-lived, single-use tokens, and keep no long-lived registration token.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict each runner group to named repositories and workflows.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on every runner registration from the audit log, and flag any that provisioning did not request.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/616.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/923.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/923.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1390.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·6",
   "skos:prefLabel": {
    "@value": "Container Socket Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Jobs get the host's container socket or privileged mode to build images, which amounts to root on the runner.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Building images does not give a job control of the host.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build images rootless, using BuildKit in rootless mode, Buildah or Kaniko.",
      "@language": "en-GB"
     },
     {
      "@value": "Forbid mounting the container socket and running privileged containers in job configuration, enforced by runner policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Move any build that truly needs privileged features into a single-use VM or microVM.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·5",
   "skos:prefLabel": {
    "@value": "Shared Tenant Runner",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Runners are shared across teams or customers, so one job can observe or affect another's.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Jobs from different tenants are separated by a boundary as strong as the trust gap between them.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Isolate jobs from different projects or customers in separate VMs or microVMs, never in containers on a shared kernel.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep caches, workspaces and temporary storage per tenant.",
      "@language": "en-GB"
     },
     {
      "@value": "Prevent jobs from listing or inspecting other jobs through the host, the runner agent or the controller API.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/124.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/546.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/124.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/226.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·4",
   "skos:prefLabel": {
    "@value": "Secrets in Logs and Artifacts",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets reach build logs, uploaded artifacts or crash dumps where masking does not apply.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Secrets are kept out of logs and artifacts by design, with masking as a backstop rather than the control.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Register derived and encoded forms of each secret for masking, and prefer short-lived credentials so a leaked value expires quickly.",
      "@language": "en-GB"
     },
     {
      "@value": "Exclude credential files and the checkout's git configuration from uploaded artifacts and crash dumps.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan logs and artifacts for secrets after each run, and restrict log access on public projects to maintainers.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: ArtiPACKED (Unit 42, 2024); tj-actions log leak (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/150.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/532.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/532.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/528.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·3",
   "skos:prefLabel": {
    "@value": "Runner Image Supply Chain",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The runner's base image and preinstalled tools are unverified or out of date.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Runner images are built from verified sources, patched on a clock, and traceable to what they contain.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build runner images in the organisation's own pipeline from base images pinned by digest, and sign the result.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild and roll out runner images on a fixed patch schedule, and retire images older than the window.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify checksums or signatures of preinstalled tools during the image build, and publish an SBOM for each image.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/runners/#rn-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/runners/"
   },
   "skos:notation": "RN·2",
   "skos:prefLabel": {
    "@value": "Resource Hijacking",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Free or shared runners are abused for mining or as attack infrastructure, helped by public triggers.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Compute is spent only on jobs that authorised people started, within set limits.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require approval before workflows run for first-time contributors and forks.",
      "@language": "en-GB"
     },
     {
      "@value": "Set per-job time, CPU and concurrency limits on every runner pool.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on unusual runtime, CPU or spend patterns per repository.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/212.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/212.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/770.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/770.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/862.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "ID",
   "skos:prefLabel": {
    "@value": "Pipeline Identity and Secrets",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The pipeline is usually the most privileged identity in the organisation, and most attacks on it end in credential theft. These cards cover secret stores, federated identity, job tokens, service accounts and access to signing keys.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Secret stores, OIDC federation, tokens, service accounts, access to signing keys",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-2"
    }
   ],
   "ost:position": 5,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·A",
   "skos:prefLabel": {
    "@value": "Long-Lived Static Credential",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Pipelines reach clouds, registries and clusters with static keys that never expire and work from anywhere.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A pipeline proves its identity at run time and receives credentials that expire with the job and work only from it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Replace static cloud, registry and cluster keys with OIDC workload identity federation that issues short-lived tokens per job.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict any remaining static credential to the runners' network with an IP or conditional access policy, and rotate it on a schedule.",
      "@language": "en-GB"
     },
     {
      "@value": "Track every remaining static credential in an inventory with an owner and a removal date.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Codecov (2021); CircleCI (2023).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/262.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/262.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·K",
   "skos:prefLabel": {
    "@value": "Loose Federation Claims",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Cloud trust policies accept workload identity tokens whose repository, branch or environment claims are matched too broadly, so another repository, fork or branch can assume the role.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A trust policy names exactly which repository, workflow and environment may assume each role.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Match the subject claim exactly on repository and ref or environment, and never use wildcards on organisation or repository.",
      "@language": "en-GB"
     },
     {
      "@value": "Bind deploy roles to a protected environment claim whose environment requires approval.",
      "@language": "en-GB"
     },
     {
      "@value": "Test each trust policy by trying to assume the role from a fork, another repository and an unprotected branch, and expect every attempt to fail.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: OIDC trust policy research (Datadog, Rezonate, 2023).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/114.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/114.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1220.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/863.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·Q",
   "skos:prefLabel": {
    "@value": "Secrets in Untrusted Runs",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets are available to jobs that run untrusted code: forks, pull requests, third-party steps.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Secrets reach only jobs that run trusted code, and within them only the steps that need each one.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Withhold secrets from fork pull requests and from runs triggered by untrusted actors.",
      "@language": "en-GB"
     },
     {
      "@value": "Scope secrets to protected environments with required reviewers instead of the whole repository.",
      "@language": "en-GB"
     },
     {
      "@value": "Expose each secret only to the step that needs it, as an environment variable on that step, never at job or workflow level.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: tj-actions/changed-files (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·J",
   "skos:prefLabel": {
    "@value": "Over-Scoped Job Token",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The token issued to each run has write rights it does not need: pushing code, creating releases, approving pull requests.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each run's token carries only the permissions its workflow declares, starting from none.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Set the organisation's default job token permission to read-only.",
      "@language": "en-GB"
     },
     {
      "@value": "Declare permissions per workflow and per job at least privilege, and enforce declarations with a workflow linter.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable the setting that lets job tokens create or approve pull requests.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: OWASP CICD-SEC-5.",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/266.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·10",
   "skos:prefLabel": {
    "@value": "Signing Key Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Code and artifact signing keys sit in pipeline secrets or files, not in a key service with a usage policy.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Signing keys cannot be exported, sign only for authorised pipelines under policy, and every signature is recorded.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Hold signing keys as non-exportable keys in an HSM or cloud KMS, with a usage policy bound to the release pipeline identity.",
      "@language": "en-GB"
     },
     {
      "@value": "Use Sigstore keyless signing with OIDC identity and transparency logging where it fits, removing stored keys altogether (see PV).",
      "@language": "en-GB"
     },
     {
      "@value": "Log every signing operation, and alert when a signature comes from an unexpected identity.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: MSI and Intel Boot Guard keys leak (2023).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/206.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/474.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/206.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/522.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/522.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/312.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·9",
   "skos:prefLabel": {
    "@value": "Publishing Credential Reach",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The credential that publishes to a public registry is reachable by many pipelines and people, so one leak lets an attacker publish as the project.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Publishing is possible from one release workflow only, under approval, with no stored token anywhere.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Publish through OIDC trusted publishing bound to a specific repository, workflow and environment.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove stored registry tokens from pipelines and maintainer accounts once trusted publishing works.",
      "@language": "en-GB"
     },
     {
      "@value": "Require reviewer approval on the publishing environment before the publish job runs.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/522.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/668.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/522.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·8",
   "skos:prefLabel": {
    "@value": "Credentials Left in the Workspace",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Checkout and login steps write credentials to disk, where later steps, caches and artifacts pick them up.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Credentials written by setup steps exist only as long as the step that needs them.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Disable credential persistence in checkout steps, for example with persist-credentials set to false.",
      "@language": "en-GB"
     },
     {
      "@value": "Log out and delete credential files before any untrusted step or upload runs.",
      "@language": "en-GB"
     },
     {
      "@value": "Exclude credential paths from caches and artifacts, and fail the job if a scan finds them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: ArtiPACKED (Unit 42, 2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/639.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/155.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/639.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/459.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/459.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/538.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·7",
   "skos:prefLabel": {
    "@value": "Incomplete Rotation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "After a compromise, rotation is partial or slow, and the attacker keeps a working credential.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Rotation after a compromise is complete, fast and verified, and old credentials stop working.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Keep a rehearsed, scripted rotation runbook for each class of pipeline credential, and time each rehearsal.",
      "@language": "en-GB"
     },
     {
      "@value": "Check rotation completeness against the secret inventory, so every copy and consumer is accounted for.",
      "@language": "en-GB"
     },
     {
      "@value": "Revoke old credentials at the issuer rather than only replacing them in the store, and confirm they are refused.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Trivy (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/324.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/324.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·6",
   "skos:prefLabel": {
    "@value": "Secret Store Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The vault or CI secret store holds every credential, with broad admin access and weak audit.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Access to the secret store is itself short-lived, narrowly held and audited.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Limit store administrators to a small group with phishing-resistant MFA and just-in-time elevation.",
      "@language": "en-GB"
     },
     {
      "@value": "Authenticate pipelines to the store with federated short-lived identity and per-path policies.",
      "@language": "en-GB"
     },
     {
      "@value": "Stream read audit logs off the store, and alert on reads outside a pipeline's normal pattern.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·5",
   "skos:prefLabel": {
    "@value": "Cross-Environment Reuse",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The same identity serves test and production, so a test pipeline can reach production.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each environment has its own identity, and nothing outside production can obtain a production credential.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Give each environment separate identities, roles and preferably separate cloud accounts.",
      "@language": "en-GB"
     },
     {
      "@value": "Bind production trust policies to the production environment claim, and protect that environment with required reviewers.",
      "@language": "en-GB"
     },
     {
      "@value": "Test from a non-production job that every attempt to obtain a production credential fails.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·4",
   "skos:prefLabel": {
    "@value": "Secret Sprawl",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Copies of one secret live in many repositories, pipelines and vaults, so rotation misses some and nobody owns it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each secret has one source of truth and one owner, and every consumer reads from it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Store each secret once in the central store, and have pipelines reference it there instead of holding copies.",
      "@language": "en-GB"
     },
     {
      "@value": "Record every consumer of each secret, so all uses can be listed before rotation.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign each secret an owner and a rotation schedule, and report overdue rotations.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1250.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·3",
   "skos:prefLabel": {
    "@value": "Machine Identity Sprawl",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Service accounts, bots and tokens multiply without owners or expiry dates.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every non-human identity has an owner, a purpose and an end date.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require an owner and an expiry date when any service account, bot or token is created.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable identities unused for a set period automatically, and delete them after a grace period.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep a single inventory of non-human identities across the hosting platform, clouds and the secret store.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/#id-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
   },
   "skos:notation": "ID·2",
   "skos:prefLabel": {
    "@value": "Debug Access Leak",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Debug logging, re-run-with-debug and interactive sessions into a runner expose secrets to whoever can turn them on.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Turning on debugging does not widen who can see secrets.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict debug logging and interactive runner sessions to named roles.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep secret values out of debug output by masking them and by never echoing credentials in scripts.",
      "@language": "en-GB"
     },
     {
      "@value": "Audit every debug session, limit its duration, and alert on sessions opened on release or production jobs.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/121.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/532.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/215.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/121.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/532.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "BS",
   "skos:prefLabel": {
    "@value": "Build Systems",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A build should turn exactly the reviewed source into exactly one output, and every threat here breaks that link. These cards cover build tools, build scripts, plugins, compilers and toolchains, and remote caches and executors.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Make, Maven, Gradle, Bazel, compilers, toolchains, build plugins, remote cache and execution",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-2"
    }
   ],
   "ost:position": 6,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·A",
   "skos:prefLabel": {
    "@value": "Build Platform Implant",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Compromised build infrastructure injects behaviour into every artifact without any change to the source.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The artifact that ships can be shown to follow from the source alone, independently of the platform that built it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Rebuild each release on an independent rebuilder with separately administered infrastructure, and block publication when its output digest differs from the platform's.",
      "@language": "en-GB"
     },
     {
      "@value": "Build release artifacts on ephemeral hosts recreated from a verified image for each job, so an implant cannot persist between builds.",
      "@language": "en-GB"
     },
     {
      "@value": "Limit administrative access to build hosts to a small named group with just-in-time elevation, and log every session to a store the build hosts cannot write.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: SolarWinds SUNSPOT (2020).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/673.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/673.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1293.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1293.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·K",
   "skos:prefLabel": {
    "@value": "Build from Unofficial Source",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The build uses source that does not match the repository: local patches, a different ref, files outside version control.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The build obtains its own source from the canonical repository and records exactly what it obtained.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Have the build platform check out source itself from the canonical repository at a full commit hash, never from a workspace, upload or developer-supplied archive.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail the build when the working tree contains files not tracked at that commit, other than declared generated outputs.",
      "@language": "en-GB"
     },
     {
      "@value": "Record the repository URI and commit digest in platform-generated provenance, and verify both against the expected repository at release (see PV).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Webmin backdoor, CVE-2019-15107 (2019).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/445.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/444.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/445.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/348.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/349.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·Q",
   "skos:prefLabel": {
    "@value": "Release Archive Divergence",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Build scripts or release archives contain logic absent from the repository, so what ships differs from what was reviewed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every shipped archive is produced by the pipeline from a tagged commit, and everything in it traces back to reviewed content.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Generate release archives in the pipeline from the signed tag, and remove maintainers' ability to upload release assets by hand.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare each archive's contents with the tagged tree, and fail the release on any file that is neither in the tree nor a declared build output.",
      "@language": "en-GB"
     },
     {
      "@value": "Review build scripts and macros as application code, and regenerate configure scripts and similar files from source in the pipeline rather than shipping pre-generated copies.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: xz Utils release tarball (2024).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/443.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/348.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/349.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/912.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·J",
   "skos:prefLabel": {
    "@value": "Malicious Build Plugin",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Build plugins run arbitrary code at build time with the build's privileges, and are fetched from repositories that get less scrutiny than application dependencies.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Build plugins are treated as dependencies with build-time privileges and receive at least the same controls as libraries.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin build plugins by version and checksum in a verified lockfile, such as Gradle dependency verification, and resolve them through the same internal proxy and firewall as libraries.",
      "@language": "en-GB"
     },
     {
      "@value": "Require security review and a named owner before a new plugin or plugin repository is added to any build.",
      "@language": "en-GB"
     },
     {
      "@value": "Run the build step with network egress blocked, so a plugin cannot fetch further code or send data out (see BS·8).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·10",
   "skos:prefLabel": {
    "@value": "Compromised Toolchain",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A compiler, linker or SDK is trojaned, so output differs from source however clean the source is.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Toolchains are verified artifacts with a recorded identity, and their output can be cross-checked with an independently sourced toolchain.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Install compilers, linkers and SDKs from pinned, signature-verified packages or digest-pinned build images, never from a download made during the build.",
      "@language": "en-GB"
     },
     {
      "@value": "Record every toolchain component by digest in the build provenance.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild critical releases with an independently sourced or bootstrapped toolchain and compare the outputs, following the diverse double-compiling method.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: XcodeGhost (2015).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·9",
   "skos:prefLabel": {
    "@value": "Remote Cache Poisoning",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A shared remote build cache accepts outputs written by untrusted builds and serves them to release builds.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A release build consumes only cache entries written by builds trusted at the same level as itself.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Grant write access to the release cache only to isolated release builders, and give developer machines and pull request builds a separate cache.",
      "@language": "en-GB"
     },
     {
      "@value": "Key cache entries on a hash of every input that affects output, including toolchain, flags, environment variables and target platform.",
      "@language": "en-GB"
     },
     {
      "@value": "Log each cache write with the writer's identity, and periodically re-execute a sample of cached actions from clean to compare digests with the stored entries.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/141.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/141.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/349.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/349.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·8",
   "skos:prefLabel": {
    "@value": "Non-Hermetic Build",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The build fetches from the network while it runs, so its output depends on what the network returned at that moment.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every input to a build is declared and fetched by digest before the build runs, and the build itself can reach nothing else.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Split fetching from building, so that a prior step resolves every declared input by digest into a local store.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable network access for the build step at the sandbox or runner level, and fail the build on any attempted connection.",
      "@language": "en-GB"
     },
     {
      "@value": "Build the same commit twice on different hosts on a schedule, and alert when the outputs differ.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/185.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·7",
   "skos:prefLabel": {
    "@value": "Non-Reproducible Output",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Timestamps, paths and ordering make each build different, so tampering cannot be found by rebuilding.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Release builds are deterministic, so an independent party can rebuild them and obtain identical bytes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Remove sources of non-determinism by setting SOURCE_DATE_EPOCH, normalising file order and permissions, and stripping build paths with path-prefix mapping.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild each release on an independent rebuilder and publish the comparison alongside the artifact.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep a list of artifacts that are not yet reproducible, each with an owner, and explain every mismatch with a diffing tool such as diffoscope.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·6",
   "skos:prefLabel": {
    "@value": "Generated Code Trust",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Code generators, schema compilers and macros emit code nobody reviews, from inputs that can be steered.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Generated code comes from pinned generators and reviewed inputs, and changes to it are visible to reviewers.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin code generators, schema compilers and macro packages by version and digest, and resolve them through the same controls as other dependencies.",
      "@language": "en-GB"
     },
     {
      "@value": "Commit generated output, or attach a diff of it to each pull request, so reviewers see what changes when an input or generator changes.",
      "@language": "en-GB"
     },
     {
      "@value": "Flag for review any dependency update that changes a schema, template or IDL file feeding code generation.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/678.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/94.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/94.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·5",
   "skos:prefLabel": {
    "@value": "Remote Execution Trust",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Remote build workers run actions for many clients and return outputs the client accepts unverified.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Outputs from remote executors are bound to the client's inputs and can be checked, and no tenant can affect another's results.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run release actions on dedicated remote executors isolated from other tenants and developer workloads, with separate content-addressed storage.",
      "@language": "en-GB"
     },
     {
      "@value": "Authenticate executors with mutual TLS, and record in the build log which worker produced each output.",
      "@language": "en-GB"
     },
     {
      "@value": "Re-execute a random sample of actions locally or on a second pool, and fail the build when an output digest differs.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/124.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/345.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/124.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/345.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·4",
   "skos:prefLabel": {
    "@value": "Hardening Flags Disabled",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Build flags in a release turn off security features, or include debug and test-only code paths.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Release build configuration is defined once, has a named security owner, and is checked against the artifact actually produced.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Define release compiler and linker flags in a central, code-owned configuration that projects import rather than copy.",
      "@language": "en-GB"
     },
     {
      "@value": "Inspect each release binary for the expected hardening (stack protector, PIE, full RELRO, fortify, control-flow protection) and fail the release when any is missing.",
      "@language": "en-GB"
     },
     {
      "@value": "Exclude debug and test-only code through build configuration, and assert in the pipeline that test endpoints and debug symbols are absent from release output.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/678.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/121.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/678.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/489.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/489.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1269.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·3",
   "skos:prefLabel": {
    "@value": "Secrets Baked into Output",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The build embeds environment variables, configuration or source maps holding secrets into shipped artifacts.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Build output can contain only values that were declared safe to publish.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pass the build an explicit allow list of environment variables rather than the runner's whole environment, and inject runtime configuration at deploy time instead.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan every artifact, image layer and source map for secrets before publishing, and block publication on a finding.",
      "@language": "en-GB"
     },
     {
      "@value": "Publish source maps and debug files only to an access-controlled symbol store, never alongside public artifacts.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/191.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/212.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/538.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/build-systems/#bs-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
   },
   "skos:notation": "BS·2",
   "skos:prefLabel": {
    "@value": "Unrecorded Build Inputs",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Tool versions, environment and parameters are not recorded, so a shipped artifact cannot be investigated later.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each shipped artifact has a complete, durable build record that the build itself could not alter.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record toolchain versions, build image digest, parameters, environment and resolved dependencies in platform-generated provenance for every build.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep build records and logs in append-only storage outside the build's reach, retained at least as long as the artifact is supported.",
      "@language": "en-GB"
     },
     {
      "@value": "Test the records periodically by rebuilding an old release from its record alone and comparing digests.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "DR",
   "skos:prefLabel": {
    "@value": "Dependency Resolution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Resolution is the moment the factory decides whose code to run, usually automatically and often by name alone. These cards cover package managers, manifests, lockfiles, install-time execution and dependency update bots.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Package managers, manifests, lockfiles, install scripts, dependency update bots",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-2"
    }
   ],
   "ost:position": 7,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·A",
   "skos:prefLabel": {
    "@value": "Install-Time Code Execution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Package managers run lifecycle scripts on install, so resolving a malicious version executes it on developer machines and runners.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Resolving and installing a package does not, by itself, run that package's code.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Disable install scripts by default, using settings such as npm ignore-scripts or the pnpm onlyBuiltDependencies allow list, and permit them only for named packages after review.",
      "@language": "en-GB"
     },
     {
      "@value": "Run dependency installation in a job that holds no secrets, tokens or cloud credentials.",
      "@language": "en-GB"
     },
     {
      "@value": "Fetch packages in one step and run the install step with network egress blocked, so a script cannot download a second stage or send data out.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: ua-parser-js (2021); Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1188.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·K",
   "skos:prefLabel": {
    "@value": "Dependency Confusion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The resolver prefers a public package over a private one of the same name, or searches several indexes and takes the highest version.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each package name maps to exactly one authoritative source, and publishing a package elsewhere cannot change that mapping.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Publish internal packages under a reserved scope or namespace, and register that scope or placeholder names on the public registries.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure each scope to resolve from exactly one index, and remove extra-index-url and similar fallback settings.",
      "@language": "en-GB"
     },
     {
      "@value": "Route resolution through an internal proxy that refuses to serve a public package whose name matches an internal one.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Birsan research (2021); PyTorch torchtriton (2022).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/159.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/427.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/159.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/427.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·Q",
   "skos:prefLabel": {
    "@value": "Floating Version Ranges",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Manifests accept ranges, so a new malicious release is picked up with no change anyone reviewed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The exact set of dependencies a build uses changes only through a reviewed change to the repository.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Commit a lockfile with integrity hashes and install in frozen mode in CI, for example npm ci, pnpm install --frozen-lockfile or pip install --require-hashes.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail any CI job that modifies the lockfile or installs a version not recorded in it.",
      "@language": "en-GB"
     },
     {
      "@value": "Propose dependency updates as pull requests that change the lockfile, so each new version passes review and the usual checks (see DR·7).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: colors and faker (2022).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/186.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·J",
   "skos:prefLabel": {
    "@value": "Typosquatting and Lookalikes",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Packages named to be mistaken for popular ones (typos, separators, scopes, combined words) are installed by mistake.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Adding a dependency is a deliberate, reviewed event, and names close to well-known packages are challenged.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Detect each new direct dependency in a pull request, and require approval from a code owner of the dependency manifests.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare new package names with a list of popular packages using edit distance and separator and scope normalisation, and flag close matches for review.",
      "@language": "en-GB"
     },
     {
      "@value": "Block known lookalike names and very recently published packages at the dependency firewall unless they are explicitly approved (see FW).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: crossenv (2017).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/630.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/630.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1007.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·10",
   "skos:prefLabel": {
    "@value": "Ownership Transfer",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A package passes to a new owner through handover, an expired maintainer domain or a re-registered deleted name, and the new owner ships malicious releases.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A change in who controls a dependency is noticed and treated as a new trust decision.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Monitor dependencies for changes of maintainer, publishing account, source repository or maintainer email domain, and raise each change for review.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin dependencies by version and hash, so a release from a new owner or a re-registered name is not installed until someone approves it.",
      "@language": "en-GB"
     },
     {
      "@value": "Track dependencies that are unmaintained or rely on expired maintainer domains, and assign owners to replace or fork them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: event-stream (2018); PyPI Revival Hijack (JFrog, 2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/695.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/695.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1104.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·9",
   "skos:prefLabel": {
    "@value": "Lockfile Tampering",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Lockfiles are long and unreviewed, so a change can point a package at a different source or hash.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A lockfile change is checked by machine against allowed sources and hashes, so its length cannot hide a redirection.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Lint every lockfile in CI with a tool such as lockfile-lint, and reject entries that resolve outside the approved registry hosts or use insecure schemes.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify that each entry carries an integrity hash and that the hash matches the artifact served by the internal mirror.",
      "@language": "en-GB"
     },
     {
      "@value": "Summarise lockfile diffs in the pull request as added, removed and re-sourced packages, so reviewers see the substance rather than the raw file.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Lockfile injection (Liran Tal, 2019).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/154.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/346.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/154.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/346.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·8",
   "skos:prefLabel": {
    "@value": "Maintainer Sabotage",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A legitimate maintainer deliberately ships destructive or political behaviour in a release.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No release from a trusted maintainer reaches production before it has been observed, and any release can be withdrawn quickly.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Apply a cooldown so that newly published versions are not proposed or installed until they have been public for a set number of days.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare each update's install-time behaviour, network access and file access with the previous version, and hold updates whose behaviour changes for review.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep known-good versions in the internal mirror, and be able to pin one across every repository with a single policy change.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: node-ipc, CVE-2022-23812 (2022).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/443.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/443.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/506.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/506.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·7",
   "skos:prefLabel": {
    "@value": "Automated Update Merge",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Dependency bots open and auto-merge updates, so a malicious release reaches production on the bot's authority.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An update bot can propose a new version but cannot, by itself, decide that it ships.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict auto-merge to updates that meet an explicit policy, such as patch releases of allowed packages after a cooldown, and require human review for the rest.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure the bot to wait a set number of days after a release before proposing it.",
      "@language": "en-GB"
     },
     {
      "@value": "Run bot pull requests with the same untrusted triggers and secret-free permissions as external contributions (see PD).",
      "@language": "en-GB"
     },
     {
      "@value": "Apply branch protection to the bot's identity, so it cannot bypass required checks or review.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/186.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/266.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·6",
   "skos:prefLabel": {
    "@value": "Manifest Confusion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The metadata a registry shows differs from what the package manager installs.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Decisions about a package rest on the contents of the artifact that is installed, not on metadata served separately.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Read scripts, dependencies and licence from the manifest inside the downloaded archive, not from the registry API.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare registry metadata with the archive's manifest at the proxy or firewall, and quarantine packages where they differ.",
      "@language": "en-GB"
     },
     {
      "@value": "Generate the SBOM from the installed tree after installation (see BM).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: npm manifest confusion (Darcy Clarke, 2023).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/691.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/691.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/348.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·5",
   "skos:prefLabel": {
    "@value": "Transitive Blind Spot",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Most of the tree arrives transitively and is never chosen or reviewed by anyone.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The full resolved tree is known for every build, and changes to it are as visible as changes to direct dependencies.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Generate the complete dependency tree from the lockfile for every build, and store it with the build record.",
      "@language": "en-GB"
     },
     {
      "@value": "Show added and removed transitive packages in each pull request, and require review when a change introduces new ones.",
      "@language": "en-GB"
     },
     {
      "@value": "Set a limit on the number of new transitive packages a single change may add, and require written justification above it.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/446.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·4",
   "skos:prefLabel": {
    "@value": "Resolver Differential",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The package manager, the SCA scanner and the SBOM generator resolve the same manifest to different trees.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every tool that reasons about dependencies works from the same resolved tree that the build installs.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Make the lockfile the single input for the installer, the scanner and the SBOM generator, and fail when a tool resolves the manifest itself.",
      "@language": "en-GB"
     },
     {
      "@value": "Produce scanner and SBOM input from the installed tree in the build environment, including platform-specific and optional dependencies.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare the package sets reported by the installer, the scanner and the SBOM for each build, and alert on any difference.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/436.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/436.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·3",
   "skos:prefLabel": {
    "@value": "Vendored Copy Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Third-party code copied or vendored into the repository is invisible to SCA and never updated.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Vendored and copied third-party code is inventoried, attributed and updated like any other dependency.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record every vendored directory with its upstream source, version and licence in a machine-readable manifest that the SBOM generator reads.",
      "@language": "en-GB"
     },
     {
      "@value": "Detect copied third-party code with snippet or file-hash matching during scanning, and require that it be declared.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign each vendored component an owner, and include it in the normal update and vulnerability processes.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1104.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1104.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/#dr-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
   },
   "skos:notation": "DR·2",
   "skos:prefLabel": {
    "@value": "Unpublished Dependency",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A dependency or version disappears from the registry and builds fail or fall back to another source.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Builds depend on an internal copy of every dependency, and a missing version fails the build rather than changing its source.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Mirror every resolved dependency into an internal repository, and resolve only from that repository.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail resolution when a pinned version or hash is unavailable, with no fallback to another index or to a different version.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain mirrored versions after upstream deletion, and alert owners when an upstream package they use is removed.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: left-pad (2016).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/603.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/603.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "SG",
   "skos:prefLabel": {
    "@value": "Scanners and Gates",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A scanner is privileged code that reads everything and decides what ships, so it is both a control and a target. These cards cover SAST, SCA, secrets, IaC, container, licence and DAST scanners, AI reviewers, and the gates that act on their results.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "SAST, SCA, secrets, IaC, container, licence and DAST scanners; quality gates; policy checks",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-2"
    }
   ],
   "ost:position": 8,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·A",
   "skos:prefLabel": {
    "@value": "Weaponised Scanner",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The scanner, or the action that installs it, is compromised and runs with the pipeline's secrets in every repository that uses it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A scanner runs as untrusted code with only the access it needs to read the code and report a result.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin scanner actions and images by full commit hash or digest, and verify their signature or provenance before the job runs.",
      "@language": "en-GB"
     },
     {
      "@value": "Run scanners in a separate job with a read-only token and no publish, deploy or cloud secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Block network egress from the scanner job, except to an internal advisory mirror where the scanner needs one.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Trivy and KICS GitHub Actions (2026).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·K",
   "skos:prefLabel": {
    "@value": "Fail-Open Gate",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A scanner error, timeout, lapsed licence or unsupported language passes the gate instead of failing it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A gate passes only on a positive result, and \"not scanned\" is a distinct outcome with its own policy.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Return a distinct result for scanner error, timeout, licence failure and unsupported file, and map each to a failed gate by default.",
      "@language": "en-GB"
     },
     {
      "@value": "Record the fail-open or fail-closed choice in the gate's policy-as-code with a named owner, and log every fail-open decision.",
      "@language": "en-GB"
     },
     {
      "@value": "Test the gate by making the scanner crash, time out and lose its licence, and assert that each case blocks the merge.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/655.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·Q",
   "skos:prefLabel": {
    "@value": "Gate Override",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Developers or admins can make a required check optional, override a failure, or merge before checks finish.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Required checks are enforced by the platform, and an override is a recorded, authorised exception rather than a routine path.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce gates as required status checks through branch rules that also bind administrators, so nothing merges while checks are pending or failed.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict overrides to a break-glass role that the change's author cannot use, and require a recorded reason for each one.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert security owners on every override and on any change to branch rules or required checks.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/841.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/841.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·J",
   "skos:prefLabel": {
    "@value": "Suppression Abuse",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The author of a change can add the inline suppression, ignore entry or baseline update that silences its findings.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The author of a change cannot, alone, silence the findings on that change.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Place ignore files, baselines and suppression configuration under code ownership that requires approval from a security owner.",
      "@language": "en-GB"
     },
     {
      "@value": "Detect new inline suppressions in a diff, and require review from someone other than the author.",
      "@language": "en-GB"
     },
     {
      "@value": "Give every suppression a reason and an expiry date, and reopen the finding when it expires.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/578.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/578.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·10",
   "skos:prefLabel": {
    "@value": "Policy Tampering",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The policy-as-code that defines a gate lives where the teams it governs can change it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Gate policy is governed by its owners separately from the teams it constrains, and each result shows which policy produced it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Keep gate policies and thresholds in a separate repository owned by security, with required review from its owners.",
      "@language": "en-GB"
     },
     {
      "@value": "Load policy into the gate from that repository by version or digest, so a governed repository cannot override it locally.",
      "@language": "en-GB"
     },
     {
      "@value": "Record the policy version with each gate result and in the artifact's attestations.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/75.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/15.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/15.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·9",
   "skos:prefLabel": {
    "@value": "Scanned Is Not Shipped",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The scanner analyses a different tree, branch, image or build from the one that ships.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A scan result applies to one artifact digest, and only that digest can be released on the strength of it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Scan the built artifact by digest after the final build step, rather than scanning a branch or tag.",
      "@language": "en-GB"
     },
     {
      "@value": "Emit each result as a signed attestation whose subject is the artifact digest (see PV).",
      "@language": "en-GB"
     },
     {
      "@value": "Push artifacts to immutable repositories, and verify at release and admission that the digest has a passing scan attestation.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/367.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/29.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/367.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·8",
   "skos:prefLabel": {
    "@value": "Scanner Evasion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Code is written to defeat analysis: obfuscation, dynamic loading, encoded payloads, constructs the scanner does not model.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Detection of deliberately hidden code is a separate control from vulnerability scanning, and assumes an adversary who knows the scanner.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Flag dynamic code loading, evaluation of computed strings, encoded or compressed blobs and binary files in source for human review.",
      "@language": "en-GB"
     },
     {
      "@value": "Run behavioural malicious-code detection, such as sandboxed install and test steps with network and file monitoring, separately from SAST.",
      "@language": "en-GB"
     },
     {
      "@value": "Document which constructs each scanner does not model, and route changes that use them to manual review.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/655.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/506.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/912.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/636.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/506.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·7",
   "skos:prefLabel": {
    "@value": "Reviewer Prompt Injection",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An LLM reviewer or triage agent reads code, comments or pull request text that tells it to approve or suppress.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An LLM reviewer's output is advisory input to a gate whose decision rests on controls the reviewed content cannot influence.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require a deterministic check or a human for every approval, merge or suppression, so an LLM verdict alone never decides one.",
      "@language": "en-GB"
     },
     {
      "@value": "Pass code, comments and pull request text to the model as delimited data, and report any instructions found in them as a finding.",
      "@language": "en-GB"
     },
     {
      "@value": "Give the reviewer agent read-only permissions limited to returning a verdict, with no tools that can approve, label, merge or change configuration.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/248.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/248.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1427.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1427.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·6",
   "skos:prefLabel": {
    "@value": "Hostile Input to the Scanner",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The code under scan exploits the scanner: parser bugs, config files the scanner executes, crafted paths in reports.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The scanner treats the code it analyses as hostile input and is contained so that compromising it gains nothing.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run scanners in a sandbox with a read-only checkout, no secrets and no network egress.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable scanner features that execute repository content, such as build files, plugins or configuration hooks, or allow them only inside that sandbox.",
      "@language": "en-GB"
     },
     {
      "@value": "Validate scanner reports before other tools consume them, rejecting paths outside the repository and escaping content rendered in comments.",
      "@language": "en-GB"
     },
     {
      "@value": "Track scanner versions across all pipelines, and roll out security fixes within a set time.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/35.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/153.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/22.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/116.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/35.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·5",
   "skos:prefLabel": {
    "@value": "Stale Advisory Data",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Advisory databases lag or cached results are reused, so new vulnerabilities are missed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Vulnerability decisions use current advisory data, and released artifacts are re-evaluated whenever that data changes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record the advisory database version and age with each scan result, and fail the gate when the data is older than a set limit.",
      "@language": "en-GB"
     },
     {
      "@value": "Re-scan the SBOMs of released and deployed artifacts when new advisories arrive, and alert owners on new matches.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on a failed advisory feed update rather than continuing silently with cached data.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/184.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/184.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·4",
   "skos:prefLabel": {
    "@value": "Coverage Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Some repositories, languages, IaC, images or generated code are never enrolled in scanning.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Scanning coverage is measured against an authoritative inventory, and new assets are enrolled by default.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build the inventory of repositories, images and IaC from the hosting platform and registries, and report each scanner's coverage against it.",
      "@language": "en-GB"
     },
     {
      "@value": "Enrol new repositories automatically through organisation-level required workflows or rules.",
      "@language": "en-GB"
     },
     {
      "@value": "Publish the list of unsupported languages and artifact types, with an owner and a compensating control for each.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·3",
   "skos:prefLabel": {
    "@value": "Findings Leakage",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Scan results, a map of every weakness, go to third-party services, public pull request comments or logs.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Findings are handled as sensitive data, with access and retention no wider than for the source they describe.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Store findings in a system that inherits the repository's access controls, and restrict security findings to the owning team and security.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep security findings out of comments and logs on public repositories and forks, and link instead to an access-controlled view.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure external scanning services with no source retention, and confirm the setting against their data processing terms before enrolment.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/150.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/150.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/201.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/201.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/532.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/#sg-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
   },
   "skos:notation": "SG·2",
   "skos:prefLabel": {
    "@value": "Alert Fatigue",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Finding volume buries the real issues, and teams stop reading results.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The volume of findings is managed so that what reaches a person is likely to matter and gets acted on.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Prioritise findings by reachability, exploitation data such as EPSS and KEV, and exposure, and gate only on the highest tier.",
      "@language": "en-GB"
     },
     {
      "@value": "Measure triage and fix rates per rule, and retire or tune rules whose findings are mostly dismissed.",
      "@language": "en-GB"
     },
     {
      "@value": "Deduplicate findings across scanners and branches before they reach anyone's queue.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/655.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/655.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/779.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "PV",
   "skos:prefLabel": {
    "@value": "Provenance and Attestation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Provenance is only worth what its verifier enforces and only as honest as the platform that wrote it. These cards cover SLSA provenance, in-toto attestations, artifact signing, Sigstore and transparency logs, and the verification that is meant to act on them.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "SLSA provenance, in-toto attestations, signing, Sigstore, transparency logs, verification",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-2"
    }
   ],
   "ost:position": 9,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-1"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·A",
   "skos:prefLabel": {
    "@value": "Forgeable Provenance",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Build steps can write or alter the provenance, so a compromised build attests to whatever it likes.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Provenance is written and signed by the build platform in a place no tenant build step can reach.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Generate provenance in a platform-controlled step isolated from user-defined build steps, as SLSA Build L3 requires.",
      "@language": "en-GB"
     },
     {
      "@value": "Sign provenance with keys or a workload identity the build steps cannot access, such as Sigstore keyless signing bound to the platform's identity.",
      "@language": "en-GB"
     },
     {
      "@value": "Test the isolation with a build step that tries to read the signing material or write the provenance, and assert that both attempts fail.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/673.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/690.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/522.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·K",
   "skos:prefLabel": {
    "@value": "Verification Not Enforced",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Provenance and signatures are produced, but nothing rejects an artifact that lacks them or fails verification.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An artifact without valid, verified attestations does not run, by default.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce signature and provenance verification in enforcing mode at cluster admission and at the deploy step, and at package install where the ecosystem supports it.",
      "@language": "en-GB"
     },
     {
      "@value": "Treat a missing signature or attestation as a verification failure.",
      "@language": "en-GB"
     },
     {
      "@value": "Attempt to deploy an unsigned image and one with a broken signature on a schedule, and assert that both are rejected.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/68.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/68.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/347.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·Q",
   "skos:prefLabel": {
    "@value": "Wrong Identity Accepted",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The verifier checks that an artifact is signed, not who signed it or which builder, repository and workflow produced it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Verification asserts who produced an artifact and from what, not merely that someone signed it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin the expected OIDC issuer and certificate identity in each policy, such as the workflow path, repository and ref, rather than accepting any signature from the issuer.",
      "@language": "en-GB"
     },
     {
      "@value": "Check the provenance's builder ID, source repository, ref and workflow against expected values.",
      "@language": "en-GB"
     },
     {
      "@value": "Define these expectations per artifact or artifact family in policy-as-code owned by the artifact's owners.",
      "@language": "en-GB"
     },
     {
      "@value": "Test each policy with an artifact signed by another repository under the same issuer, and assert that it fails.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/473.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/473.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/347.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/346.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·J",
   "skos:prefLabel": {
    "@value": "Signing Key Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A long-lived signing key is stolen and used to sign malicious artifacts that verify as genuine.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No single long-lived secret is enough to produce a signature that consumers trust.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Replace long-lived keys with Sigstore keyless signing, using short-lived certificates bound to the workload identity.",
      "@language": "en-GB"
     },
     {
      "@value": "Hold any remaining keys in a hardware-backed key service that logs every use, and alert on use outside the release pipeline.",
      "@language": "en-GB"
     },
     {
      "@value": "Rehearse revocation, including rotating the key through TUF or the verifier's trust policy and rejecting signatures made after the compromise.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: NVIDIA code-signing certificates (2022).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/474.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/206.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/474.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/654.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/522.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·10",
   "skos:prefLabel": {
    "@value": "Build Level Read as Source Trust",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Provenance faithfully records a build of a commit that was never reviewed, and a high build level is read as a statement about the source.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Policy evaluates source integrity and build integrity as separate claims and requires both.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require evidence that the commit was reviewed and merged to a protected branch, such as a SLSA Source track attestation, alongside build provenance.",
      "@language": "en-GB"
     },
     {
      "@value": "Check at verification time that the provenance's source revision is reachable from a protected branch.",
      "@language": "en-GB"
     },
     {
      "@value": "State in policy and consumer documentation what the build level claims and what it does not.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/673.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/673.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/654.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·9",
   "skos:prefLabel": {
    "@value": "Attestation Substitution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A valid attestation for one artifact is accepted for another because the subject digest is not compared, or lookup is by tag.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An attestation is accepted only for the exact artifact whose digest it names.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Compare the attestation's subject digest with the digest of the artifact being verified, and fail on any mismatch.",
      "@language": "en-GB"
     },
     {
      "@value": "Resolve tags to digests before verification, and look up attestations by digest only.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict who can push attestations to a registry repository, and verify each attestation's signer as well as its subject.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/477.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/477.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/354.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/354.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·8",
   "skos:prefLabel": {
    "@value": "Unwatched Transparency Log",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Signatures go to a transparency log nobody monitors, so a signature made with your identity by someone else goes unnoticed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every signature made under the organisation's identities is seen by the organisation, and verification depends on the log.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Monitor Rekor for entries made with the organisation's identities, and alert on any that does not match a known pipeline run.",
      "@language": "en-GB"
     },
     {
      "@value": "Require proof of inclusion, such as a signed entry timestamp or inclusion proof, during verification.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail closed when the log is unavailable, relying on proofs bundled with the artifact rather than skipping the check.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/347.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·7",
   "skos:prefLabel": {
    "@value": "Incomplete Provenance",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Provenance omits inputs such as resolved dependencies, parameters or the build image, so it attests to less than consumers assume.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Provenance records every input that could change the output, and states plainly where it is incomplete.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Include resolved dependencies with digests, external parameters and the build image digest in every provenance document.",
      "@language": "en-GB"
     },
     {
      "@value": "Mark completeness explicitly in provenance, and fail verification for critical artifacts when required fields are missing.",
      "@language": "en-GB"
     },
     {
      "@value": "Validate a sample of provenance documents by rebuilding from the recorded inputs and comparing digests.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·6",
   "skos:prefLabel": {
    "@value": "Downgrade to Unsigned",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Policy accepts older unsigned versions, or falls back to tag matching when attestations are missing.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Once signing is required, policy never weakens because an attestation is absent.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Set a cut-over date or version after which unsigned artifacts are rejected, and enforce it in admission policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove any fallback to tag matching, and fail verification when attestations are missing.",
      "@language": "en-GB"
     },
     {
      "@value": "Give each exemption an exact digest, a named owner and an expiry date, and alert before it lapses.",
      "@language": "en-GB"
     },
     {
      "@value": "Prevent rollback to older versions with a minimum-version policy or TUF metadata.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/620.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/620.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·5",
   "skos:prefLabel": {
    "@value": "Trust Root Distribution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Verifiers fetch their trust roots (keys, certificate bundles, TUF roots) insecurely, or never rotate them.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Verifiers obtain and update their trust roots through an authenticated channel that survives key compromise and rotation.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Distribute trust roots through TUF, as the Sigstore public instance does, or pin them in the verifier image.",
      "@language": "en-GB"
     },
     {
      "@value": "Monitor trust root expiry, and rotate roots before it, testing each rotation on a non-production verifier first.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail closed and alert the owners when a root has expired or cannot be updated.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/479.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/94.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/324.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/924.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/479.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/324.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·4",
   "skos:prefLabel": {
    "@value": "Unverified Delivery Path",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A manual deploy, break-glass procedure, side-loaded image or second cluster skips verification.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Verification sits at a point every path to production must cross, so a new path cannot skip it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce verification at cluster admission and in the runtime environment, not only in the CD pipeline.",
      "@language": "en-GB"
     },
     {
      "@value": "Inventory production clusters and deploy paths from infrastructure configuration, and alert on any that lacks enforcing admission policy.",
      "@language": "en-GB"
     },
     {
      "@value": "Route break-glass deploys through the same verification with a recorded, time-limited exception, and review every use.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/424.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/420.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·3",
   "skos:prefLabel": {
    "@value": "Attestation Store Tampering",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Attestations kept in a registry or database can be deleted or replaced.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Attestations, once written, cannot be removed or altered without detection.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Store attestations in a write-once store and record them in a transparency log.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict delete and overwrite rights on registries that hold attestations to a break-glass role.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on any deletion or replacement of an attestation.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/690.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/#pv-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
   },
   "skos:notation": "PV·2",
   "skos:prefLabel": {
    "@value": "Claim Inflation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A supplier claims a SLSA level or \"signed builds\" it does not meet, and consumers rely on the label.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A supplier's security claim is accepted only on evidence the consumer can verify.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require suppliers to deliver signed provenance with each artifact, and verify its build level against the claim.",
      "@language": "en-GB"
     },
     {
      "@value": "Write procurement requirements as verifiable evidence, such as provenance, signatures and identity policy, rather than labels.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign an owner to check each new supplier release against those requirements, and record the result.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "RG",
   "skos:prefLabel": {
    "@value": "Registries",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A registry turns a name into bytes, and every consumer trusts that the name still means what it meant yesterday. These cards cover public package and image registries, internal artifact repositories, and the proxies and mirrors between them.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Public package and image registries, internal artifact repositories, proxies and mirrors",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-2"
    }
   ],
   "ost:position": 10,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·A",
   "skos:prefLabel": {
    "@value": "Publisher Account Takeover",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A maintainer's registry account is taken over through phishing, reused passwords or an expired email domain, and malicious versions are published as the project.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Publishing a release requires proof that it came from the project's own build, not only from a valid login to the maintainer's account.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require phishing-resistant MFA, such as FIDO2 security keys or passkeys, for every account with publish rights on packages above a set download threshold.",
      "@language": "en-GB"
     },
     {
      "@value": "Use trusted publishing so releases come from an OIDC-authenticated CI workflow, and disable long-lived publish tokens for projects that adopt it.",
      "@language": "en-GB"
     },
     {
      "@value": "Hold a release from a new device, location or token for a delay and notify every maintainer, so a second owner can cancel it.",
      "@language": "en-GB"
     },
     {
      "@value": "Let a project mark provenance as mandatory, and have the registry reject any version without a provenance attestation that names the project's repository and workflow.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: ua-parser-js (2021); npm chalk and debug phishing (2025).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/308.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/640.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/308.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·K",
   "skos:prefLabel": {
    "@value": "Mutable Version or Tag",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A published version or image tag can be overwritten, so one name returns different content over time.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A published name and version resolve to the same bytes for as long as they exist.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Make versions and tags immutable once published, so a fix always requires a new version number rather than a replacement.",
      "@language": "en-GB"
     },
     {
      "@value": "Pull dependencies and images by content digest, and record the digest in the lockfile or manifest that the build reads.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert the owning team and every recorded consumer when the registry sees a delete and re-publish, or an attempted overwrite, of an existing version.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/148.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/148.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/471.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·Q",
   "skos:prefLabel": {
    "@value": "Internal Release Overwrite",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Pipelines or users can overwrite or re-upload artifacts in internal repositories, including releases already deployed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Release repositories are append-only, and promotion moves the artifact that was tested rather than producing a new one.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict write access on release repositories to one promotion identity, and give pipelines and people write access only to snapshot or staging repositories.",
      "@language": "en-GB"
     },
     {
      "@value": "Enable immutability on release repositories so an existing version or digest cannot be overwritten, re-uploaded or deleted outside the retention process.",
      "@language": "en-GB"
     },
     {
      "@value": "Promote by copying the same digest between repositories, and fail promotion when the digest in the target differs from the one that passed testing.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/558.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/669.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·J",
   "skos:prefLabel": {
    "@value": "Virtual Repository Shadowing",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A virtual repository merges internal and public members, so a public package shadows an internal one.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each internal name resolves to exactly one source, and no public member can ever answer for it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Configure virtual repositories to search internal members first, and document and test the resolution order for every one of them.",
      "@language": "en-GB"
     },
     {
      "@value": "Exclude internal namespaces and scopes from every remote member with explicit include and exclude patterns, so remote members never serve those names.",
      "@language": "en-GB"
     },
     {
      "@value": "Reserve internal names and scopes on the public registry where the ecosystem allows it, and alert when a remote member is asked for a name that exists internally.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/159.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/427.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/159.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/427.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·10",
   "skos:prefLabel": {
    "@value": "Registry Infrastructure Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The registry's own servers, storage, CDN or index are compromised, changing what every consumer receives.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Clients verify that content is what its publisher released, using signed metadata that the registry's own infrastructure cannot forge.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Verify packages against signed repository metadata, using a framework such as TUF, and reject content whose hash does not match a signed target.",
      "@language": "en-GB"
     },
     {
      "@value": "Check signed metadata for expiry and version rollback, so a compromised index or CDN cannot serve stale or reordered entries without detection.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare hashes from the primary registry against an independent mirror or transparency log on a schedule, and alert on any mismatch.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Docker Hub breach (2019); PEAR server (2019).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/439.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/669.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·9",
   "skos:prefLabel": {
    "@value": "Stale Proxy and Mirror",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A proxy keeps serving a version upstream has removed as malicious, or a mirror serves old metadata to hide a fix.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A proxy or mirror reflects upstream removals and metadata changes within a bounded time, and a client can tell when it does not.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Subscribe the internal proxy to upstream yank, removal and advisory events, and purge or block the affected versions on receipt.",
      "@language": "en-GB"
     },
     {
      "@value": "Set a maximum metadata age on every proxy and mirror, and fail resolution rather than serve metadata older than that limit.",
      "@language": "en-GB"
     },
     {
      "@value": "Use signed metadata with timestamps and version numbers, so a client rejects a mirror that presents an older snapshot than one it has already seen.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Go module proxy cached typosquat (Socket, 2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/141.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/672.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/141.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·8",
   "skos:prefLabel": {
    "@value": "Name and Namespace Squatting",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Anyone can claim names close to popular ones, look-alike organisation scopes, or names freed by deletion.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Package names and scopes that consumers trust are bound to a verified owner, and cannot be claimed by someone else once freed.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Reserve names freed by deletion or transfer for a cooling-off period, and never reassign a name that had significant downloads.",
      "@language": "en-GB"
     },
     {
      "@value": "Block registration of names and scopes within a small edit distance of popular ones, and flag look-alike names for review.",
      "@language": "en-GB"
     },
     {
      "@value": "Offer namespace verification through a DNS record or verified organisation, and show the verified status to consumers and in resolution output.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/630.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/630.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1007.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1007.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·7",
   "skos:prefLabel": {
    "@value": "Cross-Ecosystem Mirroring",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Automated mirroring or repackaging carries a malicious package from one ecosystem into another.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A package entering an ecosystem by automated mirroring or repackaging is judged in that ecosystem as if it were new.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Keep an inventory of every automated mirror and repackaging job, with the source ecosystem and the target namespace each one writes to.",
      "@language": "en-GB"
     },
     {
      "@value": "Run the target ecosystem's malware and policy checks on every mirrored or repackaged artifact before it becomes resolvable.",
      "@language": "en-GB"
     },
     {
      "@value": "Propagate upstream takedowns to every mirrored copy by recording the source identifier and content hash with each repackaged artifact.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Shai-Hulud 2.0, npm to Maven Central (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/669.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/669.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·6",
   "skos:prefLabel": {
    "@value": "Trusted Domain Abuse",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Malware, miners and phishing payloads are hosted under the registry's trusted domain and pass network controls.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Network trust is granted to specific repositories and artifacts, not to every byte a trusted domain will serve.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Route registry traffic through an internal proxy and deny direct egress to registry domains, so allowing a domain does not allow all of its content.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan downloaded content after fetch for malware and unexpected file types, regardless of the domain it came from.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict pipelines to an allow list of repositories, organisations or image paths on each registry, rather than allowing the whole host.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/185.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/183.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/183.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·5",
   "skos:prefLabel": {
    "@value": "Popularity Signal Manipulation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Stars, download counts and linked source repositories are faked to make a package look established.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Trust decisions about a package rest on verifiable facts about its origin, never on counts the publisher can inflate.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Remove stars, download counts and similar popularity metrics from every automated admission and risk scoring rule.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify that a package's linked source repository is its real origin by checking build provenance (see PV) rather than the repository URL in its metadata.",
      "@language": "en-GB"
     },
     {
      "@value": "Base trust on signals such as verified publisher, provenance, maintainer history and package age, and record which signal admitted each package.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: StarJacking (Checkmarx, 2022).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/693.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/691.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/693.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·4",
   "skos:prefLabel": {
    "@value": "Private Artifact Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Private packages or images are published publicly by mistake, or repositories allow anonymous pull.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Private artifacts can reach only private destinations, and every read of them requires an authenticated identity.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Disable anonymous read on every internal repository by default, and report any repository where it is enabled with an owner and a reason.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure publish steps with an explicit internal registry URL and scope, and block CI egress to public publish endpoints except from approved release workflows.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan images and packages for secrets and internal hostnames before push, and fail the push when a finding is not marked as a false positive.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/552.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/552.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/306.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·3",
   "skos:prefLabel": {
    "@value": "Retention Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Retention policies delete artifacts still deployed, or that an investigation needs.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An artifact that is running, or that an investigation depends on, cannot be removed by a retention rule.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Exempt any digest currently deployed, as reported by the deployment system, from automated retention and cleanup.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict deletion in release repositories to a separate role, log every deletion, and allow a legal or incident hold that blocks deletion entirely.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain the exact digest, SBOM and provenance of everything deployed for a defined period after it stops running, so investigators can retrieve what ran.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    },
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/826.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/826.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/registries/#rg-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/registries/"
   },
   "skos:notation": "RG·2",
   "skos:prefLabel": {
    "@value": "Upstream Availability",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Public registry outages or rate limits stop builds, and the fallback widens trust.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "When a public registry is unavailable, builds slow down or stop rather than fetch from a source they would not otherwise trust.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Serve all builds from an internal mirror or caching proxy that holds every locked dependency, so a public outage does not block them.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove secondary or fallback registry URLs from client configuration, so an outage cannot cause resolution from a less trusted source.",
      "@language": "en-GB"
     },
     {
      "@value": "Authenticate to public registries with an organisation account to raise rate limits, and alert when throttling begins rather than switching source.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/603.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/603.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "FW",
   "skos:prefLabel": {
    "@value": "Firewall and Quarantine",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A dependency firewall works only if it is the single way in and judges what it serves, not what it once saw. These cards cover dependency firewalls, curated proxies, cooldowns, quarantine and the exceptions that keep builds moving.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Dependency firewalls, curated proxies, cooldowns, quarantine, allow lists and exceptions",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-2"
    }
   ],
   "ost:position": 11,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·A",
   "skos:prefLabel": {
    "@value": "Bypass Route",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Some clients reach public registries directly: hard-coded URLs, build plugins, CI images with default configuration, developer machines, install scripts.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The firewall is the only network path from any factory client to a public registry, and that is enforced by the network rather than by configuration.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Block direct egress to public registry hosts at the network layer for CI, build and developer networks, and allow only the firewall to reach them.",
      "@language": "en-GB"
     },
     {
      "@value": "Inventory tools, build plugins and scripts that fetch outside the package manager, using egress logs, and route each one through the firewall or block it.",
      "@language": "en-GB"
     },
     {
      "@value": "Apply the same proxy and egress rules to developer machines and remote workers through managed configuration and a device network policy.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/424.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/420.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·K",
   "skos:prefLabel": {
    "@value": "Pre-Policy Cache",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Packages cached before a policy existed, or before a version was flagged, keep being served unchecked.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every artifact is judged against current policy and intelligence each time it is served, however long it has been cached.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Re-evaluate cached artifacts whenever a policy rule or intelligence feed changes, and block any that now fail before the next request.",
      "@language": "en-GB"
     },
     {
      "@value": "Check pinned versions in lockfiles and CI caches against current intelligence on a schedule, and fail builds that still reference a flagged version.",
      "@language": "en-GB"
     },
     {
      "@value": "Evaluate policy at serve time as well as at first fetch, so a flagged version cannot be returned from the firewall's cache.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/141.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/672.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/141.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/672.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·Q",
   "skos:prefLabel": {
    "@value": "Broad Exception",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An exception for one package covers every version or skips every check, and nobody removes it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An exception allows the smallest thing that unblocks the work, for a limited time, and is decided by someone other than the requester.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Scope each exception to a package, version and content hash, and to the single check it waives rather than to all checks.",
      "@language": "en-GB"
     },
     {
      "@value": "Give every exception an expiry date and an owner, and remove or renew it automatically when it lapses.",
      "@language": "en-GB"
     },
     {
      "@value": "Require approval from a reviewer other than the requester, and record who granted each exception and why.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/183.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/183.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·J",
   "skos:prefLabel": {
    "@value": "Detection Window",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The firewall blocks only packages already known to be malicious, so a new malicious release passes until intelligence catches up.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "New releases are kept out of builds until there has been time for them to be analysed and reported, with a reviewed way through for urgent fixes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce a minimum package age, or cooldown, of several days before a new version can be resolved, and apply it to transitive dependencies too.",
      "@language": "en-GB"
     },
     {
      "@value": "Run behavioural and diff analysis on new releases during the cooldown, and quarantine any that show install-time execution or new network access.",
      "@language": "en-GB"
     },
     {
      "@value": "Allow an urgent version to skip the cooldown only through a named, time-limited exception that pins its content hash and triggers a review.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/184.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/184.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·10",
   "skos:prefLabel": {
    "@value": "Fail-Open Firewall",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "When the intelligence feed, policy service or proxy fails, requests pass through or clients fall back to the public registry.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "If the firewall cannot decide, it does not serve, and any choice to fail open is explicit, owned and logged.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Fail closed by default when the intelligence feed, policy service or proxy is unavailable, and return a distinct error that names the cause.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove any client fallback to the public registry, and block public registry egress so a fallback cannot occur even if it is configured.",
      "@language": "en-GB"
     },
     {
      "@value": "Make fail-open a recorded per-ecosystem setting with an owner, and log and alert every request served while it is in effect.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/607.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/607.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·9",
   "skos:prefLabel": {
    "@value": "Ecosystem Coverage Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The firewall covers some ecosystems but not others: Go modules, Cargo, container images, CI actions, IDE extensions, AI models.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every kind of artifact the factory consumes passes through the same admission policy, whatever ecosystem it belongs to.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Inventory every artifact type the factory consumes, from egress logs and build configuration, and list which ones the firewall does not yet proxy.",
      "@language": "en-GB"
     },
     {
      "@value": "Proxy CI actions, base images, Go modules and Cargo crates through governed repositories, and block their public sources at egress.",
      "@language": "en-GB"
     },
     {
      "@value": "Bring IDE extensions and AI model downloads under the same policy through an internal marketplace or model registry with allow lists.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/424.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·8",
   "skos:prefLabel": {
    "@value": "Coordinates Without Content",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The firewall judges a name and version, not the content hash, so a different file with the same coordinates passes.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The firewall admits content, so a decision about a version holds only for the exact bytes it evaluated.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record the content hash of every artifact at first evaluation, and bind each policy decision to that hash rather than to name and version.",
      "@language": "en-GB"
     },
     {
      "@value": "Block and alert when upstream serves different bytes for a version the firewall has already seen.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify signatures and provenance where the ecosystem publishes them, and reject an artifact whose attestation does not match its hash (see PV).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/148.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/148.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1023.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1023.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·7",
   "skos:prefLabel": {
    "@value": "Quarantine Release Abuse",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A quarantined artifact is released without re-evaluation, or by the person who requested it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Release from quarantine is a new decision taken by someone independent, using what is known at the time of release.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Re-scan an artifact with current intelligence at the moment of release, and refuse release if the result is worse than when it was quarantined.",
      "@language": "en-GB"
     },
     {
      "@value": "Prevent self-release by requiring that the approver is not the person who requested the artifact or the exception.",
      "@language": "en-GB"
     },
     {
      "@value": "Limit release rights to a small security role, and log each release with the approver, the reason and the content hash.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/863.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/841.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/863.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·6",
   "skos:prefLabel": {
    "@value": "Fetch Visibility Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Fetches are not logged with requester and digest, so after an incident nobody can say which builds pulled the bad version.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every fetch leaves a record that answers which builds and machines received which bytes, and when.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Log every fetch with requester identity, build or job identifier, package coordinates, content hash and time.",
      "@language": "en-GB"
     },
     {
      "@value": "Index fetch logs so that a query by version or hash returns every build and machine that pulled it within minutes.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain fetch logs for at least as long as the longest-lived deployed artifact, and protect them from deletion by firewall administrators.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·5",
   "skos:prefLabel": {
    "@value": "Heuristic Evasion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Malicious packages dodge firewall analysis: a clean first release, payloads fetched at run time, obfuscation, delayed activation.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Analysis judges what a package does and how it changed, not only what its first release looked like.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run packages in an instrumented sandbox during install and import, and flag network fetches, process launches and file writes outside the package directory.",
      "@language": "en-GB"
     },
     {
      "@value": "Analyse the diff between each new version and the previous one, and raise the risk score for new install scripts, binaries or obfuscated code.",
      "@language": "en-GB"
     },
     {
      "@value": "Track publisher history and flag releases that follow a pattern of clean versions then sudden behaviour change, new maintainers or new dependencies.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/655.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/506.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/511.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/655.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/506.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·4",
   "skos:prefLabel": {
    "@value": "Firewall as Target",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Whoever controls the firewall's console or policy store can allow anything into every build.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Control of the firewall is treated as control of every build, and protected to that level.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Federate firewall administration through the organisation's identity provider with phishing-resistant MFA, and remove local admin accounts.",
      "@language": "en-GB"
     },
     {
      "@value": "Manage firewall policy as code in a reviewed repository, so every rule change needs a second approver before it applies.",
      "@language": "en-GB"
     },
     {
      "@value": "Send policy change and admin audit logs to a store the firewall administrators cannot modify, and alert on changes made outside the policy pipeline.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/578.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/176.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1390.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/578.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/654.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·3",
   "skos:prefLabel": {
    "@value": "Friction Bypass",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Blocks with no fast exception path push teams to vendor code, use personal tokens or route around the proxy.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Following the policy is the fastest way to get an unblocked build.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Return a block message that names the rule, the reason and a link to request an exception, rather than a bare error.",
      "@language": "en-GB"
     },
     {
      "@value": "Set and measure a service level for exception decisions, and offer a self-service path for low-risk cases such as a newer version of an approved package.",
      "@language": "en-GB"
     },
     {
      "@value": "Monitor for circumvention, such as vendored registry code, personal tokens on public registries and direct egress attempts, and follow up each finding with the team.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/655.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/655.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/#fw-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
   },
   "skos:notation": "FW·2",
   "skos:prefLabel": {
    "@value": "Policy Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Rules set once are never reviewed, so deny lists go stale and disabled rules stay disabled.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every rule has an owner and a review date, so policy reflects current threats rather than the day it was written.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Assign a named owner and a review date to every rule, and report rules that are past their review date.",
      "@language": "en-GB"
     },
     {
      "@value": "Require a reason and an expiry when a rule is disabled, and re-enable it or escalate to its owner when the expiry passes.",
      "@language": "en-GB"
     },
     {
      "@value": "Test policy against a set of known malicious and known good packages on a schedule, and alert when a rule stops catching what it should.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/184.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/184.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "BM",
   "skos:prefLabel": {
    "@value": "SBOM and VEX",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An SBOM is a claim about an artifact, and every decision built on it inherits its gaps and its author's honesty. These cards cover SBOM generation, storage and exchange, VEX statements, and the vulnerability and licence decisions driven by inventory.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "SBOM generation, storage and exchange, VEX statements, decisions driven by inventory",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-2"
    }
   ],
   "ost:position": 12,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·A",
   "skos:prefLabel": {
    "@value": "Unverifiable SBOM",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An SBOM is accepted without a signature or a binding to the artifact's digest, so anyone can supply one claiming any contents.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An SBOM is trusted only when its signer is known and it is bound to the exact artifact it describes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Publish each SBOM as a signed in-toto attestation whose subject is the artifact's digest, and store it alongside the artifact.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify the signer's identity against an expected issuer and build identity before ingesting an SBOM, and reject unsigned ones.",
      "@language": "en-GB"
     },
     {
      "@value": "Reject a supplier SBOM whose subject digest does not match the artifact actually received.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/690.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/347.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/354.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·K",
   "skos:prefLabel": {
    "@value": "Incomplete Inventory",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The SBOM omits components: static libraries, vendored code, OS packages, copied-in binaries, build tools, code downloaded at run time.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The inventory is derived from what actually ships, and states which kinds of component it could not see.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Generate the SBOM from the final artifact or image, not only from source manifests, and merge in build-time data from the build system.",
      "@language": "en-GB"
     },
     {
      "@value": "Detect copied-in and statically linked binaries by file hash and signature matching, and list unidentified binaries as unknown components rather than omitting them.",
      "@language": "en-GB"
     },
     {
      "@value": "Record in the SBOM which component types the generator covers, and mark the SBOM as incomplete when known gaps such as run-time downloads apply.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·Q",
   "skos:prefLabel": {
    "@value": "Malicious VEX",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A VEX statement marks an exploitable vulnerability \"not affected\", suppressing it for every consumer, and its author is not verified.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A VEX statement suppresses a finding only when it comes from an authorised, verified author with a justification someone has checked.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Accept only signed VEX documents from an allow list of authors, and reject unsigned or unknown-author statements.",
      "@language": "en-GB"
     },
     {
      "@value": "Require a justification code and supporting evidence for every not_affected statement, and route third-party statements to human review before they take effect.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep your own analysis authoritative, so an external VEX can propose a status but cannot override an internal affected decision automatically.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/194.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/194.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/807.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·J",
   "skos:prefLabel": {
    "@value": "SBOM Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The SBOM describes a different build from the one deployed: generated at the wrong stage, not refreshed after a patch, served from cache.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The SBOM and the artifact are produced together and bound by digest, so one cannot change without the other.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Generate the SBOM in the same build step that produces the artifact, and attach it as an attestation to that artifact's digest.",
      "@language": "en-GB"
     },
     {
      "@value": "Regenerate and re-attach the SBOM on every rebuild or patch, and never copy or cache an SBOM from a previous build.",
      "@language": "en-GB"
     },
     {
      "@value": "Check at deployment and in inventory queries that the deployed digest matches the SBOM's subject, and flag any deployment without a match.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1250.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·10",
   "skos:prefLabel": {
    "@value": "Identifier Ambiguity",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Components are named inconsistently (PURL and CPE, forks, renamed or repackaged packages), so vulnerability matching misses or misattributes.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each component carries an identifier precise enough to match vulnerabilities to the code actually shipped.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Use package URLs (PURL) as the primary identifier, with CPE only as a secondary mapping, and record the upstream source for forks and repackaged components.",
      "@language": "en-GB"
     },
     {
      "@value": "Include file hashes for components, so a fork or rebuilt package can be told apart from the original it was derived from.",
      "@language": "en-GB"
     },
     {
      "@value": "Test vulnerability matching against a fixed set of known renamed, forked and repackaged cases, and fail the pipeline when a known match is missed.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/694.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/694.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·9",
   "skos:prefLabel": {
    "@value": "Hostile SBOM Document",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "SBOMs from suppliers are untrusted input to parsers, databases and dashboards.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Supplier SBOMs are handled as untrusted input by every system that reads them.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Parse supplier SBOMs in an isolated worker with no network access or database credentials, and validate them against the SPDX or CycloneDX schema first.",
      "@language": "en-GB"
     },
     {
      "@value": "Enforce limits on document size, nesting depth and component count, and reject documents that exceed them.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable external entities and DTD processing in XML parsers, and encode SBOM fields before they are rendered in dashboards.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/230.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/201.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/230.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/611.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/611.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/79.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/770.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·8",
   "skos:prefLabel": {
    "@value": "Inventory as Reconnaissance",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A published or shared SBOM tells an attacker which vulnerable components run where.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "SBOMs reach only the parties who need them, under terms that limit further sharing, and every access is recorded.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Share SBOMs through an authenticated portal under agreed terms rather than publishing them openly, especially for internet-facing systems.",
      "@language": "en-GB"
     },
     {
      "@value": "Log every read of the SBOM store with requester identity, and review access by external parties periodically.",
      "@language": "en-GB"
     },
     {
      "@value": "Pair each shared SBOM with its VEX, so recipients see which listed vulnerabilities are not exploitable rather than treating each one as an open target.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/310.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/169.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/310.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/497.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/497.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/213.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·7",
   "skos:prefLabel": {
    "@value": "SBOM Store Tampering",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The central SBOM repository can be edited, so inventory queries during an incident return false answers.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Inventory records cannot be changed after they are written, and any change would be visible.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Store SBOMs as signed attestations in append-only storage, so a correction is a new record rather than an edit.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict write access to the SBOM store to the build pipeline's identity, and deny update and delete to people and other services.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify signatures on retrieval and record SBOM hashes in a transparency log, so a changed or replaced record is detected.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/268.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·6",
   "skos:prefLabel": {
    "@value": "Stale VEX",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A \"not affected\" statement stays in force after a code change makes the component reachable.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A not_affected status holds only for the code it was assessed against, and lapses when that code or time moves on.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Bind each VEX statement to specific product versions or digests, and give every statement an expiry date.",
      "@language": "en-GB"
     },
     {
      "@value": "Re-evaluate VEX statements automatically when the affected component, its callers or the product version change, and revert the status to under_investigation until reviewed.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign each VEX statement a named owner who is notified on expiry or re-evaluation.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/672.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/672.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·5",
   "skos:prefLabel": {
    "@value": "Conversion Loss",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Converting between SPDX and CycloneDX, or between versions, drops hashes, licences or relationships.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Converting an SBOM preserves every field that later decisions depend on, or says what was lost.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Document which fields each conversion tool drops, and choose tools that preserve hashes, licences and relationships.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare component counts, hashes and relationships before and after conversion, and fail the conversion when any are missing.",
      "@language": "en-GB"
     },
     {
      "@value": "Re-validate converted SBOMs against the target schema and keep the original document as the authoritative copy.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·4",
   "skos:prefLabel": {
    "@value": "Flat Inventory",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The SBOM lists components without their relationships, so reachability and blast radius cannot be worked out.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The inventory records how components relate, so blast radius and reachability can be worked out from it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Record dependency relationships in the SBOM using CycloneDX dependencies or SPDX relationships, marking direct and transitive dependencies.",
      "@language": "en-GB"
     },
     {
      "@value": "Reject SBOMs with no dependency graph at ingestion, or flag them as flat so decisions built on them are marked lower confidence.",
      "@language": "en-GB"
     },
     {
      "@value": "Load SBOMs into a queryable store that can answer which artifacts contain a component and which direct dependency brought it in.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·3",
   "skos:prefLabel": {
    "@value": "Compliance Theatre",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "SBOMs are produced to meet a requirement and consumed by nothing, so a vulnerable component in one blocks nothing.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every SBOM feeds at least one decision that can block or change what ships.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Feed every SBOM into a vulnerability and licence policy check that can fail the build or block deployment.",
      "@language": "en-GB"
     },
     {
      "@value": "Re-check stored SBOMs against new advisories continuously, and raise findings for deployed artifacts without waiting for a rebuild.",
      "@language": "en-GB"
     },
     {
      "@value": "Name the system and owner that consume each SBOM, and report SBOMs that no query or policy has read in a set period.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/#bm-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
   },
   "skos:notation": "BM·2",
   "skos:prefLabel": {
    "@value": "Missing Supplier SBOM",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Third-party software arrives with no SBOM, or one made by a tool that sees different things from yours.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Third-party software has an inventory before it is deployed, either from its supplier or produced locally.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Make a signed, digest-bound SBOM a procurement and contract requirement for third-party software.",
      "@language": "en-GB"
     },
     {
      "@value": "Generate your own SBOM for every third-party artifact on receipt, and compare it with the supplier's to find components either one misses.",
      "@language": "en-GB"
     },
     {
      "@value": "Track third-party artifacts with missing or partial SBOMs in a register with an owner and a date for resolution.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "IC",
   "skos:prefLabel": {
    "@value": "Infrastructure as Code",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Infrastructure as code makes the estate reviewable, and makes whoever runs the code the owner of the estate. These cards cover Terraform and OpenTofu, Pulumi, CloudFormation and configuration management, their state, modules and providers, and the plan and apply pipeline.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Terraform and OpenTofu, Pulumi, CloudFormation, Ansible; state, modules, providers, plan and apply",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-2"
    }
   ],
   "ost:position": 13,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·A",
   "skos:prefLabel": {
    "@value": "State File Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "State files hold secrets and full resource detail in plain text, in storage readable by too many identities.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "State is treated as a secret store, encrypted, readable only by the identities that apply it, and audited.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Use an encrypted state backend with a key that only the apply role can use, and block public access to the backend.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict state read access to the apply and plan roles for each workspace, and remove read access from developers and broad admin groups.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep secrets out of state by reading them at run time from a secret store or using ephemeral values, and mark unavoidable outputs as sensitive.",
      "@language": "en-GB"
     },
     {
      "@value": "Log every read and write of state objects, and alert on access from an identity that is not a pipeline role.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/639.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/312.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/922.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/639.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/312.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·K",
   "skos:prefLabel": {
    "@value": "Plan-Time Code Execution",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Running plan on an untrusted change executes code (external data sources, provider and module downloads), so a pull request borrows the pipeline's cloud credentials.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Planning an untrusted change cannot reach credentials or execute code with more privilege than its author already has.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run plan with a separate, read-only OIDC role that cannot write resources or read secrets, distinct from the apply role.",
      "@language": "en-GB"
     },
     {
      "@value": "Require a maintainer to approve plan runs on changes from forks or first-time contributors before the job receives any cloud credentials.",
      "@language": "en-GB"
     },
     {
      "@value": "Block external data sources, local-exec provisioners and unapproved providers during plan with policy-as-code on the configuration.",
      "@language": "en-GB"
     },
     {
      "@value": "Install providers and modules only from an internal mirror during plan, so plan cannot download and run arbitrary code.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/175.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/233.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/175.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·Q",
   "skos:prefLabel": {
    "@value": "Malicious Module or Provider",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Modules and providers are pulled by name and floating version, then run with the cloud credentials.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Modules and providers that run with cloud credentials are fixed to reviewed content and fetched from a controlled source.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin modules and providers to exact versions, and commit the dependency lock file with checksums so a changed package fails installation.",
      "@language": "en-GB"
     },
     {
      "@value": "Mirror approved modules and providers internally, and configure the tool to install only from that mirror.",
      "@language": "en-GB"
     },
     {
      "@value": "Require security review and an allow-list entry before a new module source or provider namespace can be used.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·J",
   "skos:prefLabel": {
    "@value": "Over-Privileged Apply Identity",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The identity that applies the code is admin across accounts, so compromising the IaC pipeline means owning the estate.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each apply can change only the resources its workspace owns, and never the permissions that bound it.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Issue a separate OIDC-scoped apply role per workspace or account, trusted only for that repository, branch and environment.",
      "@language": "en-GB"
     },
     {
      "@value": "Gate apply on approval of the reviewed plan by someone other than the author, through a protected environment.",
      "@language": "en-GB"
     },
     {
      "@value": "Deny apply roles the ability to create identities or modify their own policies, using permission boundaries or organisation-level service control policies.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·10",
   "skos:prefLabel": {
    "@value": "Plan and Apply Divergence",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "What is applied differs from what was reviewed: the plan is regenerated at apply time, or state changed in between.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The changes applied are exactly the changes that were reviewed, and nothing else.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Save the plan to a file in the plan job, and apply that saved plan file rather than generating a new plan at apply time.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail apply when state has changed since the plan was made, which saved plan files do by default, and require a fresh plan and review.",
      "@language": "en-GB"
     },
     {
      "@value": "Store the plan file as an artifact bound to its commit hash and a content hash, and verify both before apply.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/367.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/29.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/367.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·9",
   "skos:prefLabel": {
    "@value": "Configuration Controller",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A configuration management controller pushes root-level commands to every host, so its playbooks, inventory and credentials are a single point of compromise.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The configuration controller's reach is limited to what each run needs, and every change to what it runs is reviewed.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Keep playbooks and inventory in a protected repository with required review, and run only from reviewed commits.",
      "@language": "en-GB"
     },
     {
      "@value": "Replace standing root credentials with short-lived, per-run credentials or signed SSH certificates scoped to the target hosts.",
      "@language": "en-GB"
     },
     {
      "@value": "Split the controller by environment or host group, so one compromised controller cannot reach every host.",
      "@language": "en-GB"
     },
     {
      "@value": "Log every run with its commit, operator, target hosts and outcome to a store the controller cannot modify.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/445.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/234.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/445.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·8",
   "skos:prefLabel": {
    "@value": "Drift and Out-of-Band Change",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Console and CLI changes create infrastructure the code does not describe, so review no longer reflects reality and backdoors survive.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The code is the only routine way to change infrastructure, and any difference between code and reality is found and resolved.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run drift detection on a schedule for every workspace, and alert the owner on any difference from the last applied state.",
      "@language": "en-GB"
     },
     {
      "@value": "Limit console and CLI write access to read-only for most people, with write access only through a logged break-glass role.",
      "@language": "en-GB"
     },
     {
      "@value": "Open a reconciliation ticket automatically for every break-glass session, and close it only when the change is imported into code or reverted.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/176.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/176.html"
   },
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·7",
   "skos:prefLabel": {
    "@value": "Secrets in Variables and Output",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets are hard-coded or passed as plain variables that appear in logs, plan output and state.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Secrets reach infrastructure tools at run time from a secret store, and never appear in code, logs or review output.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Read secrets from a secret store at apply time using the pipeline's workload identity, and block hard-coded secrets with a pre-merge secret scan.",
      "@language": "en-GB"
     },
     {
      "@value": "Mark secret variables and outputs as sensitive so plan output and logs mask them, and fail review when a known secret pattern appears unmasked.",
      "@language": "en-GB"
     },
     {
      "@value": "Post only a summary of plan output to pull request comments, and keep the full plan in access-controlled pipeline storage.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/798.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/532.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/798.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·6",
   "skos:prefLabel": {
    "@value": "Insecure Defaults Propagated",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Templates and shared modules encode public storage, open network rules or disabled encryption, and copying spreads them.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Shared templates are secure by default, and every plan is checked against policy before it can be applied.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Evaluate policy-as-code on every plan, checking for public storage, open network rules and disabled encryption, and fail the pipeline on a violation.",
      "@language": "en-GB"
     },
     {
      "@value": "Build shared modules with encryption, private access and logging on by default, and require an explicit, named input to turn any of them off.",
      "@language": "en-GB"
     },
     {
      "@value": "Allow a policy failure to be overridden only through a recorded exception approved by the policy owner, not by the change author.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: IaC security smells (Rahman et al., 2019).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1188.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1188.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·5",
   "skos:prefLabel": {
    "@value": "Destructive Change",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A change, typo or rename destroys and recreates databases, keys or DNS records.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Destroying a critical resource requires a deliberate, separately approved action, never a side effect of an ordinary change.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Show destroy and replace actions prominently in the plan summary, and require additional approval for any plan that contains them.",
      "@language": "en-GB"
     },
     {
      "@value": "Enable deletion protection on databases, keys and DNS zones in both the code and the cloud provider, such as prevent_destroy lifecycle rules.",
      "@language": "en-GB"
     },
     {
      "@value": "Block plans that destroy resources tagged as protected using policy-as-code, and use moved blocks so renames do not cause replacement.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·4",
   "skos:prefLabel": {
    "@value": "Orphaned Resources",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Resources removed from code are not destroyed, and run on unmanaged: forgotten endpoints, dangling DNS records others can claim.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every resource in the estate is either managed by code or known and owned, and nothing is left running unmanaged.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require resource removal to go through a destroy in the plan, and flag state rm or removed blocks without destroy for explicit review.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare cloud inventory with all state files on a schedule, and report resources that no workspace manages to an owner.",
      "@language": "en-GB"
     },
     {
      "@value": "Detect DNS records that point at released IP addresses, buckets or hostnames, and alert before someone else can claim the target.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/154.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/672.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/154.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/672.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·3",
   "skos:prefLabel": {
    "@value": "Cross-Workspace Reach",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Workspaces read each other's state or outputs, so a low-trust workspace learns secrets from a high-trust one.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A workspace can read only the specific outputs it has been granted, and never another workspace's full state.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Share values between workspaces through explicit outputs or a parameter store, rather than granting read access to another workspace's state.",
      "@language": "en-GB"
     },
     {
      "@value": "Expose only non-secret outputs that consumers need, and keep secrets in a secret store with its own access control.",
      "@language": "en-GB"
     },
     {
      "@value": "Grant remote state access per workspace with least privilege, and deny low-trust workspaces read access to high-trust ones.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/639.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/#ic-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
   },
   "skos:notation": "IC·2",
   "skos:prefLabel": {
    "@value": "State Locking and Corruption",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Concurrent applies, force-unlocks or edited state make the code adopt or orphan resources.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "State changes happen one at a time, every version can be recovered, and manual edits are rare, controlled and recorded.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable state locking in the backend, and fail any apply that cannot acquire the lock.",
      "@language": "en-GB"
     },
     {
      "@value": "Turn on versioning for the state backend so any previous state can be restored, and test restoring it.",
      "@language": "en-GB"
     },
     {
      "@value": "Restrict force-unlock and state editing commands to a break-glass role, and log each use with the operator and reason.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/26.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/667.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/362.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/26.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/667.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "IM",
   "skos:prefLabel": {
    "@value": "Container Images",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An image freezes a whole operating system and its contents into one artifact, including whatever the build let in. These cards cover base images, Dockerfiles, layers, image builders, tags and digests.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Base images, Dockerfiles, layers, image builds, tags and digests",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-2"
    }
   ],
   "ost:position": 14,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·A",
   "skos:prefLabel": {
    "@value": "Untrusted Base Image",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Images build on public base images pulled by tag from unverified publishers, so a compromised base enters every image built on it.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every image starts from a base the organisation has chosen, can identify by content, and will rebuild from when that base changes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Maintain a short list of approved base images mirrored into an internal registry, and reject builds whose FROM line points anywhere else.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin each FROM line by digest and verify the publisher's signature on that digest before the build starts.",
      "@language": "en-GB"
     },
     {
      "@value": "Assign every approved base an owning team that tracks upstream releases and triggers rebuilds of all dependent images when the base digest changes.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/446.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·K",
   "skos:prefLabel": {
    "@value": "Tag Instead of Digest",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Dockerfiles and deployments reference tags, so what runs changes whenever the tag moves.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "What is built and what is deployed are named by content, so a reference resolves to the same bytes every time it is used.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Resolve tags to digests at build time and write the digest, not the tag, into Dockerfiles, manifests and Helm values.",
      "@language": "en-GB"
     },
     {
      "@value": "Run an update bot that proposes digest bumps as reviewed changes, so a moved tag becomes a visible diff rather than a silent change.",
      "@language": "en-GB"
     },
     {
      "@value": "Reject at admission any pod spec whose image reference lacks a digest (see OR·J).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/690.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·Q",
   "skos:prefLabel": {
    "@value": "Secrets in Layers",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets copied or set during the build remain in a layer or in build history, even if a later step deletes them.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Build-time secrets are available to the step that needs them and never become part of any layer, cache entry or history record.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Provide credentials to build steps through BuildKit secret mounts or SSH forwarding, and forbid ARG, ENV and COPY for secret material.",
      "@language": "en-GB"
     },
     {
      "@value": "Use multi-stage builds that copy only named artifacts into the final stage, so build tooling and intermediate files stay behind.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan every layer and the image history for secrets before push, and fail the build on any finding.",
      "@language": "en-GB"
     },
     {
      "@value": "Rotate any credential found in a published image, because deleting the tag does not recall copies already pulled.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Codecov Docker image credential (2021).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/212.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/212.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·J",
   "skos:prefLabel": {
    "@value": "Fetch During Image Build",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Build steps download scripts and install unpinned packages, outside the controls on application dependencies.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "An image build draws its inputs through the same controlled, pinned path as the application's own dependencies.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Route all network access from image builds through the organisation's dependency proxy, and deny direct egress from builders.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin operating system and language packages installed in Dockerfiles to exact versions, and verify a checksum for any file fetched by URL.",
      "@language": "en-GB"
     },
     {
      "@value": "Build a sample of images twice from the same inputs and compare the results, treating any difference as an unpinned input to track down.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·10",
   "skos:prefLabel": {
    "@value": "Builder Escape",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The image builder runs privileged, and a hostile Dockerfile or build context breaks out onto the build host.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Building an image grants no more authority over the build host than running an untrusted program would.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run image builds with a rootless builder in a user namespace, with no access to the host's container daemon socket.",
      "@language": "en-GB"
     },
     {
      "@value": "Build Dockerfiles from forks, external contributors or tenants on ephemeral builders, ideally microVMs, that hold no secrets and are destroyed after each job.",
      "@language": "en-GB"
     },
     {
      "@value": "Patch builders and their runtimes on a defined clock, and track builder versions in the same inventory as production components.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Leaky Vessels BuildKit flaws (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·9",
   "skos:prefLabel": {
    "@value": "Fetch on Start",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The container downloads code or configuration when it starts, so what runs is not what was scanned or signed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Everything a container executes is either in the image that was scanned and signed, or verified at load against an identity the build recorded.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Move plugin, script and model downloads from the entrypoint into the build, so they are scanned and covered by the image signature.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin each object that must still be loaded at run time by digest, and verify its signature before executing it.",
      "@language": "en-GB"
     },
     {
      "@value": "Deny egress from workloads by default with NetworkPolicy, so an undeclared startup fetch fails visibly in testing.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/185.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·8",
   "skos:prefLabel": {
    "@value": "Malicious Public Image",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Public hubs host images with miners or backdoors, some named to pass for official images.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Workloads run only images from sources the organisation has reviewed, and adding a source is a decision rather than a pull.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pull public images only through an internal registry proxy that allows listed namespaces and verified publishers.",
      "@language": "en-GB"
     },
     {
      "@value": "Require a recorded review, with an owner and a justification, before a new upstream namespace joins that allow list.",
      "@language": "en-GB"
     },
     {
      "@value": "Enforce allowed registries at admission, so an image referenced directly from a public hub is rejected.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: docker123321 images on Docker Hub (2018).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/616.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/185.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/616.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·7",
   "skos:prefLabel": {
    "@value": "Root and Tools by Default",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Images run as root and ship shells, package managers and setuid binaries that help an attacker after entry.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A runtime image contains only what the application needs and starts with no privilege it does not use.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build runtime images on distroless or scratch bases in a final stage that contains no shell, package manager or compiler.",
      "@language": "en-GB"
     },
     {
      "@value": "Set a numeric non-root USER in the image, and enforce runAsNonRoot and allowPrivilegeEscalation false at admission.",
      "@language": "en-GB"
     },
     {
      "@value": "Strip setuid and setgid bits from the final filesystem during the build, and fail the build if any remain.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/69.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/69.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·6",
   "skos:prefLabel": {
    "@value": "Stale Image",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Images are built once and run for months, collecting unpatched components.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Images have a maximum age, and a patched base reaches running workloads by automatic rebuild rather than by someone remembering.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Trigger a rebuild and redeploy of every dependent image when an approved base image publishes a new digest.",
      "@language": "en-GB"
     },
     {
      "@value": "Rebuild all images on a fixed schedule, for example weekly, even when no source has changed.",
      "@language": "en-GB"
     },
     {
      "@value": "Record build time in signed provenance, and block admission of images older than the age limit unless an owned exception exists.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/310.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/310.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1395.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1104.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·5",
   "skos:prefLabel": {
    "@value": "Build Context Leakage",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The build context sends the whole repository, including VCS metadata and environment files, into the image.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The build sees only the files it needs, and the final image contains only files someone meant to ship.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Commit a deny-by-default .dockerignore that admits only listed paths, so .git, .env and credential files never reach the builder.",
      "@language": "en-GB"
     },
     {
      "@value": "Copy named paths into the final stage rather than whole directories, so new files in the repository do not ship by default.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare each image's file list with the previous release, and fail the build when VCS metadata, key files or environment files appear.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/37.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/497.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/527.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/538.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/37.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/527.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·4",
   "skos:prefLabel": {
    "@value": "Invisible Layer Contents",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Image scanners read package databases, so binaries copied in without a package manager escape the inventory.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Image inventory is built from the files the image contains, not only from what package managers recorded.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Use scanners that hash and identify binaries, archives and other files on disk as well as reading package databases (see BM·K).",
      "@language": "en-GB"
     },
     {
      "@value": "Record any software copied in without a package manager in the image's SBOM, with its source and checksum.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan the flattened filesystem the container will see, with whiteouts and overwrites applied, so files removed or replaced by later layers are reported correctly.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/223.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/223.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·3",
   "skos:prefLabel": {
    "@value": "Multi-Architecture Inconsistency",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Variants of one image for different architectures differ in content, and only one is scanned or signed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every platform variant of an image receives the same checks as the one people test, and the index binds them together.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Build all variants from the same source commit in one pipeline run, and emit provenance for each platform manifest.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan and sign each platform manifest as well as the image index, and make verification fail if any variant lacks either.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify at admission the digest of the platform manifest the node will actually pull, not only the index.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/477.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/477.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/347.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-images/#im-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
   },
   "skos:notation": "IM·2",
   "skos:prefLabel": {
    "@value": "Self-Declared Metadata",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Labels for source, version and maintainer are written by the builder and trusted by downstream tools.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Downstream decisions rely on facts attested by the build platform, and labels written by the builder are treated as hints.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Take source repository, commit and builder identity from signed provenance (see PV), and ignore labels for any policy or ownership decision.",
      "@language": "en-GB"
     },
     {
      "@value": "Fail verification when an image's source or version label disagrees with its provenance.",
      "@language": "en-GB"
     },
     {
      "@value": "Inventory the tools that read labels, such as scanners, dashboards and finding routers, and move each one to provenance fields.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/691.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/348.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/807.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/691.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/348.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "RT",
   "skos:prefLabel": {
    "@value": "Container Runtime",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A container is a set of kernel features, not a security boundary unless it is configured as one. These cards cover container runtimes, isolation, the host kernel and sandboxes.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Runtimes, isolation boundaries, the host kernel, sandboxes",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-2"
    }
   ],
   "ost:position": 15,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·A",
   "skos:prefLabel": {
    "@value": "Container Escape",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A runtime or kernel flaw lets a process break out of its container onto the host.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Hosts are patched on a measured clock and treated as expendable, so an escape reaches little beyond the node itself.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Patch container runtimes and node kernels within a defined window by replacing nodes from current images rather than patching in place.",
      "@language": "en-GB"
     },
     {
      "@value": "Run untrusted or multi-tenant code in a microVM or user-space kernel sandbox selected through a RuntimeClass.",
      "@language": "en-GB"
     },
     {
      "@value": "Give nodes no credentials beyond their own, restrict kubelets with Node authorisation, and block pod access to the metadata service.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: runc CVE-2019-5736 (2019); runc CVE-2024-21626 (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·K",
   "skos:prefLabel": {
    "@value": "Privileged Container",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Workloads run privileged or with powerful capabilities, which amounts to root on the host.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Workloads receive only the kernel privileges they need, and any exception is visible, owned and time-limited.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce Pod Security Admission at the restricted level, which forbids privileged mode and requires all capabilities to be dropped except NET_BIND_SERVICE.",
      "@language": "en-GB"
     },
     {
      "@value": "Grant exemptions per namespace through a reviewed policy change that records an owner and an expiry date (see OR·J).",
      "@language": "en-GB"
     },
     {
      "@value": "Report every running privileged pod or added capability from the cluster's own state each day, and alert on any without a current exemption.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/233.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·Q",
   "skos:prefLabel": {
    "@value": "Host Mounts and Namespaces",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Host paths, the runtime socket, or the host's process and network namespaces are shared into containers.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A container sees only its own filesystem, processes and network unless a reviewed exception says otherwise.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Deny hostPath volumes, hostPID, hostIPC and hostNetwork at admission by default.",
      "@language": "en-GB"
     },
     {
      "@value": "Never mount the container runtime socket into workloads, and run agents that need host access on dedicated nodes.",
      "@language": "en-GB"
     },
     {
      "@value": "Allow any remaining hostPath mount only read-only, by exact path, in namespaces named in the exception policy.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·J",
   "skos:prefLabel": {
    "@value": "Shared Kernel Across Trust Levels",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Workloads of different trust share one kernel, so one kernel exploit crosses them all.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Workloads share a kernel only with workloads of the same trust level.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Label nodes by trust level and use taints, tolerations and node affinity so untrusted and sensitive workloads never schedule together.",
      "@language": "en-GB"
     },
     {
      "@value": "Run untrusted tenants and customer code in microVM sandboxes, giving each its own guest kernel.",
      "@language": "en-GB"
     },
     {
      "@value": "Place the most sensitive workloads, such as signing services and secret stores, on dedicated node pools or clusters.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·10",
   "skos:prefLabel": {
    "@value": "Unconfined Syscalls",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "No seccomp, AppArmor or SELinux profile applies, so the whole kernel attack surface is open to the container.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every container runs under a kernel confinement profile, and running unconfined needs an explicit, reviewed exception.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Set the RuntimeDefault seccomp profile for all pods, through the kubelet default or the pod spec, and enforce it at admission.",
      "@language": "en-GB"
     },
     {
      "@value": "Apply AppArmor or SELinux profiles to every workload, with custom profiles for services that warrant tighter confinement.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert on any running container that the runtime reports as unconfined for seccomp or its LSM.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·9",
   "skos:prefLabel": {
    "@value": "Credential Reach from Containers",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Containers can reach the cloud metadata service, node credentials or mounted service-account tokens they do not need.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A container can reach only the credentials its own workload needs, and node and cloud credentials stay out of its reach.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Block pod access to the cloud metadata endpoint with NetworkPolicy, and require IMDSv2 with a hop limit of one where the provider offers it.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable service-account token automount by default, and mount projected, audience-bound tokens only into pods that call the API.",
      "@language": "en-GB"
     },
     {
      "@value": "Give each workload its own cloud identity through workload identity federation instead of relying on the node's role.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/150.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/668.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/150.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1220.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·8",
   "skos:prefLabel": {
    "@value": "Exposed Runtime API",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The container daemon's API listens on the network without authentication, so anyone who reaches it can start containers.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The container runtime's API is reachable only locally, and any remote management is authenticated and authorised.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Bind the runtime API to a local Unix socket only, and disable TCP listeners in the daemon configuration.",
      "@language": "en-GB"
     },
     {
      "@value": "Require mutual TLS with client certificates for any remote management that remains, and firewall it to named management hosts.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan node and network ranges for runtime API ports such as 2375 and 2376, and alert on any listener that appears.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Graboid worm (Unit 42, 2019).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/36.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/306.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/36.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/306.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·7",
   "skos:prefLabel": {
    "@value": "Undetected Runtime Drift",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Processes, binaries and connections absent from the image appear at run time and nothing notices.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Expected behaviour is derived from the image and the workload, and any departure from it raises an alert that someone owns.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Deploy eBPF or audit-based runtime monitoring that alerts on processes, binaries and outbound connections absent from the image's baseline.",
      "@language": "en-GB"
     },
     {
      "@value": "Write detection rules for high-value signals such as shells in production containers, connections to mining pools and new executables in writable paths.",
      "@language": "en-GB"
     },
     {
      "@value": "Route runtime alerts to a named on-call rota with a playbook for isolating the pod and preserving evidence (see RT·2).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/549.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/549.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·6",
   "skos:prefLabel": {
    "@value": "Writable Root Filesystem",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The container's filesystem is writable, so an attacker can drop tools and persist across process restarts.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A container's filesystem matches its image for its whole life, and writable space is small, named and temporary.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Set readOnlyRootFilesystem to true for every container and enforce it at admission.",
      "@language": "en-GB"
     },
     {
      "@value": "Provide writable paths as named emptyDir volumes with size limits, backed by memory where possible.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert when an executable is written to or run from a writable volume.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/558.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/558.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·5",
   "skos:prefLabel": {
    "@value": "No User Namespace",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Root inside the container maps to root on the host.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Privilege inside a container does not carry over to the host, whatever user the process runs as.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable user namespaces for pods with hostUsers set to false, so container root maps to an unprivileged host UID range.",
      "@language": "en-GB"
     },
     {
      "@value": "Run workloads as a non-root UID set in the image and enforced at admission with runAsNonRoot.",
      "@language": "en-GB"
     },
     {
      "@value": "Check on each node pool that a container's root process appears on the host with an unprivileged UID.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/480.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/480.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·4",
   "skos:prefLabel": {
    "@value": "Resource Exhaustion",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Without limits on CPU, memory, processes and disk, one container starves its neighbours or the node.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every workload runs inside limits it cannot raise, so one container cannot exhaust the node it shares.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Require CPU, memory and ephemeral storage requests and limits on every container, with namespace defaults set by LimitRange.",
      "@language": "en-GB"
     },
     {
      "@value": "Set a per-pod PID limit in the kubelet configuration, and cap each namespace's totals with ResourceQuota.",
      "@language": "en-GB"
     },
     {
      "@value": "Reserve node resources for the kubelet and system daemons, and place tenants with unpredictable load on separate node pools.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/130.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/130.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/770.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/770.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·3",
   "skos:prefLabel": {
    "@value": "Unpacking Flaws",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The runtime unpacks image layers with path or symlink bugs that write outside the container's filesystem.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Image layers from outside the organisation are unpacked by a current runtime in a place where a path escape reaches nothing of value.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Patch container runtimes and image unpacking libraries on a defined clock, tracking advisories for path traversal and symlink flaws.",
      "@language": "en-GB"
     },
     {
      "@value": "Pull and unpack images from untrusted sources on isolated, ephemeral nodes that hold no secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify layer digests against the signed manifest before unpacking, and reject layers containing absolute paths, parent-directory entries or device files.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/132.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/126.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/22.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/59.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/132.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/22.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/#rt-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
   },
   "skos:notation": "RT·2",
   "skos:prefLabel": {
    "@value": "Ephemeral Evidence",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Container logs and filesystems disappear when the container is deleted, taking the evidence with them.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Evidence of what a container did outlives the container, in a store the workload cannot alter.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Ship container logs and runtime audit events off the node as they are written, to a store with separate administrators.",
      "@language": "en-GB"
     },
     {
      "@value": "Follow a response procedure that checkpoints or snapshots a suspect container's filesystem before the container is deleted.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain runtime and API audit records for longer than typical detection delays, and test that a terminated pod's history can be retrieved.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/571.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/571.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "OR",
   "skos:prefLabel": {
    "@value": "Orchestration",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The orchestrator's API is a remote shell on every node for whoever holds the right role. These cards cover the Kubernetes API, RBAC, admission, operators and Helm, nodes and cluster networking.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Kubernetes API, RBAC, admission, operators, Helm, nodes, cluster networking",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-2"
    }
   ],
   "ost:position": 16,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·A",
   "skos:prefLabel": {
    "@value": "Exposed Control Plane",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The API server, kubelet, etcd or a dashboard is reachable from the internet or accepts anonymous requests.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Control plane components accept only authenticated requests over private paths, and etcd answers only the API server.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Expose the API server on a private endpoint or to named source ranges, and reach it from outside through an authenticated access proxy.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable anonymous authentication on the API server and kubelets, and set kubelet authorisation to Webhook mode.",
      "@language": "en-GB"
     },
     {
      "@value": "Require client certificates for etcd, and firewall it so that only API server hosts can connect.",
      "@language": "en-GB"
     },
     {
      "@value": "Scan public address ranges for API server, kubelet, etcd and dashboard ports, and alert on any response.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: Tesla Kubernetes console (2018).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/36.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/306.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/36.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/306.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·K",
   "skos:prefLabel": {
    "@value": "Over-Broad RBAC",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Roles grant wildcards, secret reads, pod create and exec, or bind and impersonate, so many identities can become cluster-admin.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each identity holds the narrowest roles its job needs, and the paths by which a role can grow into cluster-admin are known and few.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Replace wildcard verbs and resources with explicit lists, and reject new wildcard roles in policy checks on RBAC manifests.",
      "@language": "en-GB"
     },
     {
      "@value": "Treat pod create, exec, secret read, bind, escalate and impersonate as privileged rights granted only to named groups.",
      "@language": "en-GB"
     },
     {
      "@value": "Run an RBAC escalation analysis in CI and on a schedule, and fail when any identity gains a path to cluster-admin.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/233.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/266.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·Q",
   "skos:prefLabel": {
    "@value": "Admission Webhook Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Admission webhooks see every object with high privilege, so one flaw gives cluster-wide control, and a failing webhook may fail open.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Admission webhooks are held to the standard of the cluster they guard, and their failure behaviour is a deliberate choice.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run webhooks in a dedicated namespace whose NetworkPolicy admits only traffic from the API server.",
      "@language": "en-GB"
     },
     {
      "@value": "Set failurePolicy to Fail for security webhooks, scope them with namespace and object selectors, and alert when a webhook times out.",
      "@language": "en-GB"
     },
     {
      "@value": "Pin webhook images by digest, grant them only the permissions they use, and patch them on the same clock as the control plane.",
      "@language": "en-GB"
     },
     {
      "@value": "Prefer in-process ValidatingAdmissionPolicy where a rule can be written in CEL, removing both a network hop and a privileged service.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: IngressNightmare, CVE-2025-1974 (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/234.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/636.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/234.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/636.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·J",
   "skos:prefLabel": {
    "@value": "Admission Policy Absent",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Nothing at admission blocks privileged pods, host mounts, untrusted registries or unsigned images.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The cluster refuses workloads that break its security baseline, whoever or whatever submits them.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enforce Pod Security Admission at the restricted level on every namespace, with a lower level only under a reviewed exemption.",
      "@language": "en-GB"
     },
     {
      "@value": "Admit images only from allowed registries, by digest, carrying a signature and provenance from the expected build identity (see PV).",
      "@language": "en-GB"
     },
     {
      "@value": "Grant exemptions per namespace in version-controlled policy with an owner and an expiry, and report them on a schedule.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/233.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/693.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/233.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/693.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·10",
   "skos:prefLabel": {
    "@value": "Cluster Secrets Exposure",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Secrets sit unencrypted in etcd, readable by broad roles and copied into many namespaces.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Secrets are encrypted at rest under a key held outside the cluster, and readable only by the workloads that use them.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable etcd encryption at rest with a KMS provider, so the key encryption key never sits on control plane disks.",
      "@language": "en-GB"
     },
     {
      "@value": "Grant get and list on secrets only to named service accounts in their own namespace, and remove secret access from broad roles.",
      "@language": "en-GB"
     },
     {
      "@value": "Scope secret operators and external secret controllers to the namespaces they serve, instead of copying secrets across the cluster.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/639.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/639.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/312.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/312.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·9",
   "skos:prefLabel": {
    "@value": "Operator Privilege",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Operators and controllers run with cluster-admin to manage resources, so one compromised controller owns the cluster.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A controller holds only the permissions for the resources and namespaces it manages.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Install operators in namespaced mode where supported, with Roles limited to the resource types they reconcile.",
      "@language": "en-GB"
     },
     {
      "@value": "Review the RBAC each third-party operator requests before install, and pin its image and manifests by digest.",
      "@language": "en-GB"
     },
     {
      "@value": "Run operators on system node pools away from tenant workloads, and audit their API calls for actions outside their declared purpose.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/234.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/234.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·8",
   "skos:prefLabel": {
    "@value": "Hostile Chart or Manifest",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Charts from public repositories carry unexpected RBAC, hooks or images.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "What is installed in the cluster is rendered output someone reviewed, from a chart whose origin is verified.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Mirror third-party charts into an internal repository, pin each by version and digest, and verify its signature or provenance file.",
      "@language": "en-GB"
     },
     {
      "@value": "Render charts in CI and review the full manifest diff, including RBAC, CRDs and images, before every install or upgrade.",
      "@language": "en-GB"
     },
     {
      "@value": "Disable chart hooks unless allow-listed, and apply the same admission policy to hook jobs as to any other workload.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·7",
   "skos:prefLabel": {
    "@value": "Flat Cluster Network",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "With no network policies, any pod reaches any other pod, the control plane and the metadata service.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Pods reach only the services they are meant to call, and every other path is closed by default.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Apply a default-deny ingress and egress NetworkPolicy to every namespace, then allow named flows.",
      "@language": "en-GB"
     },
     {
      "@value": "Block pod egress to the cloud metadata service and the API server, except for workloads that need them.",
      "@language": "en-GB"
     },
     {
      "@value": "Encrypt traffic between workloads with mutual TLS from a service mesh or the network plugin.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·6",
   "skos:prefLabel": {
    "@value": "Namespace as Tenant Boundary",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Teams or customers are separated only by namespace, while sharing nodes, CRDs and cluster-scoped resources.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Tenants who might be hostile to each other share nothing that one can read or change on the other's behalf.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Deny tenants the right to create cluster-scoped resources such as CRDs, ClusterRoles and webhook configurations.",
      "@language": "en-GB"
     },
     {
      "@value": "Place mutually untrusted tenants on separate clusters, or at the least on dedicated node pools with sandboxed runtimes.",
      "@language": "en-GB"
     },
     {
      "@value": "List what tenants share in each cluster, including nodes, CRDs, ingress controllers and DNS, and review the list whenever a tenant is added.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/124.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/124.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·5",
   "skos:prefLabel": {
    "@value": "Node to Cluster Escalation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "A compromised node's credentials read secrets for pods on other nodes or change objects beyond the node.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A node's credentials allow only the actions needed for the pods scheduled on that node.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable the Node authoriser and the NodeRestriction admission plugin, so a kubelet can read only secrets for pods bound to it.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep privileged workloads such as controllers and CI runners off nodes that run untrusted pods.",
      "@language": "en-GB"
     },
     {
      "@value": "Replace nodes after a short maximum lifetime from immutable images, and rotate kubelet certificates automatically.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/233.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1220.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1220.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·4",
   "skos:prefLabel": {
    "@value": "Service Account Token Abuse",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Default service accounts with automounted tokens are usable from any compromised pod.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Pods carry an API credential only when they need one, and that credential is short-lived and narrowly scoped.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Set automountServiceAccountToken to false on every default service account, and enable it per workload only where needed.",
      "@language": "en-GB"
     },
     {
      "@value": "Use projected service-account tokens with a short expiry and a bound audience, and remove legacy long-lived token secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Bind no roles to default service accounts, and check that in policy for every namespace.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/150.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1188.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/560.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1188.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·3",
   "skos:prefLabel": {
    "@value": "Audit Logging Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "API audit logging is off, too coarse or kept on the cluster, so actions cannot be reconstructed.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every change to the cluster can be reconstructed from records that the cluster's own administrators cannot rewrite.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Enable API server audit logging with a policy that records metadata for all requests and full request bodies for RBAC, workload and exec changes.",
      "@language": "en-GB"
     },
     {
      "@value": "Ship audit events as they are written to an external store under separate administration.",
      "@language": "en-GB"
     },
     {
      "@value": "Alert when audit events stop arriving, when the audit policy changes, or when event objects are deleted in bulk.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/571.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/268.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/orchestration/#or-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
   },
   "skos:notation": "OR·2",
   "skos:prefLabel": {
    "@value": "Version Lag",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Clusters and add-ons run unsupported versions with known flaws.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Clusters and their add-ons stay within supported versions on a planned schedule rather than one forced by an incident.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Upgrade clusters on a fixed cadence that keeps each within the upstream support window, replacing nodes as part of each upgrade.",
      "@language": "en-GB"
     },
     {
      "@value": "Inventory add-ons such as ingress controllers, CNI plugins, CSI drivers and operators with their versions, and track their advisories.",
      "@language": "en-GB"
     },
     {
      "@value": "Check manifests for deprecated APIs in CI before each upgrade, and fail on any API removed in the next version.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/310.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/310.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1104.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1104.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1395.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "DL",
   "skos:prefLabel": {
    "@value": "Delivery and Deployment",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The last hop decides what actually runs, and every earlier control is worth only what this hop enforces. These cards cover CD tools, GitOps controllers, promotion, environments, approvals, rollback and release channels.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "CD tools, GitOps controllers, promotion, environments, approvals, rollback",
    "@language": "en-GB"
   },
   "ost:unit": "station",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-a"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-k"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-q"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-j"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-2"
    }
   ],
   "ost:position": 17,
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/#line-2"
   },
   "skos:related": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-a",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·A",
   "skos:prefLabel": {
    "@value": "GitOps Repository as Production",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Whoever can write to the repository a GitOps controller syncs from controls production, and it is often protected less than application code.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The repository a controller syncs from is protected as production access, and the controller applies only changes it can attribute.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Protect the synced branch with required review by production owners and no bypass for administrators.",
      "@language": "en-GB"
     },
     {
      "@value": "Require signed commits, and configure the GitOps controller to verify signatures against an allowed key set before syncing.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep configuration repositories separate from application repositories, with membership no wider than the group that holds production access.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/445.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/445.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/732.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-k",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·K",
   "skos:prefLabel": {
    "@value": "CD Controller Compromise",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The CD controller holds credentials for every cluster and environment, so a flaw or an exposed console hands over all of them.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "No single delivery component holds every environment's credentials, and its interfaces are guarded as closely as the environments it reaches.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run a CD controller per environment or cluster that pulls from inside its target, so no central instance holds credentials for all of them.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep the controller's console and API off the internet, and federate administrator access through single sign-on with MFA.",
      "@language": "en-GB"
     },
     {
      "@value": "Patch the controller on a defined clock, and give its service account rights only in the namespaces it deploys to.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Argo CD CVE-2022-24348 (2022).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/180.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/180.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-q",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·Q",
   "skos:prefLabel": {
    "@value": "Promotion Without Re-verification",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "An artifact reaches production by rebuild, retag or a different digest, so what was tested is not what ships.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Promotion moves one immutable artifact between environments, and each environment verifies it again before it runs.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Promote by digest, referencing the exact image that passed earlier stages, and forbid rebuilds in promotion pipelines.",
      "@language": "en-GB"
     },
     {
      "@value": "Record test results as attestations bound to the digest, so a different digest carries no evidence to pass on.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify signature, provenance and test attestations for the digest at each environment's admission (see PV).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/367.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/29.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/367.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-j",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·J",
   "skos:prefLabel": {
    "@value": "Approval Bypass",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Deployment approvals can be skipped by direct API calls, re-runs, admin override or self-approval.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Approval is enforced by the deploy target, which accepts only changes carrying a valid approval from someone other than the requester.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Issue approvals as signed attestations that the deploy target or its admission controller verifies, not as a step in the pipeline's interface.",
      "@language": "en-GB"
     },
     {
      "@value": "Reject approvals from the person who authored or triggered the change, and require fresh approval for any re-run or changed input.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove administrator override from deployment environments, or treat each use as a break-glass event that alerts the owning team.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/207.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/36.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/841.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/207.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/841.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·10",
   "skos:prefLabel": {
    "@value": "Direct-to-Production Path",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Engineers and tools hold standing access to deploy outside the pipeline.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "The pipeline is the only standing route to production, and any other access is temporary, recorded and reconciled.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Remove standing write access to production from people and tools, and grant it just in time with approval and an expiry.",
      "@language": "en-GB"
     },
     {
      "@value": "Log every break-glass session, alert the owning team, and review each one afterwards.",
      "@language": "en-GB"
     },
     {
      "@value": "Configure the GitOps controller to detect and revert out-of-band changes, and alert on every revert.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/554.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/554.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/424.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/424.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/266.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·9",
   "skos:prefLabel": {
    "@value": "Release Channel Hijack",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "The update server, download page, CDN or update channel that delivers software to customers is compromised.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Clients trust an update because they have verified its signature and freshness, not because of where it came from.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Sign every release with a key held in an HSM, and have clients verify the signature before installing.",
      "@language": "en-GB"
     },
     {
      "@value": "Protect update metadata with TUF or an equivalent scheme, using separate roles, threshold signing and expiry to resist freeze, rollback and mix-and-match attacks.",
      "@language": "en-GB"
     },
     {
      "@value": "Hold the download domain, DNS and CDN accounts under dedicated MFA-protected identities, and monitor for changes to records and published files.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:example": {
    "@value": "Seen in: 3CX (2023); Polyfill.io (2024).",
    "@language": "en-GB"
   },
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/669.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/186.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/347.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/669.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·8",
   "skos:prefLabel": {
    "@value": "Environment Boundary Leak",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Staging and production share clusters, credentials, networks or data, so compromising staging reaches production.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Lower environments share nothing with production that would let a compromise of one reach the other.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Give each environment its own cloud accounts, clusters, credentials and network, with no routes from staging into production.",
      "@language": "en-GB"
     },
     {
      "@value": "Issue pipeline identities per environment, so production refuses the credentials of a staging job.",
      "@language": "en-GB"
     },
     {
      "@value": "Use synthetic or masked data in lower environments, and block automated copying of production data into them.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/124.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/124.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·7",
   "skos:prefLabel": {
    "@value": "Flag and Remote Config Tampering",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Feature flags and remote configuration change production behaviour without a code change or review.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Changes to production behaviour through flags or remote configuration are reviewed, attributable and reversible, like code changes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Restrict production flag and configuration changes to named roles, and require a second approver for flags that enable features or relax controls.",
      "@language": "en-GB"
     },
     {
      "@value": "Write every flag change to an immutable audit log with actor, time, old value and new value.",
      "@language": "en-GB"
     },
     {
      "@value": "Remove code behind retired flags, and treat activation of any flag that gates dormant code as a release.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/176.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/15.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/912.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/176.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/15.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·6",
   "skos:prefLabel": {
    "@value": "Values and Overlay Injection",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Values files and overlays from contributors or tenants inject arbitrary manifests at render time.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Contributors and tenants set only declared values, and what renders is checked as the manifest it really is.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Define a schema for each chart's values, and reject undeclared keys or types, including raw YAML blocks.",
      "@language": "en-GB"
     },
     {
      "@value": "Never pass tenant-supplied strings through template functions such as tpl, so a value cannot become markup.",
      "@language": "en-GB"
     },
     {
      "@value": "Validate the fully rendered manifests against admission policy in CI before they reach the controller.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/77.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/153.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/77.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1336.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/1336.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/915.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·5",
   "skos:prefLabel": {
    "@value": "Rollback to Vulnerable Version",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Rollback restores a version with a known vulnerability, or an attacker forces a downgrade.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "A rollback is a deployment like any other, subject to the same vulnerability policy and authorisation.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Maintain a deny list of digests with known critical vulnerabilities, and reject them at admission whether deployed forward or back.",
      "@language": "en-GB"
     },
     {
      "@value": "Limit rollback to the roles that can approve deployments, and log each one with its target version.",
      "@language": "en-GB"
     },
     {
      "@value": "Keep a patched recent version available as the rollback target, so restoring service does not mean restoring a known flaw.",
      "@language": "en-GB"
     },
     {
      "@value": "Enforce version monotonicity in update clients, so an older signed release cannot be served as an update (see DL·9).",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/166.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1328.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/166.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1328.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·4",
   "skos:prefLabel": {
    "@value": "Canary Blind Spot",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Progressive rollout watches availability, not security signals, so a malicious build passes the canary.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Progressive rollout judges a build on its security behaviour as well as its health, and its stages cannot be skipped quietly.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Include security signals in canary analysis, such as new outbound destinations, unexpected processes and shifts in authentication errors.",
      "@language": "en-GB"
     },
     {
      "@value": "Compare a build's runtime behaviour with a baseline from previous releases, because a malicious build can keep its error rate normal.",
      "@language": "en-GB"
     },
     {
      "@value": "Require approval to skip or shorten rollout stages, and record each skip with the actor and the reason.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·3",
   "skos:prefLabel": {
    "@value": "Deployment Record Gap",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "There is no reliable record of what was deployed where, when and by whom.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "What runs where is answerable from a record that the deploying systems write but cannot change.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Emit a deployment record with digest, environment, actor, approval and time from the deploy target rather than from the pipeline.",
      "@language": "en-GB"
     },
     {
      "@value": "Write deployment records to an append-only store outside the delivery platform.",
      "@language": "en-GB"
     },
     {
      "@value": "Join deployment records with live cluster inventory, so a query for a digest or version returns every location within minutes.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/268.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/778.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/778.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/#dl-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
   },
   "skos:notation": "DL·2",
   "skos:prefLabel": {
    "@value": "Orphaned Preview Environments",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Preview and ephemeral environments outlive their purpose, running old code with real credentials.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Preview environments live only as long as the change that created them and hold nothing a stranger could use.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Tear down preview environments automatically when their pull request closes, and after a maximum age regardless.",
      "@language": "en-GB"
     },
     {
      "@value": "Give previews their own short-lived, low-privilege credentials and synthetic data, never production secrets.",
      "@language": "en-GB"
     },
     {
      "@value": "Put previews behind authentication by default, and report any that are publicly reachable each day.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "None",
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/772.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/772.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/459.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "T",
   "skos:prefLabel": {
    "@value": "Structural hazards",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "These ten hazards are properties of the software factory itself, so no single station can fix them. Apply them to the whole design after the stations.",
    "@language": "en-GB"
   },
   "skos:scopeNote": {
    "@value": "Hazards of the software factory as a whole",
    "@language": "en-GB"
   },
   "ost:unit": "structural hazards",
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t10"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t9"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t8"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t7"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t6"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t5"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t4"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t3"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t2"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t1"
    }
   ],
   "skos:topConceptOf": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t10",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T10",
   "skos:prefLabel": {
    "@value": "Transitive Trust",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Every component trusts its upstream, recursively, so the factory is as strong as the weakest link in a tree nobody has fully drawn.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Trust in an artifact rests on verification at each link the organisation can see, and the links it cannot verify are named and owned.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Draw the trust chain for each critical artifact, from source, tools, actions, base images and dependencies through to runtime, and keep it as a maintained architecture record.",
      "@language": "en-GB"
     },
     {
      "@value": "Mark on that chain where verification is enforced and where it is assumed, and give each assumption an owner.",
      "@language": "en-GB"
     },
     {
      "@value": "Identify the upstreams whose fall would reach every artifact, and give each a compensating control such as mirroring, pinning or independent verification.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: SolarWinds (2020).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/446.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t9",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T9",
   "skos:prefLabel": {
    "@value": "Names That Move",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Tags, branches, versions and \"latest\" are pointers, not contracts, and most of the factory addresses things by name.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Every hand-off between stations refers to content by an immutable identifier, and mutable names are resolved once, visibly, and on record.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Resolve tags, branches and version ranges to digests or commit hashes at one recorded point, and carry the resolved identifier through every later stage.",
      "@language": "en-GB"
     },
     {
      "@value": "Treat a moved name as an event, with update bots proposing the new digest as a reviewed change.",
      "@language": "en-GB"
     },
     {
      "@value": "Test the design by assuming every mutable name moves overnight, and list the stations that would silently run different content.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: trivy-action (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/690.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/690.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/471.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/471.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t8",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T8",
   "skos:prefLabel": {
    "@value": "The Pipeline Outranks Everyone",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Automation concentrates write access to source, registries, clouds and production in identities nobody logs in as.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Automation holds no more authority than the people who can direct it, and that authority is split so no one pipeline holds it all.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Split pipeline identities by stage and environment, so building, signing, publishing and deploying use separate credentials with separate trust policies.",
      "@language": "en-GB"
     },
     {
      "@value": "Map who can make each pipeline act, through commits, triggers, workflow edits and runner access, and keep that group no larger than the group approved for its targets.",
      "@language": "en-GB"
     },
     {
      "@value": "Require human approval or a second independent identity for actions no single person may take alone, such as publishing a release or deploying to production.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Codecov (2021).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/122.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/560.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/122.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t7",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T7",
   "skos:prefLabel": {
    "@value": "Running Strangers' Code Is the Job",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Install scripts, build plugins, actions and test suites execute third-party code by design at every stage.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Each stage decides what third-party code can reach before that code runs, because running it is unavoidable.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Run third-party code such as install scripts, plugins, actions and test suites in ephemeral sandboxes with no secrets and egress limited to the proxy.",
      "@language": "en-GB"
     },
     {
      "@value": "Separate stages that execute third-party code from stages that hold signing keys or publishing credentials, passing only digest-addressed artifacts between them.",
      "@language": "en-GB"
     },
     {
      "@value": "Inventory where third-party code executes and with which privileges, and review the inventory whenever a stage gains a secret.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/446.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Direct",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/829.html"
   },
   "skos:closeMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t6",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T6",
   "skos:prefLabel": {
    "@value": "The Guard Is Inside the Wall",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Scanners, firewalls, signers and SBOM generators run with the widest reach, so compromising a control compromises everything it protects.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Security controls meet a stricter standard than the code they check, and no single control's verdict is final.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Pin, verify and update scanners, firewalls, signers and SBOM generators through a supply chain held to the highest internal tier.",
      "@language": "en-GB"
     },
     {
      "@value": "Give each control read access to what it checks and write access only to its own results, with signing and publishing keys held elsewhere.",
      "@language": "en-GB"
     },
     {
      "@value": "Cross-check critical verdicts with an independent second control, so a control that lies is caught by disagreement.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Trivy and KICS (2026).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/670.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/578.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/250.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/654.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/670.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/250.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t5",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T5",
   "skos:prefLabel": {
    "@value": "Checked Is Not Run",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Each station checks an artifact, and the next receives something that may differ.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "One digest is carried end to end, and every check is bound to the digest it examined.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Fix the artifact digest at build and carry it unchanged through scanning, signing, promotion and admission, with no rebuild, retag or re-fetch.",
      "@language": "en-GB"
     },
     {
      "@value": "Record each check's result as an attestation over that digest, so its evidence cannot be reused for different bytes.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify at runtime admission that the digest about to run holds every attestation the policy requires.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/29.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/367.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/29.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/367.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t4",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T4",
   "skos:prefLabel": {
    "@value": "Configuration Is Code",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "YAML, HCL, Dockerfiles and policy files are executable instructions that are reviewed and owned as settings.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Files that change what executes are treated as code, with owners, review and tests to match.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Classify workflow files, Dockerfiles, IaC, Helm values and policy files as executable, and assign each a code owner.",
      "@language": "en-GB"
     },
     {
      "@value": "Enforce review of those files through code-owner rules by people who understand what the files execute.",
      "@language": "en-GB"
     },
     {
      "@value": "Lint, policy-test and diff the rendered output of configuration changes in CI, as for application code.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/75.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/35.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/75.html"
   },
   "ost:cweMatch": "None"
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t3",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T3",
   "skos:prefLabel": {
    "@value": "Self-Propagation",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Compromised output becomes someone else's input: stolen publish tokens republish, pipelines infect pipelines, and a factory becomes a worm's carrier.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Nothing is published or consumed automatically without a step that a compromised peer cannot satisfy.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Publish only through short-lived trusted-publishing identities scoped to one package, with human approval of each release, so stolen tokens cannot republish.",
      "@language": "en-GB"
     },
     {
      "@value": "Apply a cooldown before new upstream versions enter builds, giving compromised releases time to be found and withdrawn.",
      "@language": "en-GB"
     },
     {
      "@value": "Require provenance from the expected build identity on consumed packages, so output from a compromised factory without that identity is refused.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ],
   "ost:strideFit": "Loose",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: Shai-Hulud (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/442.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/494.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/829.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/494.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T2",
   "skos:prefLabel": {
    "@value": "Shared Fate",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Most factories depend on the same few platforms, registries, actions and base images, so their outages and compromises are everyone's.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Dependence on shared providers is known, verified at each use and survivable when a provider fails.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "List the external platforms, registries, actions and base images without which the factory cannot build or deploy.",
      "@language": "en-GB"
     },
     {
      "@value": "Mirror critical dependencies, images and actions internally, so builds and rollbacks continue while a provider is down.",
      "@language": "en-GB"
     },
     {
      "@value": "Verify signatures and digests on everything taken from a shared provider, so its compromise yields refused content rather than accepted content.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Partial",
   "skos:example": {
    "@value": "Seen in: tj-actions (2025).",
    "@language": "en-GB"
   },
   "skos:broadMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/538.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/1357.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/538.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/1357.html"
   }
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/#t1",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:broader": {
    "@id": "https://ostering.com/taxonomies/software-factory/structural-hazards/"
   },
   "skos:notation": "T1",
   "skos:prefLabel": {
    "@value": "Evidence Lives Where the Attacker Works",
    "@language": "en-GB"
   },
   "skos:definition": {
    "@value": "Logs, provenance, audit trails and SBOMs are stored in the systems an attacker compromises, and are rewritten or deleted with the breach.",
    "@language": "en-GB"
   },
   "ost:mitigationPrinciple": {
    "@value": "Evidence is written to an independent store as it is produced, under administrators who cannot change the systems it describes.",
    "@language": "en-GB"
   },
   "ost:designMeasure": {
    "@list": [
     {
      "@value": "Stream logs, audit trails, provenance and SBOMs to an append-only store in a separate account with separate administrators.",
      "@language": "en-GB"
     },
     {
      "@value": "Record signatures and attestations in a transparency log, so later deletion or rewriting is detectable.",
      "@language": "en-GB"
     },
     {
      "@value": "Retain the inputs needed to reconstruct a past build, such as source commits, lockfiles and base digests, and test a reconstruction periodically.",
      "@language": "en-GB"
     }
    ]
   },
   "ost:stride": [
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    }
   ],
   "ost:strideFit": "Clean",
   "ost:capecMatch": "Direct",
   "skos:closeMatch": [
    {
     "@id": "https://capec.mitre.org/data/definitions/268.html"
    },
    {
     "@id": "https://capec.mitre.org/data/definitions/571.html"
    }
   ],
   "ost:capecBestFit": {
    "@id": "https://capec.mitre.org/data/definitions/268.html"
   },
   "ost:cweMatch": "Partial",
   "ost:cweBestFit": {
    "@id": "https://cwe.mitre.org/data/definitions/653.html"
   },
   "skos:broadMatch": [
    {
     "@id": "https://cwe.mitre.org/data/definitions/653.html"
    },
    {
     "@id": "https://cwe.mitre.org/data/definitions/732.html"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/#line-1",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "L1",
   "skos:prefLabel": {
    "@value": "Line 1, Source to Artifact",
    "@language": "en-GB"
   },
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/workstation-and-agents/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/version-control/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-definition/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/runners/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/pipeline-identity-and-secrets/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/build-systems/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/dependency-resolution/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/scanners-and-gates/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/provenance-and-attestation/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/taxonomies/software-factory/#line-2",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/taxonomies/software-factory/"
   },
   "skos:notation": "L2",
   "skos:prefLabel": {
    "@value": "Line 2, Artifact to Runtime",
    "@language": "en-GB"
   },
   "skos:narrower": [
    {
     "@id": "https://ostering.com/taxonomies/software-factory/registries/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/firewall-and-quarantine/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/sbom-and-vex/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/infrastructure-as-code/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-images/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/container-runtime/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/orchestration/"
    },
    {
     "@id": "https://ostering.com/taxonomies/software-factory/delivery-and-deployment/"
    }
   ]
  },
  {
   "@id": "https://ostering.com/ns/stride#",
   "@type": "skos:ConceptScheme",
   "dcterms:title": {
    "@value": "STRIDE threat categories",
    "@language": "en-GB"
   },
   "skos:hasTopConcept": [
    {
     "@id": "https://ostering.com/ns/stride#Spoofing"
    },
    {
     "@id": "https://ostering.com/ns/stride#Tampering"
    },
    {
     "@id": "https://ostering.com/ns/stride#Repudiation"
    },
    {
     "@id": "https://ostering.com/ns/stride#Informationdisclosure"
    },
    {
     "@id": "https://ostering.com/ns/stride#Denialofservice"
    },
    {
     "@id": "https://ostering.com/ns/stride#Elevationofprivilege"
    }
   ]
  },
  {
   "@id": "https://ostering.com/ns/stride#Spoofing",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "S",
   "skos:prefLabel": {
    "@value": "Spoofing",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/stride#Tampering",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "T",
   "skos:prefLabel": {
    "@value": "Tampering",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/stride#Repudiation",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "R",
   "skos:prefLabel": {
    "@value": "Repudiation",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/stride#Informationdisclosure",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "I",
   "skos:prefLabel": {
    "@value": "Information disclosure",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/stride#Denialofservice",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "D",
   "skos:prefLabel": {
    "@value": "Denial of service",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/stride#Elevationofprivilege",
   "@type": "skos:Concept",
   "skos:inScheme": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:topConceptOf": {
    "@id": "https://ostering.com/ns/stride#"
   },
   "skos:notation": "E",
   "skos:prefLabel": {
    "@value": "Elevation of privilege",
    "@language": "en-GB"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#mitigationPrinciple",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "mitigationPrinciple",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "What a sound design does about the threat, stated so that different designs can satisfy it in different ways.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#designMeasure",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "designMeasure",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "An ordered list of concrete ways of satisfying the mitigation principle; examples, not the only acceptable answers.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#stride",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "stride",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The STRIDE categories the threat belongs to, best fit first.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#strideFit",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "strideFit",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "Clean: a STRIDE prompt would plausibly find this threat. Loose: STRIDE gives a label but not the question that finds it.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#capecMatch",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "capecMatch",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The rating for the entry's CAPEC 3.9 patterns as a whole. Direct: the best-fit pattern (ost:capecBestFit) describes the threat, and the patterns are linked with skos:closeMatch. Partial: only a generic parent pattern applies, linked with skos:broadMatch. None: no pattern.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#cweMatch",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "cweMatch",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The rating for the entry's CWE 4.20 weaknesses as a whole. Direct: the best-fit weakness (ost:cweBestFit) names the flaw, and any others cover further aspects of it; all are linked with skos:closeMatch. Partial: only a broader or adjacent weakness applies, linked with skos:broadMatch. None: no CWE weakness names it.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#capecBestFit",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "capecBestFit",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The CAPEC pattern that fits the entry best, first of its list.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#cweBestFit",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "cweBestFit",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The CWE weakness that fits the entry best, first of its list; for a Direct match, the one that names the flaw.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#position",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "position",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "The group's place in the sequence of layers or stations.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  },
  {
   "@id": "https://ostering.com/ns/taxonomy#unit",
   "@type": "rdf:Property",
   "rdfs:label": {
    "@value": "unit",
    "@language": "en-GB"
   },
   "rdfs:comment": {
    "@value": "What a group is in this taxonomy: a layer, a station, or the structural hazards.",
    "@language": "en-GB"
   },
   "rdfs:isDefinedBy": {
    "@id": "https://ostering.com/ns/taxonomy#"
   }
  }
 ]
}