505 lines
14 KiB
JSON
505 lines
14 KiB
JSON
{
|
|
"$defs": {
|
|
"Asset": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "Unique identifier, e.g. 'A-01'.",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"description": {
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"classification": {
|
|
"$ref": "#/$defs/DataClassification"
|
|
},
|
|
"location": {
|
|
"description": "Where stored/processed, e.g. 'RDS PostgreSQL', 'S3 bucket prod-lab-pdfs'.",
|
|
"title": "Location",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name",
|
|
"description",
|
|
"classification",
|
|
"location"
|
|
],
|
|
"title": "Asset",
|
|
"type": "object"
|
|
},
|
|
"DataClassification": {
|
|
"enum": [
|
|
"Public",
|
|
"Internal",
|
|
"Confidential",
|
|
"Restricted"
|
|
],
|
|
"title": "DataClassification",
|
|
"type": "string"
|
|
},
|
|
"DataFlow": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "Unique identifier, e.g. 'DF-01'.",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"source": {
|
|
"description": "Originating component.",
|
|
"title": "Source",
|
|
"type": "string"
|
|
},
|
|
"destination": {
|
|
"description": "Receiving component.",
|
|
"title": "Destination",
|
|
"type": "string"
|
|
},
|
|
"data_classification": {
|
|
"$ref": "#/$defs/DataClassification"
|
|
},
|
|
"protocol": {
|
|
"description": "Concrete protocol, e.g. 'HTTPS', 'MQTT/TLS', 'gRPC', 'AMQP'.",
|
|
"title": "Protocol",
|
|
"type": "string"
|
|
},
|
|
"crosses_boundary": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "ID of the TrustBoundary this flow crosses, if any.",
|
|
"title": "Crosses Boundary"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"source",
|
|
"destination",
|
|
"data_classification",
|
|
"protocol"
|
|
],
|
|
"title": "DataFlow",
|
|
"type": "object"
|
|
},
|
|
"Mitigation": {
|
|
"properties": {
|
|
"description": {
|
|
"description": "Specific, actionable control. Must reference a concrete technology, configuration, or process \u2014 not a generic category. Bad: 'use encryption'. Good: 'enable TLS 1.3 with mutual auth on the MQTT broker using AWS IoT Core device certificates'.",
|
|
"minLength": 15,
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"type": {
|
|
"$ref": "#/$defs/MitigationType"
|
|
},
|
|
"priority": {
|
|
"$ref": "#/$defs/MitigationPriority"
|
|
},
|
|
"references": {
|
|
"anyOf": [
|
|
{
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional references: OWASP/NIST/CIS control IDs or doc links.",
|
|
"title": "References"
|
|
}
|
|
},
|
|
"required": [
|
|
"description",
|
|
"type",
|
|
"priority"
|
|
],
|
|
"title": "Mitigation",
|
|
"type": "object"
|
|
},
|
|
"MitigationPriority": {
|
|
"enum": [
|
|
"P0",
|
|
"P1",
|
|
"P2"
|
|
],
|
|
"title": "MitigationPriority",
|
|
"type": "string"
|
|
},
|
|
"MitigationType": {
|
|
"enum": [
|
|
"Preventive",
|
|
"Detective",
|
|
"Corrective",
|
|
"Deterrent"
|
|
],
|
|
"title": "MitigationType",
|
|
"type": "string"
|
|
},
|
|
"PwnismsDomain": {
|
|
"description": "The seven PWNISMS domains. All seven must be addressed in every model.",
|
|
"enum": [
|
|
"Product",
|
|
"Workload",
|
|
"Network",
|
|
"IAM",
|
|
"Secrets",
|
|
"Monitoring",
|
|
"SupplyChain"
|
|
],
|
|
"title": "PwnismsDomain",
|
|
"type": "string"
|
|
},
|
|
"PwnismsDomainCoverage": {
|
|
"properties": {
|
|
"domain": {
|
|
"$ref": "#/$defs/PwnismsDomain"
|
|
},
|
|
"addressed": {
|
|
"description": "True if threats in this domain were identified; False if N/A.",
|
|
"title": "Addressed",
|
|
"type": "boolean"
|
|
},
|
|
"threat_ids": {
|
|
"description": "IDs of threats belonging to this domain (if addressed=True).",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Threat Ids",
|
|
"type": "array"
|
|
},
|
|
"justification_if_not_applicable": {
|
|
"anyOf": [
|
|
{
|
|
"type": "string"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Required when addressed=False. Must explain why the domain is not relevant to this specific system. Never leave domains unaddressed without justification.",
|
|
"title": "Justification If Not Applicable"
|
|
}
|
|
},
|
|
"required": [
|
|
"domain",
|
|
"addressed"
|
|
],
|
|
"title": "PwnismsDomainCoverage",
|
|
"type": "object"
|
|
},
|
|
"RiskLevel": {
|
|
"enum": [
|
|
"High",
|
|
"Medium",
|
|
"Low"
|
|
],
|
|
"title": "RiskLevel",
|
|
"type": "string"
|
|
},
|
|
"Scope": {
|
|
"properties": {
|
|
"in_scope": {
|
|
"description": "Components, flows, or features being threat-modeled.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"minItems": 1,
|
|
"title": "In Scope",
|
|
"type": "array"
|
|
},
|
|
"out_of_scope": {
|
|
"description": "Explicitly excluded elements.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Out Of Scope",
|
|
"type": "array"
|
|
},
|
|
"assumptions": {
|
|
"description": "Assumptions that, if invalidated, would change the model.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Assumptions",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"in_scope"
|
|
],
|
|
"title": "Scope",
|
|
"type": "object"
|
|
},
|
|
"SecurityObjective": {
|
|
"enum": [
|
|
"Confidentiality",
|
|
"Integrity",
|
|
"Availability",
|
|
"Authenticity",
|
|
"NonRepudiation",
|
|
"Authorization",
|
|
"Privacy"
|
|
],
|
|
"title": "SecurityObjective",
|
|
"type": "string"
|
|
},
|
|
"StrideCategory": {
|
|
"description": "Optional STRIDE cross-categorization per threat.",
|
|
"enum": [
|
|
"Spoofing",
|
|
"Tampering",
|
|
"Repudiation",
|
|
"InformationDisclosure",
|
|
"DenialOfService",
|
|
"ElevationOfPrivilege"
|
|
],
|
|
"title": "StrideCategory",
|
|
"type": "string"
|
|
},
|
|
"Threat": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "Unique identifier, e.g. 'T-01'.",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"title": {
|
|
"description": "Short title of the threat.",
|
|
"maxLength": 120,
|
|
"title": "Title",
|
|
"type": "string"
|
|
},
|
|
"pwnisms_domain": {
|
|
"$ref": "#/$defs/PwnismsDomain",
|
|
"description": "Primary PWNISMS domain this threat belongs to."
|
|
},
|
|
"stride_category": {
|
|
"anyOf": [
|
|
{
|
|
"$ref": "#/$defs/StrideCategory"
|
|
},
|
|
{
|
|
"type": "null"
|
|
}
|
|
],
|
|
"default": null,
|
|
"description": "Optional STRIDE cross-categorization for this threat."
|
|
},
|
|
"affected_component": {
|
|
"description": "The component under threat. Must be a component that appears in or is directly implied by the input system description \u2014 do not invent components not present in the scenario.",
|
|
"title": "Affected Component",
|
|
"type": "string"
|
|
},
|
|
"affected_asset_ids": {
|
|
"description": "IDs of assets impacted (referencing Asset.id).",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Affected Asset Ids",
|
|
"type": "array"
|
|
},
|
|
"description": {
|
|
"description": "What could go wrong. 2\u20134 sentences, concrete and specific.",
|
|
"minLength": 50,
|
|
"title": "Description",
|
|
"type": "string"
|
|
},
|
|
"attack_vector": {
|
|
"description": "How an attacker realistically exploits this threat.",
|
|
"minLength": 20,
|
|
"title": "Attack Vector",
|
|
"type": "string"
|
|
},
|
|
"preconditions": {
|
|
"description": "What must be true for this threat to be exploitable.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Preconditions",
|
|
"type": "array"
|
|
},
|
|
"security_objectives_violated": {
|
|
"items": {
|
|
"$ref": "#/$defs/SecurityObjective"
|
|
},
|
|
"minItems": 1,
|
|
"title": "Security Objectives Violated",
|
|
"type": "array"
|
|
},
|
|
"likelihood": {
|
|
"$ref": "#/$defs/RiskLevel"
|
|
},
|
|
"likelihood_rationale": {
|
|
"minLength": 20,
|
|
"title": "Likelihood Rationale",
|
|
"type": "string"
|
|
},
|
|
"impact": {
|
|
"$ref": "#/$defs/RiskLevel"
|
|
},
|
|
"impact_rationale": {
|
|
"minLength": 20,
|
|
"title": "Impact Rationale",
|
|
"type": "string"
|
|
},
|
|
"mitigations": {
|
|
"description": "At least one concrete mitigation per threat.",
|
|
"items": {
|
|
"$ref": "#/$defs/Mitigation"
|
|
},
|
|
"minItems": 1,
|
|
"title": "Mitigations",
|
|
"type": "array"
|
|
},
|
|
"residual_risk": {
|
|
"description": "Risk that remains after mitigations are applied.",
|
|
"title": "Residual Risk",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"title",
|
|
"pwnisms_domain",
|
|
"affected_component",
|
|
"description",
|
|
"attack_vector",
|
|
"security_objectives_violated",
|
|
"likelihood",
|
|
"likelihood_rationale",
|
|
"impact",
|
|
"impact_rationale",
|
|
"mitigations",
|
|
"residual_risk"
|
|
],
|
|
"title": "Threat",
|
|
"type": "object"
|
|
},
|
|
"TrustBoundary": {
|
|
"properties": {
|
|
"id": {
|
|
"description": "Unique identifier, e.g. 'TB-01'.",
|
|
"title": "Id",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"description": "Short name, e.g. 'Internet to API Gateway'.",
|
|
"title": "Name",
|
|
"type": "string"
|
|
},
|
|
"between": {
|
|
"description": "The two sides of the boundary: [outside, inside].",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"maxItems": 2,
|
|
"minItems": 2,
|
|
"title": "Between",
|
|
"type": "array"
|
|
},
|
|
"description": {
|
|
"title": "Description",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"id",
|
|
"name",
|
|
"between",
|
|
"description"
|
|
],
|
|
"title": "TrustBoundary",
|
|
"type": "object"
|
|
}
|
|
},
|
|
"description": "A PWNISMS threat model for the system described in the input scenario.\n\nFill every field. Every one of the seven PWNISMS domains must appear in\n`pwnisms_coverage` \u2014 either with threats, or with an explicit N/A\njustification. No silent omissions.",
|
|
"properties": {
|
|
"system_summary": {
|
|
"description": "2\u20134 sentence summary of the system being threat-modeled.",
|
|
"maxLength": 800,
|
|
"minLength": 50,
|
|
"title": "System Summary",
|
|
"type": "string"
|
|
},
|
|
"scope": {
|
|
"$ref": "#/$defs/Scope"
|
|
},
|
|
"assets": {
|
|
"description": "Named information/system assets worth protecting.",
|
|
"items": {
|
|
"$ref": "#/$defs/Asset"
|
|
},
|
|
"title": "Assets",
|
|
"type": "array"
|
|
},
|
|
"trust_boundaries": {
|
|
"description": "At least one trust boundary must be identified.",
|
|
"items": {
|
|
"$ref": "#/$defs/TrustBoundary"
|
|
},
|
|
"minItems": 1,
|
|
"title": "Trust Boundaries",
|
|
"type": "array"
|
|
},
|
|
"data_flows": {
|
|
"description": "Key data flows, especially those crossing trust boundaries.",
|
|
"items": {
|
|
"$ref": "#/$defs/DataFlow"
|
|
},
|
|
"title": "Data Flows",
|
|
"type": "array"
|
|
},
|
|
"threats": {
|
|
"description": "Identified threats. Typical count: 8\u201325 depending on system complexity. Each threat must be tagged with a PWNISMS domain.",
|
|
"items": {
|
|
"$ref": "#/$defs/Threat"
|
|
},
|
|
"minItems": 5,
|
|
"title": "Threats",
|
|
"type": "array"
|
|
},
|
|
"pwnisms_coverage": {
|
|
"description": "One entry per PWNISMS domain. All seven domains must be present. Domains without identified threats must carry an explicit justification for why they do not apply to this system.",
|
|
"items": {
|
|
"$ref": "#/$defs/PwnismsDomainCoverage"
|
|
},
|
|
"title": "Pwnisms Coverage",
|
|
"type": "array"
|
|
},
|
|
"open_questions": {
|
|
"description": "Ambiguities or missing information in the scenario that would materially affect the threat model if resolved.",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"title": "Open Questions",
|
|
"type": "array"
|
|
}
|
|
},
|
|
"required": [
|
|
"system_summary",
|
|
"scope",
|
|
"trust_boundaries",
|
|
"threats",
|
|
"pwnisms_coverage"
|
|
],
|
|
"title": "ThreatModel",
|
|
"type": "object"
|
|
}
|