Pormenjen naicn rendovanja podatak iz template, popunjeni ceo dokument

This commit is contained in:
2025-04-18 16:29:07 +02:00
parent fc29671331
commit 31d679d9cf
7 changed files with 753 additions and 142 deletions

View File

@@ -0,0 +1,87 @@
from django.template import Template, Context
import re
def render_universal_segment(segment, context_data):
segment_type = segment.get('segment_type', 'unknown')
raw_content = segment.get('content')
if raw_content is None:
content = []
elif isinstance(raw_content, dict):
content = [raw_content]
elif isinstance(raw_content, list):
content = raw_content
else:
content = [raw_content]
rendered = []
context = Context(context_data)
for item in content:
if not isinstance(item, dict):
continue
title = Template(item.get('title', '')).render(context)
subtitle = Template(item.get('subtitle', '')).render(context)
description = Template(item.get('description', '')).render(context)
if title:
rendered.append(f'<h2 style="color: #2c3e50; margin-top: 30px;">{title}</h2>')
if subtitle:
rendered.append(f'<h3 style="color: #34495e; margin-top: 20px;">{subtitle}</h3>')
if description:
processed_desc = []
in_list = False
for line in description.split('\n'):
line = line.strip()
if re.match(r'^[-•*]\s', line):
if not in_list:
processed_desc.append('<ul style="list-style-type: disc; margin-left: 20px;">')
in_list = True
processed_desc.append(f'<li>{line[2:].strip()}</li>')
else:
if in_list:
processed_desc.append('</ul>')
in_list = False
if line:
processed_desc.append(f'<p style="margin: 10px 0; line-height: 1.6;">{line}</p>')
if in_list:
processed_desc.append('</ul>')
rendered.append('\n'.join(processed_desc))
if 'headers' in item and 'rows' in item:
table_html = ['<table class="report-table" style="width: 100%; border-collapse: collapse; margin: 20px 0;">']
table_html.append('<thead><tr>')
for header in item['headers']:
table_html.append(f'<th style="border: 1px solid #ddd; padding: 8px; text-align: left;">{Template(header).render(context)}</th>')
table_html.append('</tr></thead><tbody>')
for row in item['rows']:
table_html.append('<tr>')
for cell in row:
cell_content = Template(cell).render(context) if isinstance(cell, str) else ', '.join([Template(str(c)).render(context) for c in cell])
table_html.append(f'<td style="border: 1px solid #ddd; padding: 8px;">{cell_content}</td>')
table_html.append('</tr>')
table_html.append('</tbody></table>')
rendered.append('\n'.join(table_html))
if 'image' in item:
image_url = Template(item['image']).render(context)
rendered.append(f'<img src="{image_url}" alt="{title}" style="max-width: 100%; height: auto; margin: 20px 0;">')
if 'html' in segment:
html_template = Template(segment['html'])
rendered_html = html_template.render(context)
rendered.append(rendered_html)
return '\n'.join(rendered)
def render_template(template_segments, context_data):
final_output = []
for segment in template_segments:
segment_html = render_universal_segment(segment, context_data)
final_output.append(f'<div class="segment {segment.get("segment_type", "")}">{segment_html}</div>')
return '\n'.join(final_output)

108
backend/core/tables.py Normal file
View File

@@ -0,0 +1,108 @@
from backend.core.models import DocumentRiskControl
from backend.core.utils import calculate_aggregate_likelihood, calculate_aggregate_weight, map_weight_to_impact_likelihood
def risk_matrix_table():
likelihood_labels = [
"Certain (90-100%)",
"Almost Certain (80-89%)",
"Very Probable (70-79%)",
"Probable (60-69%)",
"Highly Likely (50-59%)",
"Likely (40-49%)",
"Occasional (30-39%)",
"Possible (20-29%)",
"Unlikely (10-19%)",
"Rare (0-9%)"
]
impact_labels = [
"Insignificant",
"Minor",
"Moderate",
"Major",
"Severe",
"Catastrophic",
"Critical",
"Extreme",
"Disastrous",
"Unrecoverable"
]
color_mapping = {
"Very Low": "green",
"Low": "lightgreen",
"Medium": "yellow",
"High": "orange",
"Critical": "red"
}
table_matrix_risk = [["Impact ↓ / Likelihood →"] + impact_labels]
for likelihood_index, likelihood_label in enumerate(likelihood_labels, start=1):
reversed_index = 11 - likelihood_index
row = [likelihood_label]
for impact_index in range(1, 11):
score = reversed_index * impact_index
if score <= 20:
label = "Very Low"
elif score <= 40:
label = "Low"
elif score <= 60:
label = "Medium"
elif score <= 80:
label = "High"
else:
label = "Critical"
color_class = color_mapping[label]
row.append((score, label, color_class))
table_matrix_risk.append(row)
return table_matrix_risk
def get_risk_table(document):
risks = (
DocumentRiskControl.objects
.filter(document=document)
.values('risk', 'risk__risk_name')
.distinct()
)
risks_with_controls = []
for risk_entry in risks:
risk = {
'id': risk_entry['risk'],
'name': risk_entry['risk__risk_name']
}
controls = (
DocumentRiskControl.objects
.filter(document=document, risk_id=risk['id'])
.values('control', 'control__name', 'weight', 'likelihood')
.distinct()
)
max_weight = 10*10
total_weight = calculate_aggregate_weight(controls)
total_likelihood = calculate_aggregate_likelihood(controls)
impact, likelihood = map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight)
r_impact = round(impact)
r_likelihood = round(likelihood)
residua_impact = r_impact - 1 if r_impact > 2 else r_impact
residual_likelihood = r_likelihood - 1 if r_likelihood > 2 else r_likelihood
risks_with_controls.append({
'risk': risk,
'controls': list(controls),
'total_weight': total_weight,
'impact': impact,
'likelihood': likelihood,
'r_impact': r_impact,
'r_likelihood': r_likelihood,
'risk_score': r_impact * r_likelihood,
'residual_impact': residua_impact,
'residual_likelihood': residual_likelihood,
'residual_risk_score': residua_impact * residual_likelihood,
})
risks_with_controls.sort(key=lambda x: x['risk_score'], reverse=True)
return risks_with_controls

