Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated per TFDEV-5123
Image RemovedImage Added

📙 You will learn

How to configure defect templates.

Prerequisites

Audience: IT Professional
Difficulty: Intermediate
Time needed: Approximately 20 minutes
Tools required: N/A

Velocity Templates

ThreadFix uses a Velocity template to generate defect descriptions. Velocity has also made available a comprehensive user guide.

Finding the Defect Description Template

Multiple defect templates can be defined at once. The original template is located at tomcat/webapps/threadfix/velocityTemplates/defect with the name Classic_Description.vm. User files can be placed in this directory with any desired changes or the existing template updated as necessary. When submitting a defect through the ThreadFix UI, choose between any template file in this directory and they will appear within ThreadFix by their filename.

Samples

As of 3.8 current ThreadFix users utilizing the Rally defect tracker need to add the following code to their template file and any other customized template files they've created.

Code Block
#if ( $defectTrackerName=="Rally" || $defectTrackerName=="Azure DevOps")
    #set ( $br = $br.replaceAll("\n", "<br />") )
#end

Default Template

By default, ThreadFix submits defects with vulnerability information in the format as seen in the image displayed below of defects submitted to JIRA:

If the “Include Scanner Detail” field is checked when submitting a defect, the Scanner Detail field for the first vulnerability will be included in the beginning of the defect description, as shown in the image below:

Table of Contents

Table of Contents
Expand
titleScanner Detail field - Click to expand

If looking closely at the Classic_Description.vm file, the section which provides all of the default output is viewable:

Expand
titledefectDescription.vm - click to expand
Code Block
#if( $metadata.preamble && $metadata.preamble != "" )
    #header("General information")$br
    $metadata.preamble$br
    $br
#end
#set( $vulnIndex=0 )
#if( $vulnerabilities )
    #foreach( $vulnerability in $vulnerabilities )
        #if( $vulnerability.genericVulnerability && $vulnerability.surfaceLocation )
            Vulnerability\[${vulnIndex}]: #addThreadfixLink( "${baseUrl}$vulnerability.getUri()" )$br
            $vulnerability.genericVulnerability.name$br
            CWE entry: http://cwe.mitre.org/data/definitions/${vulnerability.genericVulnerability.id}.html$br
            #set( $dependencyFinding = "" )
            #set( $staticFinding = "" )
            #set( $dynamicFinding = "" )

            #set( $dependencyFinding = $dependencyFindings.get($vulnerability) )
            #set( $staticFinding = $staticFindings.get($vulnerability) )
            #set( $dynamicFinding = $dynamicFindings.get($vulnerability) )

            #if( $dependencyFinding && $dependencyFinding.getDependency() )
                #set( $refId = "" )
                #set( $refLink = "" )
                #set( $componentName = "" )

                #set( $refId = $dependencyFinding.getDependency().getRefId() )
                #set( $refLink = $dependencyFinding.getDependency().getRefLink() )
                #set( $componentName = $dependencyFinding.getDependency().getComponentName() )

                #if( $refId != "" || $componentName != "" )
                    Vulnerability dependency:$br
                    #if( $refId != "" )Reference: $refId #if($refLink != "")($refLink)#end$br#end
                    #if( $componentName != "" )Component: $componentName$br#end
                #end
            #end
            #if( $staticFinding && $staticFinding.getDataFlowElements() )
                #set( $dataFlows = "" )
                #set( $dataFlows = $staticFinding.getDataFlowElements() )

                #if( $dataFlows != "")
                    Vulnerability source file location:$br
                    #foreach( $dataFlow in $dataFlows )
                        #set( $sourceFileLocation = "" )
                        #set( $lineNumber = "" )

                        #set( $sourceFileLocation = $dataFlow.getSourceFileName() )
                        #set( $lineNumber = $dataFlow.getLineNumber() )

                        #if( $sourceFileLocation != "" )
                        File: $sourceFileLocation#if($lineNumber != "") line $lineNumber#end$br
                        #end
                    #end
                #end
            #end
            #if( $dynamicFinding && $dynamicFinding.surfaceLocation )
                #set( $url = "" )
                #set( $parameter = "" )

                #set( $url = $dynamicFinding.surfaceLocation.getUrl() )
                #set( $parameter = $dynamicFinding.surfaceLocation.parameter )

                #if( $url != "" || $parameter != "" )
                    Vulnerability attack surface location:$br
                    #if( $url != "" )URL: ${url}#end$br
                    #if( $parameter != "" )Parameter: ${parameter}#end$br
                #end
            #end

            #if($addFindingsDetails)
                #addFindingsDetails( $vulnerability )
            #end
            #set( $vulnIndex = $vulnIndex + 1 )
        #end
        $br
    #end

    #if( $customTexts.size() > 0 )
        #header("ThreadFix Custom Text:")$br
        #foreach ($customText in $customTexts)
            $customText
        #end
    #end
