{ "$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" }