View File

@@ -1,66 +1,159 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document PDF</title>
<style>
@page {
size: A4;
margin: 2cm;
}
<div class="document-container">
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
* {
box-sizing: border-box;
}
@media print {
table {
page-break-inside: avoid; /* Prevent table from breaking across pages */
}
tr {
page-break-inside: avoid; /* Prevent table rows from breaking across pages */
page-break-after: auto;
}
thead {
display: table-header-group; /* Ensure table headers repeat on each page */
}
tfoot {
display: table-footer-group; /* Ensure table footers repeat on each page */
}
.page-break {
page-break-before: always; /* Force a page break before this element */
}
}
body {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 12pt;
overflow-wrap: break-word;
}
<div>
{{ rendered_html|safe }}
.document-container {
width: 100%;
max-width: 100%;
padding: 0;
margin: 0;
}
.document-header {
margin-bottom: 2rem;
}
.document-meta {
color: #666;
font-size: 0.9rem;
}
.document-content {
line-height: 1.6;
}
.document-title {
font-size: 2.5rem;
margin-bottom: 1.5rem;
}
.document-subtitle {
font-size: 2rem;
margin-bottom: 1.25rem;
}
.document-h1 {
font-size: 1.75rem;
margin-bottom: 1rem;
}
.document-h2 {
font-size: 1.5rem;
margin-bottom: 0.75rem;
}
.document-h3 {
font-size: 1.25rem;
margin-bottom: 0.5rem;
}
.document-quote {
border-left: 4px solid #ccc;
margin: 1.5rem 0;
padding-left: 1rem;
font-style: italic;
}
.document-body {
margin-bottom: 1rem;
}
.green { background-color: green; color: white; }
.lightgreen { background-color: lightgreen; }
.yellow { background-color: yellow; }
.orange { background-color: orange; }
.red { background-color: red; color: white; }
table {
width: 100%;
table-layout: fixed;
word-wrap: break-word;
border-collapse: collapse;
}
th, td {
padding: 4px 6px;
font-size: 10pt;
text-align: center;
border: 1px solid #ddd;
overflow-wrap: break-word;
word-break: break-word;
}
th {
background-color: #f2f2f2;
font-weight: bold;
}
caption {
font-weight: bold;
margin-bottom: 10px;
}
.cmmi thead th {
border-bottom: 1px solid black;
}
img {
max-width: 100%;
height: auto;
}
.page-break {
page-break-after: always;
}
</style>
</head>
<body>
<div class="document-container">
{% if error %}
<p style="color: red;">{{ error }}</p>
{% endif %}
<div>
{{ rendered_html|safe }}
</div>
</div>
<style>
.document-container {
max-width: 800px;
margin: 2rem auto;
padding: 0 1rem;
}
.document-header {
margin-bottom: 2rem;
}
.document-meta {
color: #666;
font-size: 0.9rem;
}
.document-content {
line-height: 1.6;
}
.document-title {
font-size: 2.5rem;
margin-bottom: 1.5rem;
}
.document-subtitle {
font-size: 2rem;
margin-bottom: 1.25rem;
}
.document-h1 {
font-size: 1.75rem;
margin-bottom: 1rem;
}
.document-h2 {
font-size: 1.5rem;
margin-bottom: 0.75rem;
}
.document-h3 {
font-size: 1.25rem;
margin-bottom: 0.5rem;
}
.document-quote {
border-left: 4px solid #ccc;
margin: 1.5rem 0;
padding-left: 1rem;
font-style: italic;
}
.document-body {
margin-bottom: 1rem;
}
</style>
</body>
</html>