#end

The general information provided includes the Vulnerability Type for the submitted vulnerability. Users can create a defect for one vulnerability or one defect for multiple vulnerabilities. The general information also includes Scanner Detail information if the corresponding checkbox is selected when submitting defects. Following that, the defect description lists each vulnerability along with pertinent details. Dynamic findings, static findings, and DependencyCheck findings all provide different information sets to make the defect description more useful. The final section lists custom text for each vulnerability type, which can be configured in ThreadFix from the Customize ThreadFix Vulnerability Types page.

Additional information can be included for each vulnerability. At the top of Classic_Description.vm, change #set( $addFindingsDetails=false ) from “false” to “true”. This adds the following section to each vulnerability:

Code Block
##This part will add most of the interesting details of the findings of a vulnerability
#macro( addFindingsDetails $vulnerability )
    #if( $vulnerability.findings && !$vulnerability.findings.isEmpty() )
        #foreach( $finding in $vulnerability.findings )
            #presentIfNotNull("Scanner Detail" $finding.scannerDetail false)
            #presentIfNotNull("Scanner Recommendation" $finding.scannerRecommendation false)
            #presentIfNotNull("Attack String" $finding.attackString true)
            #presentIfNotNull("Attack Request" $finding.attackRequest true)
            #presentIfNotNull("Attack Response" $finding.attackResponse true)
            #addDataFlow($finding)
        #end
    #end
#end

The presentIfNotNull method is a way of including vulnerability details only if they exist for that vulnerability, three variables are required for this.

  1. First provide a string that will print before the information.

  2. Specify which field to print (a full list of available fields are available at the bottom of this page).

  3. If final variable is set to "true", JIRA defect trackers will treat the field as a code block and other defect trackers will separate the section with horizontal lines. Setting it to "false" will treat the field as plaintext. If the additional finding details are enabled, the same vulnerability defect shown above will now contain much more information by default:

Expand
titleVulnerability Defect detailed view - Click to expand

Add Dependency Validation Information

There may be times when the default fields submitted with defects are not the desired ones. For example, more information may be desired to be provided for DependencyCheck findings. By customizing the Classic_Description.vm the preferred information for the defects can be retrieved. For this example, changes were made for the following:

Code Block
##This part will add most of the interesting details of the findings of a vulnerability
#macro( addFindingsDetails $vulnerability )
    #if( $vulnerability.findings && !$vulnerability.findings.isEmpty() )
        #foreach( $finding in $vulnerability.findings )
            #presentIfNotNull("Scanner Detail" $finding.scannerDetail false)
            #presentIfNotNull("Scanner Recommendation" $finding.scannerRecommendation false)
            #presentIfNotNull("Attack String" $finding.attackString true)
            #presentIfNotNull("Attack Request" $finding.attackRequest true)
            #presentIfNotNull("Attack Response" $finding.attackResponse true)
            #addDataFlow($finding)
			#if( $finding.dependency )
				#presentIfNotNull("Component File Path" $finding.dependency.componentFilePath false)
				#presentIfNotNull("Description" $finding.dependency.description false)
				#presentIfNotNull("Source" $finding.dependency.source false)
			#end
        #end
    #end
#end

The defect ThreadFix submitted after making these changes contained more relevant information for a dependency validation finding:

Notice there is no “Source” section when it was included in the addFindingsDetails section. The vulnerability used for this defect did not have any data for that field, so due to the presentIfNotNull method it was excluded without issue.

Full Field List

A list of fields have been provided in this section for customizing defect submissions. Keep in mind that not every field is relevant to every vulnerability, use checks such as the presentIfNotNull method when including them. ThreadFix recommends making a backup of Classic_Description.vm before making any major changes.

Findings

The following fields should be used in the addFindingsDetails macro.

Value

code

Description

$finding.createdDate

Adds the Created Date of the finding

$finding.modifiedDate

Adds the Modified Date of the finding

$finding.attackRequest

Adds the Attack Request of the finding

$finding.attackResponse

Adds the Attack Response of the finding

$finding.attackString

Adds the Attack String of the finding

$finding.authenticationRequired

Adds the Authentication Requirement of the finding

$finding.calculatedFilePath

Adds the Calculated File Path of the finding

$finding.calculatedUrlPath

Adds the Calculated URL Path of the finding

$finding.longDescription

Adds the Long Description of the finding

$finding.markedFalsePositive

Boolean determining if finding is marked as a false positive. 1 for false positive and 0 for not false positive

