Skip to content
Vulnotes LogoVulnotes
Filters

Filters ​

Filters transform values when outputting variables. Chain them with the pipe | character.

INFO

The examples below use vuln. as the loop variable (e.g. vuln.severity). This assumes you are inside a {% for vuln in vulnerabilities %} loop.

Date formatting ​

formatDate ​

Formats a date value. Long and full use English month names; short follows the rendering environment's locale.

liquid
{{ dates.startDate | formatDate: 'short' }}   <!-- e.g. 1/15/2025 -->
{{ dates.startDate | formatDate: 'long' }}    <!-- January 15, 2025 -->
{{ dates.startDate | formatDate: 'full' }}    <!-- Wednesday, January 15, 2025 -->
FormatOutput
shortLocale-dependent, e.g. 1/15/2025
longJanuary 15, 2025
fullWednesday, January 15, 2025

String manipulation ​

capitalize, uppercase, lowercase ​

liquid
{{ "hello world" | capitalize }}   <!-- Hello world -->
{{ report.title | uppercase }}     <!-- PENETRATION TEST REPORT -->
{{ report.title | lowercase }}    <!-- penetration test report -->

Score formatting ​

score ​

Formats a numeric value to one decimal place. Returns 0.0 for null or undefined values.

liquid
{{ vuln.cvss.score | score }}   <!-- 7.5 -->
{{ vuln.cvss.baseScore | score }}

cvssMetric ​

Returns Not Defined for null or empty CVSS metric values.

liquid
{{ vuln.cvss.AV | cvssMetric }}   <!-- Network -->
{{ vuln.cvss.E | cvssMetric }}    <!-- Not Defined (if empty) -->

Color mapping ​

These filters return hex color codes that can be used in inline styles.

severityColor / severityBackgroundColor ​

Map a severity string to a color. Use severityColor for text and severityBackgroundColor for backgrounds.

These are typically used in table cells where you can set the cell's color via the visual editor, or in inline styles:

liquid
{{ vuln.severity | severityColor }}
{{ vuln.severity | severityBackgroundColor }}

textColor / backgroundColor ​

Map a numeric CVSS score to a color.

RangeSeverity
9.0 – 10.0Critical
7.0 – 8.9High
4.0 – 6.9Medium
0.1 – 3.9Low
0Informational
liquid
{{ vuln.cvss.score | backgroundColor }}
{{ vuln.cvss.score | textColor }}

mapColor / mapBgColor ​

Map arbitrary values to custom colors. Format: 'key1:#hex1,key2:#hex2,_default:#hex'.

liquid
{{ vuln.remediation_complexity | mapColor: 'Easy:#22c55e,Medium:#eab308,Hard:#ef4444,_default:#6b7280' }}
{{ vuln.priority | mapBgColor: 'P1:#dc2626,P2:#ea580c,P3:#ca8a04,P4:#2563eb' }}

Matching is case-insensitive. Use _default for a fallback color.

Value mapping ​

mapValue ​

Translate or map a value to a different string. Format: 'key1:value1,key2:value2,_default:fallback'.

liquid
{{ vuln.severity | mapValue: 'Critical:Critique,High:Élevé,Medium:Moyen,Low:Faible,Info:Information' }}
{{ vuln.remediation_complexity | mapValue: 'Easy:Facile,Medium:Moyen,Hard:Difficile,_default:Inconnu' }}

Matching is case-insensitive. Returns the original value if no match is found and no _default is set.

Sorting ​

sort_by ​

Sort an array by a property. Supports nested properties with dot-notation.

liquid
<!-- Sort by CVSS score -->
{% for vuln in vulnerabilities | sort_by: 'cvss.score' %}
  {{ vuln.title }}: {{ vuln.cvss.score | score }}
{% endfor %}

<!-- Sort alphabetically by title -->
{% for vuln in vulnerabilities | sort_by: 'title' %}
  {{ vuln.title }}
{% endfor %}

sort_multi ​

Sort by multiple keys with custom value ordering. Format: 'property1:value1|value2;property2:value1|value2'.

Semicolons separate sort keys, colons separate property from value order, pipes separate values.

liquid
<!-- Sort by severity (Critical first), then alphabetically by title -->
{% for vuln in vulnerabilities | sort_multi: 'severity:Critical|High|Medium|Low|Info;title' %}
  {{ vuln.severity }}: {{ vuln.title }} ({{ vuln.cvss.score | score }})
{% endfor %}

Without a custom value list, a key sorts in ascending order. To sort by score from highest to lowest, use sort_by: 'cvss.score' | reverse.

Filtering by vulnerability template ​

When a report uses more than one vulnerability template (for example, a Web template and a Mobile template on the same report), every finding still ends up in the same vulnerabilities array. Each finding carries a templateName field with the name of the vulnerability template it was created from, so you can split or filter the list inside your report template.

Loop only findings from one template ​

Use a Liquid if inside the loop to render a section per template:

liquid
<!-- Web findings -->
{% for vuln in vulnerabilities %}
  {% if vuln.templateName == 'Web' %}
    {{ forloop.index }}. {{ vuln.title }} ({{ vuln.severity }})
    {{ vuln.description }}
  {% endif %}
{% endfor %}

<!-- Mobile findings -->
{% for vuln in vulnerabilities %}
  {% if vuln.templateName == 'Mobile' %}
    {{ forloop.index }}. {{ vuln.title }} ({{ vuln.severity }})
    {{ vuln.description }}
  {% endif %}
{% endfor %}

Pre-filter with the where filter ​

The standard Liquid where filter returns a sub-array, which keeps forloop.index and size accurate for each group:

liquid
{% assign web_vulns = vulnerabilities | where: 'templateName', 'Web' %}
{% assign mobile_vulns = vulnerabilities | where: 'templateName', 'Mobile' %}

Web findings: {{ web_vulns | size }}
Mobile findings: {{ mobile_vulns | size }}

{% for vuln in web_vulns %}
  {{ forloop.index }}. {{ vuln.title }}
{% endfor %}

You can chain it with sort_by or sort_multi to order each group independently:

liquid
{% assign web_vulns = vulnerabilities | where: 'templateName', 'Web' | sort_by: 'cvss.score' %}

TIP

The name must match the vulnerability template name exactly (case-sensitive). If you rename a vulnerability template, also update any templateName comparisons in your report templates.

Standard Liquid filters ​

All standard LiquidJS filters are also available. Some commonly used ones:

FilterDescriptionExample
sizeArray length or string length{{ vulnerabilities | size }}
plusAdd a number{{ stats.criticalCount | plus: stats.highCount }}
minusSubtract a number{{ stats.totalVulnerabilities | minus: stats.informativeCount }}
defaultFallback value if empty{{ client.logo | default: '/placeholder.png' }}
joinJoin array items{{ vuln.tags | join: ', ' }}
replaceReplace text{{ report.title | replace: 'Draft', 'Final' }}
truncateTruncate to length{{ vuln.description | truncate: 100 }}
strip_htmlRemove HTML tags{{ vuln.description | strip_html }}
newline_to_brConvert newlines to <br>{{ text | newline_to_br }}