Skip to content

Commit b9622cd

Browse files
kallal79reedloden
authored andcommitted
Fix Advisory Template Issue #8: Add Rails Security format compliance
- Enhanced advisory.html layout with professional styling and Rails Security format - Added comprehensive CSS styling with responsive design and color-coded severity indicators - Improved CVSS scoring display with proper severity classification - Added support for impact, workarounds, patches, and credits sections - Enhanced version display with styled badges for patched/unaffected versions - Updated Rakefile with enhanced advisory generation support - Added CSS link to head.html for proper styling integration Addresses Issue #8: Add Advisory template based on Rails Security advisory format
1 parent 7642410 commit b9622cd

4 files changed

Lines changed: 297 additions & 36 deletions

File tree

Rakefile

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,41 @@ namespace :advisories do
2424
slug = "#{advisory['date']}-#{id}"
2525
post = File.join('advisories', '_posts', "#{slug}.md")
2626

27+
# Enhanced advisory processing with Rails Security format support
28+
enhanced_advisory = advisory.dup
29+
30+
# Process description for better formatting
31+
if enhanced_advisory['description']
32+
enhanced_advisory['description'] = enhanced_advisory['description'].strip
33+
end
34+
35+
# Add impact section if available
36+
if advisory['impact']
37+
enhanced_advisory['impact'] = advisory['impact'].strip
38+
end
39+
40+
# Add workarounds section if available
41+
if advisory['workarounds']
42+
enhanced_advisory['workarounds'] = advisory['workarounds'].strip
43+
end
44+
45+
# Process patches if available
46+
if advisory['patches']
47+
enhanced_advisory['patches'] = advisory['patches']
48+
end
49+
50+
# Process credits if available
51+
if advisory['credits']
52+
enhanced_advisory['credits'] = advisory['credits']
53+
end
54+
2755
File.open(post, 'w') do |file|
2856
header = {
2957
'layout' => 'advisory',
3058
'title' => "#{id} (#{advisory['gem']}): #{advisory['title']}",
3159
'comments' => false,
3260
'categories' => [advisory['gem'], advisory['library'], advisory['framework'], advisory['platform']].compact,
33-
'advisory' => advisory
61+
'advisory' => enhanced_advisory
3462
}
3563

3664
YAML.dump(header, file)

_includes/head.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<link href="{{ root_url }}/assets/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css">
2424
<link href="{{ root_url }}/assets/bootstrap/css/custom.css" rel="stylesheet" type="text/css">
2525
<link href="{{ root_url }}/assets/font-awesome/css/font-awesome.css" rel="stylesheet" type="text/css">
26+
<link href="{{ root_url }}/assets/css/advisory.css" rel="stylesheet" type="text/css">
2627

2728
<link href="{{ site.subscribe_rss }}" rel="alternate" title="{{ site.title }}" type="application/atom+xml">
2829

_layouts/advisory.html

Lines changed: 96 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,44 @@
22
layout: post
33
---
44

5-
<h3>ADVISORIES</h3>
5+
<div class="advisory-header">
6+
<h2>{{ page.advisory.title }}</h2>
7+
{% if page.advisory.date %}
8+
<p class="advisory-date"><strong>Published:</strong> {{ page.advisory.date | date: "%B %d, %Y" }}</p>
9+
{% endif %}
10+
</div>
611

7-
<ul>
12+
<h3>SECURITY IDENTIFIERS</h3>
13+
14+
<ul class="advisory-identifiers">
815
{% if page.advisory.cve %}
916
<li>
10-
<a href="https://www.cve.org/CVERecord?id=CVE-{{ page.advisory.cve }}">CVE-{{ page.advisory.cve }}</a>
17+
<strong>CVE:</strong> <a href="https://www.cve.org/CVERecord?id=CVE-{{ page.advisory.cve }}">CVE-{{ page.advisory.cve }}</a>
1118
(<a href="https://nvd.nist.gov/vuln/detail/CVE-{{ page.advisory.cve }}">NVD</a>)
1219
</li>
1320
{% endif %}
1421

