larxius commited on
Commit
a3f2381
·
verified ·
1 Parent(s): fe62170

Update backend/utils/pdf_generator.py

Browse files
Files changed (1) hide show
  1. backend/utils/pdf_generator.py +39 -45
backend/utils/pdf_generator.py CHANGED
@@ -970,54 +970,48 @@ def generate_scan_pdf(scan, vulnerabilities):
970
  elements.append(Paragraph(rem_final_text, normal))
971
  elements.append(Spacer(1, 25))
972
 
973
- # --- APPENDIX: REQUIRES MANUAL VERIFICATION & LEGAL DISCLAIMER ---
974
- elements.append(PageBreak())
975
- elements.append(Paragraph("<b>Appendix: Requires Manual Verification</b>", heading2))
976
- elements.append(Spacer(1, 5))
977
- elements.append(Paragraph("The following findings were flagged by automated heuristic signatures or out-of-band probes, but lack full payload confirmation. They are excluded from executive summary severity counts and require manual verification by a security engineer.", normal))
978
- elements.append(Spacer(1, 15))
979
 
980
- target_url = scan.target_url if (scan and getattr(scan, 'target_url', None)) else 'https://www.target.com'
 
 
 
 
 
981
 
982
- # Appendix Item A.1
983
- elements.append(Paragraph("<b>A.1 Blind XSS Payloads Submitted to 1 Form(s) — Awaiting Callback [Requires Verification]</b>", styles['Heading3']))
984
- a1_data = [
985
- ["Status", Paragraph("<font color='#EA580C'>Requires Verification</font>", normal), "CVSS Score", "8.2"],
986
- ["Category", "Blind XSS", "Severity", Paragraph("<font color='#99CC33'>Low</font>", normal)],
987
- ["CVSS Vector", "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", "", ""]
988
- ]
989
- a1_table = Table(a1_data, colWidths=[80, 150, 80, 150])
990
- a1_table.setStyle(TableStyle([
991
- ('BACKGROUND', (0,0), (-1,-1), colors.HexColor("#F9FAFB")),
992
- ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#E5E7EB")),
993
- ('FONTNAME', (0,0), (0,-1), 'Helvetica-Bold'),
994
- ('FONTNAME', (2,0), (2,-1), 'Helvetica-Bold'),
995
- ]))
996
- elements.append(a1_table)
997
- elements.append(Spacer(1, 8))
998
- a1_desc = f"<b>Description:</b><br/>Out-of-band XSS payloads were submitted to 1 form endpoint(s).<br/>Callback listener configured at: <font name='Courier'>https://xss-reporting.internal/callback</font><br/>&bull; {html.escape(target_url)} (injection attempted)<br/><br/><i>This is NOT a confirmed finding. Blind XSS requires an external callback to verify execution. Monitor your XSS hunter / callback server for incoming requests from https://xss-reporting.internal/callback. If a callback is received, escalate to Critical.</i>"
999
- elements.append(Paragraph(a1_desc, normal))
1000
- elements.append(Spacer(1, 15))
1001
 
1002
- # Appendix Item A.2
1003
- elements.append(Paragraph("<b>A.2 XML External Entity (XXE) Error-Based Detection [Requires Verification]</b>", styles['Heading3']))
1004
- a2_data = [
1005
- ["Status", Paragraph("<font color='#EA580C'>Requires Verification</font>", normal), "CVSS Score", "3.9"],
1006
- ["Category", "Injection", "Severity", Paragraph("<font color='#99CC33'>Low</font>", normal)],
1007
- ["CVSS Vector", "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", "", ""]
1008
- ]
1009
- a2_table = Table(a2_data, colWidths=[80, 150, 80, 150])
1010
- a2_table.setStyle(TableStyle([
1011
- ('BACKGROUND', (0,0), (-1,-1), colors.HexColor("#F9FAFB")),
1012
- ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#E5E7EB")),
1013
- ('FONTNAME', (0,0), (0,-1), 'Helvetica-Bold'),
1014
- ('FONTNAME', (2,0), (2,-1), 'Helvetica-Bold'),
1015
- ]))
1016
- elements.append(a2_table)
1017
- elements.append(Spacer(1, 8))
1018
- a2_desc = f"<b>Description:</b><br/>An Unconfirmed XXE indicator was detected at {html.escape(target_url)} via XML error messages.<br/>Error pattern matched: <font name='Courier'>XML</font><br/><b>Confidence:</b> Unconfirmed &mdash; this is based on a single error substring match. It may be a false positive (generic XML error on any malformed input). Manual verification is required before treating as exploitable.<br/>If a single payload(s) triggered this: 1 independent payload(s) matched error patterns."
1019
- elements.append(Paragraph(a2_desc, normal))
1020
- elements.append(Spacer(1, 20))
 
 
 
 
 
 
 