View File

@@ -0,0 +1,64 @@
import unittest
from django.template import Context
from ..processors import render_universal_segment, render_template
class TestProcessors(unittest.TestCase):
def setUp(self):
self.context_data = {
"document": {
"organization": {"name": "Example Corp"},
"created_at": "2025-04-08",
"third_party_vendor_access": 50
}
}
self.template_segments = [
{
"segment_type": "example_segment",
"content": [
{
"title": "Main Title",
"subtitle": "Subtitle 1",
"description": "This is the first description.\n- Bullet 1\n- Bullet 2"
},
{
"subtitle": "Subtitle 2",
"description": "This is the second description.\nAnother paragraph here."
}
],
"html": "<div><p>Custom HTML content with {{ document.organization.name }}</p></div>"
}
]
def test_render_universal_segment(self):
segment = self.template_segments[0]
result = render_universal_segment(segment, self.context_data)
self.assertIn("<h2 style=", result)
self.assertIn("<h3 style=", result)
self.assertIn("<ul style=", result)
self.assertIn("<div><p>Custom HTML content with Example Corp</p></div>", result)
def test_render_template(self):
result = render_template(self.template_segments, self.context_data)
self.assertIn('<div class="segment example_segment">', result)
self.assertIn("Main Title", result)
self.assertIn("Subtitle 1", result)
self.assertIn("Custom HTML content with Example Corp", result)
def test_empty_segment(self):
segment = {"segment_type": "empty_segment", "content": []}
result = render_universal_segment(segment, self.context_data)
self.assertEqual(result, "")
def test_missing_html(self):
segment = {
"segment_type": "no_html_segment",
"content": [{"title": "Title Only"}]
}
result = render_universal_segment(segment, self.context_data)
self.assertIn("Title Only", result)
self.assertNotIn("<div>", result)
def test_missing_content(self):
segment = {"segment_type": "html_only", "html": "<p>Only HTML</p>"}
result = render_universal_segment(segment, self.context_data)
self.assertIn("<p>Only HTML</p>", result)

View File