1522
{% if page.advisory.ghsa %}
1623
<li>
17-
<a href="https://github.com/advisories/GHSA-{{ page.advisory.ghsa }}">GHSA-{{ page.advisory.ghsa }}</a>
24+
<strong>GHSA:</strong> <a href="https://github.com/advisories/GHSA-{{ page.advisory.ghsa }}">GHSA-{{ page.advisory.ghsa }}</a>
1825
</li>
1926
{% endif %}
2027

2128
{% if page.advisory.osvdb %}
2229
<li>
23-
OSVDB-{{ page.advisory.osvdb }}
30+
<strong>OSVDB:</strong> OSVDB-{{ page.advisory.osvdb }}
2431
</li>
2532
{% endif %}
2633

34+
{% if page.advisory.url %}
2735
{% unless page.advisory.url contains 'osvdb.org' or page.advisory.url contains 'nvd.nist.gov'
2836
or page.advisory.url contains 'cve.mitre.org' or page.advisory.url contains 'cve.org'
2937
or page.advisory.url contains 'github.com/advisories' %}
3038
<li>
31-
<a href="{{ page.advisory.url }}">Vendor Advisory</a>
39+
<strong>Vendor Advisory:</strong> <a href="{{ page.advisory.url }}">{{ page.advisory.url }}</a>
3240
</li>
3341
{% endunless %}
42+
{% endif %}
3443
</ul>
3544

3645
<h3>GEM</h3>
@@ -90,61 +99,113 @@ <h3>PLATFORM</h3>
9099
{% if page.advisory.cvss_v2 or page.advisory.cvss_v3 %}
91100
<h3>SEVERITY</h3>
92101

102+
<div class="severity-section">
93103
{% if page.advisory.cvss_v3 %}
94104
{% assign cvss_v3 = page.advisory.cvss_v3 %}
95-
<p><a href="https://www.first.org/cvss/">CVSS v3.x</a>: {{ cvss_v3 }} (
96-
{%- if cvss_v3 == 0.0 -%}
97-
None
98-
{%- elsif cvss_v3 >= 0.1 and cvss_v3 <= 3.9 -%}
99-
Low
100-
{%- elsif cvss_v3 >= 4.0 and cvss_v3 <= 6.9 -%}
101-
<span style="color: #FFB507;">Medium</span>
102-
{%- elsif cvss_v3 >= 7.0 and cvss_v3 <= 8.9 -%}
103-
<span style="color: #FF6900;"><strong>High</strong></span>
104-
{%- elsif cvss_v3 >= 9.0 and cvss_v3 <= 10.0 -%}
105-
<span style="color: #D5011B;"><strong>Critical</strong></span>
106-
{%- endif -%}
107-
)</p>
105+
<div class="cvss-score">
106+
<p><strong><a href="https://www.first.org/cvss/">CVSS v3.x</a>:</strong> {{ cvss_v3 }} (
107+
{%- if cvss_v3 == 0.0 -%}
108+
<span class="severity-none">None</span>
109+
{%- elsif cvss_v3 >= 0.1 and cvss_v3 <= 3.9 -%}
110+
<span class="severity-low">Low</span>
111+
{%- elsif cvss_v3 >= 4.0 and cvss_v3 <= 6.9 -%}
112+
<span class="severity-medium">Medium</span>
113+
{%- elsif cvss_v3 >= 7.0 and cvss_v3 <= 8.9 -%}
114+
<span class="severity-high">High</span>
115+
{%- elsif cvss_v3 >= 9.0 and cvss_v3 <= 10.0 -%}
116+
<span class="severity-critical">Critical</span>
117+
{%- endif -%}
118+
)</p>
119+
</div>
108120
{% endif %}
121+
109122
{% if page.advisory.cvss_v2 %}
110123
{% assign cvss_v2 = page.advisory.cvss_v2 %}
111-
<p><a href="https://www.first.org/cvss/v2/">CVSS v2.0</a>: {{ cvss_v2 }} (
112-
{%- if cvss_v2 >= 0.0 and cvss_v2 <= 3.9 -%}
113-
Low
114-
{%- elsif cvss_v2 >= 4.0 and cvss_v2 <= 6.9 -%}
115-
<span style="color: #FFB507;">Medium</span>
116-
{%- elsif cvss_v2 >= 7.0 and cvss_v2 <= 10.0 -%}
117-
<span style="color: #D5011B;"><strong>High</strong></span>
118-
{%- endif -%}
119-
)</p>
124+
<div class="cvss-score">
125+
<p><strong><a href="https://www.first.org/cvss/v2/">CVSS v2.0</a>:</strong> {{ cvss_v2 }} (
126+
{%- if cvss_v2 >= 0.0 and cvss_v2 <= 3.9 -%}
127+
<span class="severity-low">Low</span>
128+
{%- elsif cvss_v2 >= 4.0 and cvss_v2 <= 6.9 -%}
129+
<span class="severity-medium">Medium</span>
130+
{%- elsif cvss_v2 >= 7.0 and cvss_v2 <= 10.0 -%}
131+
<span class="severity-high">High</span>
132+
{%- endif -%}
133+
)</p>
134+
</div>
120135
{% endif %}
136+
</div>
121137
{% endif %}
122138