1021
 
1022
  # Legal Disclaimer & Confidentiality Notice
1023
  elements.append(PageBreak())
 
970
  elements.append(Paragraph(rem_final_text, normal))
971
  elements.append(Spacer(1, 25))
972
 
973
+ # --- APPENDIX: REQUIRES MANUAL VERIFICATION (ONLY IF UNCONFIRMED FINDINGS EXIST) ---
974
+ unconfirmed_findings = [
975
+ v for v in (findings or [])
976
+ if getattr(v, 'requires_verification', False)
977
+ or (getattr(v, 'confidence', '') and str(getattr(v, 'confidence', '')).lower() in ['unconfirmed', 'requires verification', 'heuristic'])
978
+ ]
979
 
980
+ if unconfirmed_findings:
981
+ elements.append(PageBreak())
982
+ elements.append(Paragraph("<b>Appendix: Requires Manual Verification</b>", heading2))
983
+ elements.append(Spacer(1, 5))
984
+ elements.append(Paragraph("The following findings were flagged by automated heuristic signatures or out-of-band probes, but lack full payload confirmation. They are excluded from executive summary severity counts and require manual verification by a security engineer.", normal))
985
+ elements.append(Spacer(1, 15))
986
 
987
+ target_url = scan.target_url if (scan and getattr(scan, 'target_url', None)) else 'https://www.target.com'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
988
 
989
+ for u_idx, u_vuln in enumerate(unconfirmed_findings, start=1):
990
+ u_title = getattr(u_vuln, 'title', f"Unconfirmed Finding #{u_idx}")
991
+ u_cvss = str(getattr(u_vuln, 'cvss_score', '0.0'))
992
+ u_cat = getattr(u_vuln, 'category', 'General')
993
+ u_sev = getattr(u_vuln, 'severity', 'Low')
994
+ u_desc = getattr(u_vuln, 'description', '')
995
+ u_vec = getattr(u_vuln, 'cvss_vector', 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N')
996
+
997
+ elements.append(Paragraph(f"<b>A.{u_idx} {html.escape(u_title)} [Requires Verification]</b>", styles['Heading3']))
998
+ u_data = [
999
+ ["Status", Paragraph("<font color='#EA580C'>Requires Verification</font>", normal), "CVSS Score", u_cvss],
1000
+ ["Category", u_cat, "Severity", Paragraph(f"<font color='#99CC33'>{u_sev}</font>", normal)],
1001
+ ["CVSS Vector", u_vec, "", ""]
1002
+ ]
1003
+ u_table = Table(u_data, colWidths=[80, 150, 80, 150])
1004
+ u_table.setStyle(TableStyle([
1005
+ ('BACKGROUND', (0,0), (-1,-1), colors.HexColor("#F9FAFB")),
1006
+ ('GRID', (0,0), (-1,-1), 0.5, colors.HexColor("#E5E7EB")),
1007
+ ('FONTNAME', (0,0), (0,-1), 'Helvetica-Bold'),
1008
+ ('FONTNAME', (2,0), (2,-1), 'Helvetica-Bold'),
1009
+ ]))
1010
+ elements.append(u_table)
1011
+ elements.append(Spacer(1, 8))
1012
+ desc_p = f"<b>Description:</b><br/>{html.escape(u_desc)}"
1013
+ elements.append(Paragraph(desc_p, normal))
1014
+ elements.append(Spacer(1, 15))
1015
 
1016
  # Legal Disclaimer & Confidentiality Notice
1017
  elements.append(PageBreak())