@@ -53,13 +53,16 @@ class DocumentViewTest(TestCase):
template_content = """
- segment_type: "h1"
content: "{{ document.organization.name }} - Risk Report"
content:
title: "{{ document.organization.name }} - Risk Report"
- segment_type: "p"
content: "Created at: {{ document.created_at|date:'Y-m-d' }}"
content:
descripton: |
"Created at: {{ document.created_at|date:'Y-m-d' }}"
- segment_type: "h2"
content: "Top 10 Risk Identified"
- segment_type: "table"
content: |
html: |
<table>
<tr>
<th>Risk ID</th>
@@ -81,11 +84,13 @@ class DocumentViewTest(TestCase):
{% endfor %}
</table>
- segment_type: "image"
content: "data:image/png;base64,{{ graph }}"
content:
image: "data:image/png;base64,{{ graph }}"
- segment_type: "h2"
content: "Risks with Controls"
content:
title: "Risks with Controls"
- segment_type: "body"
content: |
html: |
{% for item in risks_with_controls %}
<div class="risk">
<h3>Risk: {{ item.risk.name }}</h3>
@@ -107,7 +112,8 @@ class DocumentViewTest(TestCase):
response = self.client.get(reverse('core:document', kwargs={'document_id': self.document.id}))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'document.html')
self.assertContains(response, self.organization.name)
self.assertContains(response, self.organization.name)
self.assertContains(response, "Risk Report")
def test_index_view(self):
response = self.client.get(reverse('core:index'))

View File

@@ -6,10 +6,11 @@ from .forms import OrganizationForm
from .models import Organization,Document, DocumentTemplate,DocumentRiskControl,Risk
from backend.accounts.utils import send_confirmation_email, send_document_email
from django.contrib.admin.views.decorators import staff_member_required
from django.template import Template, Context
from .utils import generate_pdf, map_weight_to_impact_likelihood, calculate_aggregate_weight, calculate_aggregate_likelihood, generate_risk_graph
from .tables import risk_matrix_table ,get_risk_table
from django.conf import settings
site_domain = settings.SITE_DOMAIN
from .processors import render_template
@@ -49,40 +50,8 @@ def thankyou(request):
def document(request, document_id):
document = get_object_or_404(Document, id=document_id)
risks = (
DocumentRiskControl.objects
.filter(document=document)
.values('risk', 'risk__risk_name')
.distinct()
)
risks_with_controls = []
for risk_entry in risks:
risk = {
'id': risk_entry['risk'],
'name': risk_entry['risk__risk_name']
}
controls = (
DocumentRiskControl.objects
.filter(document=document, risk_id=risk['id'])
.values('control', 'control__name', 'weight', 'likelihood')
.distinct()
)
max_weight = 10*10
total_weight = calculate_aggregate_weight(controls)
total_likelihood = calculate_aggregate_likelihood(controls)
impact, likelihood = map_weight_to_impact_likelihood(total_weight, total_likelihood, max_weight)
risks_with_controls.append({
'risk': risk,
'controls': list(controls),
'total_weight': total_weight,
'impact': impact,
'likelihood': likelihood,
'risk_score': (round(impact) * round(likelihood))
})
risks_with_controls = get_risk_table(document)
table_risk_matrix = risk_matrix_table()
graph_base64 = generate_risk_graph(risks_with_controls)
template_obj = get_object_or_404(DocumentTemplate, name="Default Template")
@@ -95,28 +64,10 @@ def document(request, document_id):
context = {
'document': document,
'risks_with_controls': risks_with_controls,
'graph': graph_base64,
'graph': graph_base64,
'table_risk_matrix': table_risk_matrix,
}
rendered_content = ""
for segment in template_segments:
content = segment.get('content', '')
segment_type = segment.get('segment_type', '')
django_template = Template(content)
processed_content = django_template.render(Context(context))
if segment_type == "h1":
rendered_content += f"<h1>{processed_content}</h1>\n"
elif segment_type == "h2":
rendered_content += f"<h2>{processed_content}</h2>\n"
elif segment_type == "h3":
rendered_content += f"<h3>{processed_content}</h3>\n"
elif segment_type == "p":
rendered_content += f"<p>{processed_content}</p>\n"
elif segment_type == "image":
rendered_content += f'<img src="{processed_content}" alt="Risk Graph" style="max-width:100%; height:auto;">\n'
else:
rendered_content += processed_content
rendered_content = render_template(template_segments, context)
return render(request, 'document.html', {'rendered_html': rendered_content})

View File

@@ -1,15 +1,228 @@
- segment_type: "h1"
content: "{{ document.organization.name }} - Risk Report "
- segment_type: "organization"
content:
- title: "{{ document.organization.name }} - Risk Report"
description: |
Created at: {{ document.created_at|date:'Y-m-d' }}
- segment_type: "p"
content: "Created at: {{ document.created_at|date:'Y-m-d' }}"
- segment_type: "executive_summary"
content:
- title: "Executive Summary"
description: |
This Cyber Risk Assessment Report provides a comprehensive evaluation of {{ document.organization.name }}s cybersecurity posture, focusing on identifying critical risks, prioritizing mitigation strategies, and aligning practices with internationally recognized frameworks such as CIS CSC18 v8.1, NIST CSF 2.0, ISO 27001:2022, and regulatory requirements like NIS2, DORA and GDPR. The assessment was conducted by StackSight LLC, leveraging insights from data provided by the representatives of {{ document.organization.name }}, consultancy and industry reports, and threat intelligence sources, to provide actionable guidance tailored to {{ document.organization.name }}s unique operational environment.
- subtitle: "Key Findings"
description: |
The assessment revealed several areas where "{{ document.organization.name }}" - faces heightened cybersecurity risks, particularly in the domains of phishing, ransomware, vendor risks, and unpatched software vulnerabilities. These risks pose significant threats to operational continuity, sensitive data, and regulatory compliance. The following are the top risks identified:
- Phishing Attacks: High likelihood due to reliance on email communication and remote workforce operations.
- Ransomware Incidents: Elevated impact, threatening critical data and operational systems.
- Vendor Risks: Increased exposure due to reliance on over {{ document.organization.third_party_vendor_access }} third-party vendors without robust monitoring.
- subtitle: "Recommendations"
description: |
To address these risks, we propose a strategic roadmap comprising targeted safeguards, each prioritized for its effectiveness in reducing risk likelihood and impact. Key recommendations include:
- Phishing Risk Mitigation:
- Deploy advanced email filtering systems to reduce spam and malicious emails.
- Enforce multi-factor authentication (MFA) organization-wide to secure access.
- Conduct phishing simulations and training programs to enhance employee awareness.
- Ransomware Prevention:
- Implement a comprehensive patch management program to address software vulnerabilities.
- Utilize endpoint detection and response (EDR) tools to monitor and contain threats.
- Ensure frequent data backups, stored securely offline, to enable recovery.
- Vendor Risk Management:
- Establish robust vendor security standards, aligned with ISO 27001.
- Conduct regular third-party risk assessments to monitor compliance and address vulnerabilities.
- Integrate continuous monitoring solutions for vendor activities accessing critical systems.
- subtitle: "Value Proposition"
description: |
By implementing these recommendations, {{ document.organization.name }} stands to achieve the following benefits:
- 75% reduction in financial exposure from cyber incidents through targeted risk mitigation.
- Increased compliance with regulatory mandates.
- Enhanced operational continuity and reduced downtime during potential cyber events.
- subtitle: "Next Steps"
description: |
We recommend initiating a phased implementation plan, focusing first on high-priority safeguards such as MFA, patch management, and vendor assessments, to address the most pressing risks. Additionally, a regular risk register review cycle should be established to adapt to the evolving threat landscape.
- segment_type: "h2"
content: "Top 10 Risk Identified"
- segment_type: "inherent_limitations"
content:
- title: "Inherent Limitations"
subtitle: "Dynamic Nature of Cyber Threats"
description: |
Cybersecurity threats evolve rapidly, driven by advancements in attack techniques, changes in technology, and new vulnerabilities. This report reflects a "point-in-time" snapshot of the organizations risk landscape and does not account for changes occurring after the assessment. Regular updates are crucial to ensure that the organization remains resilient against emerging threats.
A phishing risk rated as medium during this assessment could escalate due to unforeseen factors, such as a surge in targeted attacks within the industry.
- segment_type: "table"
content: |
- subtitle: "Focus on Risk Management Frameworks"
description: |
This assessment adopts a risk-based approach, aligning findings with frameworks such as ISO 27001, CIS CSC18, NIST CSF, and regulatory requirements that include GDPR, NIS2, PCI DSS, and DORA. While these frameworks are comprehensive, they are not exhaustive. The recommendations are tailored to organizational priorities and risk tolerances, but residual risks are an inherent part of this approach.
Residual Risk
The level of risk remaining after the implementation of all recommended safeguards. For example, while multi-factor authentication (MFA) significantly reduces phishing risks, user behavior may still leave a small residual risk.
- subtitle: "Scope and Context"
description: |
This report is an organization-level assessment, emphasizing risks related to strategic and operational cybersecurity governance. It does not provide a system-level evaluation (e.g., penetration testing or vulnerability scanning) or an asset-level analysis of specific infrastructure components, devices, or applications.
For a more detailed understanding of individual systems or assets, supplementary assessments, such as technical audits, vulnerability scans, or penetration tests, are recommended.
- subtitle: "Reliance on Provided Inputs"
description: |
The accuracy and reliability of this assessment are contingent upon the quality and completeness of the information provided by {{ document.organization.name }}. Any gaps, inaccuracies, or omissions in the input data may influence the findings and recommendations.
If incomplete information about third-party integrations is provided, the resulting vendor risk analysis may underestimate potential vulnerabilities.
- subtitle: "Control Maturity Assumptions"
description: |
Residual risk calculations in this report assume that all recommended controls are implemented at highest maturity levels (e.g., CMMI Level 5). However, the maturity of controls within {{ document.organization.name }} may vary based on resources, implementation timelines, and ongoing maintenance efforts.
For example, while patch management can significantly reduce software vulnerabilities, its effectiveness depends on factors like update frequency and organizational policies.
- subtitle: "Scope of External Factors"
description: |
While this assessment focuses on internal risks under {{document.organization.name}}s control, it does not evaluate broader external factors such as geopolitical risks, natural disasters, or systemic vulnerabilities in third-party ecosystems.
- subtitle: "Dependency on Timely Implementation"
description: |
The recommendations provided in this report assume the timely and effective implementation of proposed controls. Delays, partial implementations, or inadequate maintenance may result in higher residual risks than estimated in this assessment.
Delayed adoption of endpoint detection and response (EDR) tools could leave the organization exposed to ransomware attacks for longer than necessary.
- subtitle: "Regular Reassessment Requirement"
description: |
This report serves as a baseline assessment of cybersecurity risks. Given the dynamic nature of cyber threats and changes in technology and business processes, we recommend periodic reassessments to keep the risk register updated and aligned with the evolving threat landscape.
A risk identified as low today might increase in severity due to changes in attack vectors, regulatory environments, or organizational growth.
- segment_type: "approach_and_methodologies"
content:
- title: "Approach and Methodologies"
subtitle: "Methodology Overview"
description: |
The risk assessment methodology employed in this report is rooted in the NIST 800-30 Guide for Conducting Risk Assessments, which defines risk as a function of likelihood and impact. This method is widely adopted due to its scalability and alignment with organizational needs. It is also compliant with ISO 27001, ISO31000, PCI DSS, ENISA, and CSA CCM, by focusing on the common key elements:
1. Risk Identification: Identifying threats, vulnerabilities, and potential impacts.
2. Risk Assessment: Evaluating the likelihood and severity of risks.
3. Risk Mitigation/Treatment: Implementing strategies to reduce, transfer, or accept risks.
4. Documentation: Keeping a detailed record of the risk assessment process.
5. Continuous Monitoring: Ongoing assessment to ensure that new risks are identified and mitigated.
6. Communication: Ensuring that risk findings are communicated to relevant stakeholders.
- subtitle: "Inputs and Data Collection"
description: |
This assessment was tailored using the following inputs from {{ document.organization.name }}:
1. Organizational Scale: Employee headcount and annual revenue.
2. Technology Landscape: Dependency on critical applications and network segmentation.
3. Regulatory Frameworks: Requirements such as GDPR, ISO 27001, and NIST CSF compliance.
4. Operational Context: Industry sector and reliance on third-party vendors.
Insights were further enriched by incorporating data from leading sources, such as:
- Verizon DBIR, emphasizing phishing and ransomware trends.
- PwCs Global Digital Trust Insights, highlighting gaps in vendor security management.
- EYs Cybersecurity Risk Radar, identifying emerging threats to specific industries.
The outcome of the assessment is a Risk Register with top 10 organization-wide cybersecurity risks.
- subtitle: "Risk Assessment Process"
description: |
StackSight utilizes key concepts from standard NIST 800-30: Guide for Conducting Risk Assessments. A key calculation of risk provided by this document is one that ascribes a risk score to the likelihood of that risk being exploited, multiplied by the impact of the risk being exploited. This scoring methodology has been generally adopted globally and is considered by most to be the standard.
This standard utilizes the concepts of inherent risk and residual risk. Inherent risk is the likelihood and impact of a risk being exploited without any mitigating factors or controls. While this is typically never the actual case, it represents the worst-case scenario presented by a given risk and serves as a solid “starting point” for how to measure the eventual reduction of that risk. Residual risk, on the other hand, considers all mitigating factors associated with a given risk, namely, controls. While the actual values and scale utilized are different between organizations, a scale of 1-5 is very common. In this scale, 1 is low and 5 is high.
For further use we define the risk impact scored as:
- 1: Less than (0.05% of annual revenue or x% of materiality) loss, no time required on individual contributors nor management to resolve. No reputational impact.
- 2: Above (0.05% of annual revenue or x% of materiality) loss, 1-10hrs individual contributors time to resolve, and 10-20hrs of management time to resolve. Minimal concern of reputational impact.
- 3: Above $(0.1% of annual revenue or x% of materiality) loss, 40-80hrs individual contributors time to resolve, and 10-20 hrs. of management time to resolve. Moderate concern of reputational impact.
- 4: $(0.5% of annual revenue or x% of materiality), 80-160hrs individual contributors time to resolve, and 20-30 hrs. of management time to resolve. Major concern of reputational impact.
- 5: $(1% of annual revenue or materiality) + loss, 160+ individual contributors time to resolve and 40hrs of management time to resolve. Enormous concern of reputational impact ("extremely out of line with regulations/unethical behavior").
Material impact definition can depend on the organizational type. For companies above 1b annual revenue, it is set at 1% of annual revenue, and for organizations below that amount, it is 10%. For non-profit organizations, other stated guidelines are used.
- segment_type: impact_definition_table
content:
description: |
Impact is aslo defined with the following table:
headers: ["Level", "Financial Cost", "Reputational Impact", "Management Effort", "Operational Resources", "RPO", "RTO"]
rows:
- ["Insignificant (1-2)", "< 0.05% Material", "Normal", "Normal", "Normal", "16 hr", "64 hr"]
- ["Significant (3-4)", "> 0.5% Material", "Minor", "Minor", "Minor", "8 hr", "32 hr"]
- ["Severe (5-6)", "> 10% Material", "Moderate", "Moderate", "Moderate", "4 hr", "16 hr"]
- ["Material (7-8)", "> 50% Material", "Critical", "Critical", "Critical", "2 hr", "8 hr"]
- ["Major (9-10)", "> Material", "Precarious", "Precarious", "Precarious", "1 hr", "4 hr"]
- segment_type: "list_stack_sights"
content:
- description: |
For determining likelihood, we use StackSight's commonly referenced scale:
- level: 1-2
description: "0-3% chance of happening in a year"
- level: 3-4
description: "4-10% chance of happening in a year"
- level: 5-6
description: "11-50% chance of happening in a year"
- level: 7-8
description: "51-90% chance of happening in a year"
- level: 9-10
description: "91-100% chance of happening in a year"
- segment_type: "likelihood_table"
content:
description: |
Likelihood is defined on the probability of the risk materializing in the next 12 months.
html: |
<table>
{% for row in table_risk_matrix %}
<tr>
{% for cell in row %}
{% if forloop.parentloop.first %}
<th>{{ cell }}</th>
{% else %}
{% if forloop.first %}
<th>{{ cell }}</th>
{% else %}
<td style="background-color: {{ cell.2 }};">
{{ cell.1 }}<br>{{ cell.0 }}
</td>
{% endif %}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
- segment_type: "aproach_continuation"
content:
description: |
Baseline Risk Tolerance is defined at the risk level 7 and below, established by taking the maximum Impact (5) and Likelihood (5) which divides the risk matrix diagonally between the minimum and maximum risk ranges of 0-25 which establishes the Tolerance Range.
subtitle: "Risk Treatment Planning"
description: |
Risks are categorized by priority, with treatment strategies that include mitigation, avoidance, or transference, depending on severity and organizational capacity. Identified risks are mapped to safeguards from CIS CSC18, prioritized by effectiveness in reducing likelihood and impact. Each control is weighted based on its potential to mitigate the risk, and residual risk scores are calculated assuming full control maturity. Each mapped safeguard provides in-depth information on its utility specific to the risk.
Identified safeguards are grouped into CIS Control as a guidance for security program building. Other CIS safeguards, belonging to the same CIS Control group are documented for further considerations. Also any control defined as a dependencies are listed as well. Implementation of these extended security programs could help reduce identified risks by additional 12%.
subtitle: "Residual Risk Assessment"
description: |
After implementing the recommended controls, the residual risks are quantified, offering a clearer view of the organizations risk posture. Research has shown that implementing recommended safeguards will reduce the related risk by 80%, if the controls are functioning at the highest maturity level.
subtitle: "Technical Term: Residual Risk:"
description: |
The level of risk that remains after implementing all feasible controls. For example, while MFA reduces phishing risk, a small residual risk persists due to potential human error.
- segment_type: "results_and_recomendation"
content:
- title: "Results and Recomendation"
subtitle: "Organizational Context"
description: |
{{document.organization.name }} operates in the {{document.organization.industry_sector }} sector, employing {{document.organization.employee_headcount }} personnel with annual revenues of approximately {{document.organization.annual_revenue}}. The organization relies heavily on technology, with a dependency score of {{document.organization.it_dependency}}. Regulatory mandates such as {{document.organization.compliance_frameworks}} drive the need for robust cybersecurity governance.
- segment_type: "top_ten_risks"
content:
- subtitle: "Top 10 Risk Identified"
description: |
Based on the assessment, the following top 10 risks have been prioritized:
html: |
<table class="classic-table">
<tr>
<th>Risk ID</th>
<th>Risk Name</th>
@@ -22,22 +235,104 @@
<tr>
<td>{{ item.risk.id }}</td>
<td>{{ item.risk.name }}</td>
<td>{{ item.impact|floatformat:0 }}</td>
<td>{{ item.likelihood|floatformat:0 }}</td>
<td>{{ item.r_impact }}</td>
<td>{{ item.r_likelihood}}</td>
<td>{{ item.risk_score }}</td>
<td> - </td>
</tr>
{% endfor %}
</table>
- segment_type: "image"
content: "data:image/png;base64,{{ graph }}"
- segment_type: "h2"
content: "Risks with Controls"
- segment_type: "graph_risk_likelihood"
content:
description: |
Each risk is assigned an impact and likelihood score, and plotted on a risk matrix to visualize prioritization.
image: "data:image/png;base64,{{ graph }}"
- segment_type: "body"
content: |
- segment_type: "result_continuation"
content:
subtitle: "Recommended Controls"
description: |
For each risk, tailored safeguards are recommended based on the CIS CSC18 framework. For example:
• Phishing Mitigation:
◦ Deploy advanced email filtering tools.
◦ Mandate organization-wide multi-factor authentication (MFA).
◦ Conduct regular phishing simulations and employee training.
• Vendor Risk Management:
◦ Establish vendor security standards aligned with ISO 27001.
◦ Conduct third-party risk assessments.
◦ Implement continuous monitoring for vendor compliance.
subtitle: "Key Insight:"
description: |
According to CIS report xxxxx risk can be reduced by 80%/////
subtitle: "Risk Treatment Plan"
description: |
To address identified risks, a comprehensive risk treatment plan is proposed, prioritizing controls with the highest risk reduction capacity. Strategies include:
1. Mitigation: Implementing safeguards to reduce likelihood or impact.
2. Avoidance: Refraining from high-risk activities or architectures.
3. Transference: Shifting risk through insurance or contractual agreements.
4. Acceptance: Informed decision by organizational leadership not to take any action.
Where feasible, all risks should be treated. If the risk score is 8 or above based on the risk assessment procedure, it must be treated in a timely manner. Before considering accepting a risk, the risk should be reduced to the smallest possible residual risk using one or more risk treatment approaches.
content:
title: "Risks with Residuals"
html: |
<table class="classic-table">
<tr>
<th>Risk ID</th>
<th>Risk Name</th>
<th>Inherent Impact </th>
<th>Interent Liklihood </th>
<th>Inherent Risk Score </th>
<th>Residual Impact </th>
<th>Residual Liklihood </th>
<th>Residual Risk Score </th>
</tr>
{% for item in risks_with_controls %}
<tr>
<td>{{ item.risk.id }}</td>
<td>{{ item.risk.name }}</td>
<td>{{ item.r_impact }}</td>
<td>{{ item.r_likelihood}}</td>
<td>{{ item.risk_score }}</td>
<td>{{ item.residual_impact }}</td>
<td>{{ item.residual_likelihood}}</td>
<td>{{ item.residual_risk_score }}</td>
</tr>
{% endfor %}
</table>
- segment_type: "frameworks_and_standards"
content:
-title: "Frameworks and Standards"
subtitle: "CIS CSC18"
description: |
The report aligns with the CIS Critical Security Controls (CSC18) framework, a globally recognized standard for implementing scalable and high-impact controls.
- segment_type: cmmi_table
content:
headers: ["Category", "Level 1", "Level 2", "Level 3", "Level 4", "Level 5"]
rows:
- ["Govern", "Governance and oversight of cybersecurity risk is reactive and ad hoc.", "Governance and oversight of cybersecurity risk exists, but is nascent and unreliable.", "Governance and oversight of cybersecurity risk is established, predictable and reliable.", "Governance and oversight of cybersecurity risk provides direction and shapes the overall program.", "Governance is a key pillar of the cybersecurity risk program and current-state of all safeguards and controls is known and reportable."]
- ["Identify", "Little to no cybersecurity risk identification.", "Process for cybersecurity risk identification exists, but it is immature.", "Risks to IT assets are identified and managed in a standard, well-defined process.", "Risk to the business environment are identified and proactively monitored on a periodic basis.", "Cybersecurity risks are continuously monitored and incorporated into business decisions."]
- ["Protect", "Asset protection is reactive and ad hoc.", "Data protection mechanisms are implemented across the environment.", "Data is formally defined and protected in accordance with its classification.", "The environment is proactively monitored via protective technologies.", "Protection standards are operationalized through automation and advanced technologies."]
- ["Detect", "Anomalies or events are not detected or not detected in a timely manner.", "Anomaly detection is established through detection tools and monitoring procedures.", "A baseline of 'normal' activity is established and applied against tools/procedures to better identify malicious activity.", "A continuous monitoring program is established to detect threats in real-time.", "Detection and monitoring solutions are continuously learning behaviors and adjusting detection capabilities."]
- ["Respond", "The process for responding to incidents is reactive or non-existent.", "The process for recovering from incidents is reactive or non-existent.", "Analysis capabilities are applied consistently to incidents by Incident Response (IR) roles.", "An IR Plan defines steps for incident preparation, analysis, containment, eradication, and post-incident.", "Response times and impacts of incidents are monitored and minimized."]
- ["Recover", "Resiliency and recovery capabilities are applied consistently to incidents impacting business operations.", "A Continuity & Disaster Recovery Plan defines steps to continue critical functions and resume normal operations.", "Recovery times and impacts of incidents are monitored and minimized.", "The capabilities of all IT personnel, procedures, and technologies are regularly tested and updated.", "The capabilities of all IT personnel, procedures, and technologies are regularly tested and updated."]
- segment_type: "framework_continuation"
content:
subtitle: "NIST CSF"
description: |
The NIST Cybersecurity Framework (CSF) provides a structured approach to risk management, emphasizing identification, protection, detection, response, and recovery.
Industry and Consultancy Benchmarks
• Verizon DBIR: Insights into phishing, ransomware, and insider threats.
• PwCs Digital Trust Insights: Trends in vendor risk management and supply chain vulnerabilities.
- segment_type: "risk_controls_table"
content:
- title: "Risks with Controls"
html: |
{% for item in risks_with_controls %}
<div class="risk">
<h3>Risk: {{ item.risk.name }}</h3>
@@ -52,3 +347,10 @@
</div>
</div>
{% endfor %}
- segment_type: "continous_improvment"
content:
- title: "Continuous Improvement"
description: |
Cybersecurity is a continuous journey. {{document.organization.name}} should establish regular risk register reviews and maturity assessments to adapt to evolving threats. Implementing a cybersecurity improvement roadmap will ensure that controls remain effective and aligned with organizational priorities.
The risk register should be reviewed regularly. The review must include a re-assessment of risks based on identified changes to organizational information systems and the environments in which the systems operate that may affect risk (change monitoring) including changes in the feasibility of the ongoing implementation of risk response measures. Risks that have been accepted should be re-evaluated at every cycle. Efforts should be made to optimize risk response measures, where feasible.