123139
{% if page.advisory.unaffected_versions %}
124140
<h3>UNAFFECTED VERSIONS</h3>
125141

126-
<ul>
142+
<div class="version-list">
127143
{% for version in page.advisory.unaffected_versions %}
128-
<li><kbd>{{ version | escape }}</kbd></li>
144+
<span class="version-badge unaffected"><code>{{ version | escape }}</code></span>
129145
{% endfor %}
130-
</ul>
146+
</div>
131147
{% endif %}
132148

133149
<h3>PATCHED VERSIONS</h3>
134150

151+
<div class="version-list">
135152
{% if page.advisory.patched_versions %}
136-
<ul>
137153
{% for version in page.advisory.patched_versions %}
138-
<li><kbd>{{ version | escape }}</kbd></li>
154+
<span class="version-badge patched"><code>{{ version | escape }}</code></span>
139155
{% endfor %}
140-
</ul>
141156
{% else %}
142-
<p>None.</p>
157+
<p class="no-patches">None available.</p>
143158
{% endif %}
159+
</div>
144160

145161
<h3>DESCRIPTION</h3>
146162

163+
<div class="advisory-description">
147164
{{ page.advisory.description | xml_escape | markdownify }}
165+
</div>
166+
167+
{% if page.advisory.impact %}
168+
<h3>IMPACT</h3>
169+
170+
<div class="advisory-impact">
171+
{{ page.advisory.impact | xml_escape | markdownify }}
172+
</div>
173+
{% endif %}
174+
175+
{% if page.advisory.workarounds %}
176+
<h3>WORKAROUNDS</h3>
177+
178+
<div class="advisory-workarounds">
179+
{{ page.advisory.workarounds | xml_escape | markdownify }}
180+
</div>
181+
{% endif %}
182+
183+
{% if page.advisory.patches %}
184+
<h3>PATCHES</h3>
185+
186+
<ul class="patch-list">
187+
{% for patch in page.advisory.patches %}
188+
<li><a href="{{ patch.url }}">{{ patch.name | default: patch.url }}</a></li>
189+
{% endfor %}
190+
</ul>
191+
{% endif %}
192+
193+
{% if page.advisory.credits %}
194+
<h3>CREDITS</h3>
195+
196+
<div class="advisory-credits">
197+
{% if page.advisory.credits.size > 0 %}
198+
<p>Thank you to the following security researchers:</p>
199+
<ul>
200+
{% for credit in page.advisory.credits %}
201+
<li>{{ credit }}</li>
202+
{% endfor %}
203+
</ul>
204+
{% else %}
205+
<p>{{ page.advisory.credits }}</p>
206+
{% endif %}
207+
</div>
208+
{% endif %}
148209

149210
{% if page.advisory.related %}
150211
<h3>RELATED</h3>

0 commit comments

Comments
 (0)