diff --git a/gcp/appengine/frontend3/src/styles.scss b/gcp/appengine/frontend3/src/styles.scss
index 2f8a9f830bb..c338378f272 100644
--- a/gcp/appengine/frontend3/src/styles.scss
+++ b/gcp/appengine/frontend3/src/styles.scss
@@ -360,8 +360,16 @@ mwc-icon-button.mdc-data-table__sort-icon-button {
/** Vulnerability page */
-.vulnerability-page .title {
- font-size: 60px;
+.vulnerability-page {
+ .title {
+ font-size: $osv-heading-size;
+ }
+
+ @media (max-width: 500px) {
+ .title {
+ font-size: $osv-heading-size-mobile;
+ }
+ }
}
dl.vulnerability-details,
@@ -382,6 +390,7 @@ dl.vulnerability-details,
pre {
white-space: pre-wrap;
+ overflow: auto;
}
.links {
@@ -389,11 +398,28 @@ dl.vulnerability-details,
display: flex;
flex-direction: column;
gap: 10px;
+ overflow-wrap: break-word;
}
}
.vulnerability-packages-container {
- margin-top: 80px;
+ margin-top: 50px;
+
+ .title {
+ margin-left: 20px;
+ font-size: 24px;
+ margin-bottom: 16px;
+ font-weight: bold;
+ }
+
+ // Tab bar styling.
+ --const-mq-affordances:
+ [screen and (max-width: 500px) ] collapse |
+ [screen and (min-width: 501px) ] tab-bar;
+
+ .force-collapse {
+ --const-mq-affordances: [screen] collapse;
+ }
}
.vulnerability-packages {
@@ -410,10 +436,38 @@ dl.vulnerability-details,
font-size: 20px;
}
- // Tab bar styling.
- --const-mq-affordances:
- [screen] tab-bar
- ;
+ .version-value {
+ font-family: $osv-heading-font-family;
+ }
+
+ .events {
+ gap: 4px;
+ }
+
+ .spicy-sections-workaround {
+ // https://github.com/tabvengers/spicy-sections/issues/64.
+ pointer-events: none;
+ }
+
+ &[affordance="collapse"] h2 {
+ .vuln-ecosystem {
+ display: inline;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+ .vuln-name {
+ display: inline;
+ font-weight: normal;
+ }
+
+ &[expanded] {
+ background: #fff;
+ color: $osv-accent-color;
+ }
+
+ width: 100%;
+ }
+
&[affordance="tab-bar"] h2 {
cursor: default;
diff --git a/gcp/appengine/frontend3/src/templates/vulnerability.html b/gcp/appengine/frontend3/src/templates/vulnerability.html
index 8b4ec3f99d0..7c7724d06b1 100644
--- a/gcp/appengine/frontend3/src/templates/vulnerability.html
+++ b/gcp/appengine/frontend3/src/templates/vulnerability.html
@@ -17,7 +17,7 @@
{{ vulnerability.id }}
Modified
{{ vulnerability.modified }}
Details
- {{ vulnerability.details }}
+ {{ vulnerability.details }}
References
@@ -31,48 +31,86 @@ {{ vulnerability.id }}
-
+ Affected packages
+
{% for affected in vulnerability.affected %}
- {{ affected['package']['ecosystem'] }}
- /
- {{ affected['package']['name'] }}
+ {{ affected['package']['ecosystem'] }}
+ /
+ {{ affected['package']['name'] }}
{{ affected['package']['name'] }}
-
Affected ranges
+
+ Affected ranges
+
+
{% for range in affected['ranges'] %}
- Type
- {{ range['type'] }}
- Events
- - {{ range['events'] }}
+ -
+
+ {% for event in range['events'] %}
+
+ {{ event | event_type }}
+
+
+ {% endfor %}
+
+
{% endfor %}
-
Affected versions
-
+
+ Affected versions
+
+
+
{% for version in affected['versions'] %}
{{ version }}
{% endfor %}
-
-
Ecosystem specific
-
-
{{ affected['ecosystem_specific'] }}
+ {% if affected['ecosystem_specific'] %}
+
+
+ Ecosystem specific
+
+
+
+
{{ affected['ecosystem_specific'] }}
+
-
-
-
Database specific
-
-
{{ affected['database_specific'] }}
+ {% endif %}
+ {% if affected['database_specific'] %}
+
+
+ Database specific
+
+
+
+
{{ affected['database_specific'] }}
+
-
+ {% endif %}
{% endfor %}
diff --git a/gcp/appengine/frontend_handlers.py b/gcp/appengine/frontend_handlers.py
index ebfb3821801..d2af98c4cd9 100644
--- a/gcp/appengine/frontend_handlers.py
+++ b/gcp/appengine/frontend_handlers.py
@@ -291,6 +291,59 @@ def vulnerability_handler():
return jsonify(osv_get_by_id(vuln_id))
+@blueprint.app_template_filter('event_type')
+def event_type(event):
+ """Get the type from an event."""
+ if event.get('introduced'):
+ return 'Introduced'
+ if event.get('fixed'):
+ return 'Fixed'
+ if event.get('limit'):
+ return 'Limit'
+ if event.get('last_affected'):
+ return 'Last affected'
+
+ return None
+
+
+@blueprint.app_template_filter('event_link')
+def event_link(event):
+ """Get the link from an event."""
+ if event.get('introduced_link'):
+ return event['introduced_link']
+ if event.get('fixed_link'):
+ return event['fixed_link']
+ if event.get('limit_link'):
+ return event['limit_link']
+ if event.get('last_affected_link'):
+ return event['last_affected_link']
+
+ return None
+
+
+@blueprint.app_template_filter('event_value')
+def event_value(event):
+ """Get the value from an event."""
+ if event.get('introduced'):
+ return event['introduced']
+ if event.get('fixed'):
+ return event['fixed']
+ if event.get('limit'):
+ return event['limit']
+ if event.get('last_affected'):
+ return event['last_affected']
+
+ return None
+
+
+@blueprint.app_template_filter('should_collapse')
+def should_collapse(affected):
+ """Whether if we should collapse the package tab bar."""
+ total_package_length = sum(
+ [len(entry.get('package', {}).get('name', '')) for entry in affected])
+ return total_package_length > 70 or len(affected) > 5
+
+
@blueprint.app_template_filter('log')
def logarithm(n):
return math.log(n)