$finding.nativeId

Adds the Native ID of the finding

$finding.rawFinding

Adds the Raw Finding

$finding.scannedDate

Adds the finding’s Scanned Date

$finding.scannerDetail

Adds the finding’s Scanner Details

$finding.scannerRecommendation

Adds the finding’s Scanner Recommendation

$finding.sourceFileLocation

Adds the finding’s Source File Location

$finding.urlReference

Adds the finding’s URL Reference

$finding.scanId

Adds the finding’s Scan ID

$finding.vulnerability.

id

id

Adds the finding’s Vulnerability ID

$finding.dependency.componentFilePath

Adds the finding’s Dependency Component File Path

$finding.dependency.componentName

Adds the finding’s Dependency Component Name

$finding.dependency.cve

Adds the finding’s Dependency CVE

$finding.dependency.description

Adds the finding’s Dependency Description

$finding.dependency.refLink

Adds the finding’s Dependency RefLink

$finding.dependency.source

Adds the finding’s Dependency Source

$finding.dependency.getRefId()

Adds the finding’s Dependency Reference ID

$finding.channelSeverity.name

Adds the finding’s Channel Severity Name

$finding.channelVulnerability.name

Adds the finding’s Channel Vulnerability Name

$finding.getChannelNameOrNull()

Adds the finding’s Channel Name if it is not Null

Vulnerabilities

Most likely the following fields will be used in the first block of code, in the #foreach( $vulnerability in the #foreach( $vulnerability in $vulnerabilities ) loop.

Code Block$vulnerability.closeTime $vulnerability.foundByScanner $vulnerability.isFalsePositive $vulnerability.applicationId $vulnerability.surfaceLocation.parameter $vulnerability.surfaceLocation.path

$vulnerabilities ) loop.

Value

Description

$vulnerability.closeTime

Adds the vulnerability’s Close Time

$vulnerability.foundByScanner

Boolean determining if vulnerability was found by a scanner. 1 for true and 0 for false

$vulnerability.isFalsePositive

Boolean determining if vulnerability is a false positive. 1 for false positive and 0 for not false positive

$vulnerability.applicationId

Adds the vulnerability’s Application ID

$vulnerability.application.name

Adds the vulnerability’s Application Name

$vulnerability.surfaceLocation.parameter

Adds the vulnerability’s Surface Location Parameter

$vulnerability.surfaceLocation.path

Adds the vulnerability’s Surface Location Path

$vulnerability.surfaceLocation.getUrl()

Adds the vulnerability’s surface location URL

$vulnerability.genericSeverity.name

Adds the vulnerability’s Generic Severity Name

$vulnerability.genericSeverity.customName

Adds the vulnerability’s Generic Severity Custom Name

$vulnerability.genericVulnerability.name

Adds the vulnerability’s Generic Vulnerability Name

$vulnerability.genericVulnerability

.customText

.customText

Adds the vulnerability’s Generic Vulnerability Custom Text

$vulnerability.genericVulnerability.cweId

Adds the vulnerability’s CWE ID

Data Flow Elements

These fields can be used in the addDataFlow macro at the bottom of Classic_Description.vm.

Value

code

Description

$dataflowElement.sourceFileName

Adds the Data Flow Element’s Source File Name

$dataflowElement.lineNumber

Adds the Data Flow Element’s Line Number

$dataflowElement.lineText

Adds the Data Flow Element’s Line Text

$dataflowElement.sequence

Adds the Data Flow Element’s Sequence

$dataflowElement.columnNumber

Adds the Data Flow Element’s Column Number

Extra

To get a link to the ThreadFix page for a vulnerability, use ${baseUrl}$vulnerability.getUri().

To get a link to the CWE entry for a vulnerability, use http://cwe.mitre.org/data/definitions/${vulnerability.genericVulnerability.id}.html

Optional Velocity Tools

Note

This feature is available only in 2.8.3 and newer.

ThreadFix has added the Velocity Tool manager which allows Velocity Tools to be added to the velocity-tools.xml file for Velocity Template editing. $display tools has been added and will allow access to the display tools. This addition does not change current functionality, it adds the ability to add to Velocity as needed by the client.

Velocity Tools Example Use - HTML Tags in Jira Defects

Occasionally users may find HTML tags in Jira defect descriptions from defects created in ThreadFix. The HTML tags are provided to ThreadFix by some of the remote providers and are used solely for formatting. When transferred to Jira these will display as originally exported by the remote provider. Users may now use velocity tools to have access to the $display.stripTags. By adding $display.stripTags($metadata.preamble) in place of metadata.preamblein Classic_Description.vm will remove HTML tags from being added into the Jira defect description.