interface Props {
branchLike?: BranchLike;
component: Component;
- findings: Array<SecurityHotspot>;
+ findings: SecurityHotspot[];
showCWE: boolean;
type: 'owaspTop10' | 'sansTop25' | 'cwe';
}
: null;
const title = getRatingTooltip('security_rating', finding.vulnerabilityRating || 1);
+ const hasActiveRules = finding.activeRules > 0;
return (
<React.Fragment key={finding.category || finding.cwe}>
<tr>
{this.getName(finding, isCWE ? 'cwe' : type)}
</td>
<td className="text-right">
- <div className="display-inline-flex-center">
- <Link
- to={getComponentIssuesUrl(component.key, {
- ...params,
- types: IssueType.Vulnerability,
- resolved: 'false'
- })}>
- {finding.vulnerabilities}
- </Link>
- <Tooltip overlay={title}>
+ {!hasActiveRules && '-'}
+ {hasActiveRules && (
+ <div className="display-inline-flex-center">
<Link
- className="link-no-underline spacer-left"
to={getComponentIssuesUrl(component.key, {
...params,
types: IssueType.Vulnerability,
resolved: 'false'
})}>
- <Rating value={finding.vulnerabilityRating || 1} />
+ {finding.vulnerabilities}
</Link>
- </Tooltip>
- </div>
+ <Tooltip overlay={title}>
+ <Link
+ className="link-no-underline spacer-left"
+ to={getComponentIssuesUrl(component.key, {
+ ...params,
+ types: IssueType.Vulnerability,
+ resolved: 'false'
+ })}>
+ <Rating value={finding.vulnerabilityRating || 1} />
+ </Link>
+ </Tooltip>
+ </div>
+ )}
</td>
<td className="text-right security-column-separator">
- <Link
- to={getComponentIssuesUrl(component.key, {
- ...params,
- types: IssueType.Hotspot,
- resolved: 'false',
- statuses: 'OPEN,REOPENED'
- })}>
- {finding.openSecurityHotspots}
- </Link>
+ {!hasActiveRules && '-'}
+ {hasActiveRules && (
+ <Link
+ to={getComponentIssuesUrl(component.key, {
+ ...params,
+ types: IssueType.Hotspot,
+ resolved: 'false',
+ statuses: 'OPEN,REOPENED'
+ })}>
+ {finding.openSecurityHotspots}
+ </Link>
+ )}
</td>
<td className="text-right">
- <Link
- to={getComponentIssuesUrl(component.key, {
- ...params,
- types: IssueType.Hotspot,
- resolutions: 'FIXED',
- statuses: 'RESOLVED'
- })}>
- {finding.toReviewSecurityHotspots}
- </Link>
+ {!hasActiveRules && '-'}
+ {hasActiveRules && (
+ <Link
+ to={getComponentIssuesUrl(component.key, {
+ ...params,
+ types: IssueType.Hotspot,
+ resolutions: 'FIXED',
+ statuses: 'RESOLVED'
+ })}>
+ {finding.toReviewSecurityHotspots}
+ </Link>
+ )}
</td>
<td className="text-right">
- <Link
- to={getComponentIssuesUrl(component.key, {
- ...params,
- types: IssueType.Hotspot,
- resolutions: 'WONTFIX',
- statuses: 'RESOLVED'
- })}>
- {finding.wontFixSecurityHotspots}
- </Link>
+ {!hasActiveRules && '-'}
+ {hasActiveRules && (
+ <Link
+ to={getComponentIssuesUrl(component.key, {
+ ...params,
+ types: IssueType.Hotspot,
+ resolutions: 'WONTFIX',
+ statuses: 'RESOLVED'
+ })}>
+ {finding.wontFixSecurityHotspots}
+ </Link>
+ )}
</td>
</tr>
{subFindings}
const component = { key: 'foo', name: 'Foo', qualifier: 'TRK' } as Component;
const findings = [
{
+ activeRules: 1,
+ totalRules: 1,
category: 'a1',
vulnerabilities: 2,
vulnerabilityRating: 5,
wontFixSecurityHotspots: 0,
distribution: [
{
+ activeRules: 1,
+ totalRules: 1,
cwe: '42',
vulnerabilities: 1,
vulnerabilityRating: 1,
]
},
{
+ activeRules: 1,
+ totalRules: 2,
+ category: 'a2',
+ vulnerabilities: 2,
+ vulnerabilityRating: 5,
+ toReviewSecurityHotspots: 2,
+ openSecurityHotspots: 10,
+ wontFixSecurityHotspots: 0,
+ distribution: [
+ {
+ activeRules: 1,
+ totalRules: 1,
+ cwe: '42',
+ vulnerabilities: 1,
+ vulnerabilityRating: 1,
+ toReviewSecurityHotspots: 2,
+ openSecurityHotspots: 10,
+ wontFixSecurityHotspots: 0
+ }
+ ]
+ },
+ {
+ activeRules: 0,
+ totalRules: 1,
+ category: 'a3',
+ vulnerabilities: 2,
+ vulnerabilityRating: 5,
+ toReviewSecurityHotspots: 2,
+ openSecurityHotspots: 10,
+ wontFixSecurityHotspots: 0,
+ distribution: [
+ {
+ activeRules: 1,
+ totalRules: 1,
+ cwe: '42',
+ vulnerabilities: 1,
+ vulnerabilityRating: 1,
+ toReviewSecurityHotspots: 2,
+ openSecurityHotspots: 10,
+ wontFixSecurityHotspots: 0
+ }
+ ]
+ },
+ {
+ activeRules: 1,
+ totalRules: 1,
category: 'unknown',
vulnerabilities: 3,
vulnerabilityRating: 3,
type="owaspTop10"
/>
);
- expect(wrapper.find('tr').length).toBe(4);
+ expect(wrapper.find('tr').length).toBe(6);
expect(wrapper).toMatchSnapshot();
});
const wrapper = shallow(
<VulnerabilityList component={component} findings={findings} showCWE={true} type="owaspTop10" />
);
- expect(wrapper.find('tr').length).toBe(5);
+ expect(wrapper.find('tr').length).toBe(9);
expect(wrapper).toMatchSnapshot();
});
</td>
</tr>
</React.Fragment>
+ <React.Fragment
+ key="a2"
+ >
+ <tr>
+ <td
+ className=""
+ >
+ <React.Fragment>
+ A2
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ <div
+ className="display-inline-flex-center"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ <Tooltip
+ overlay="metric.security_rating.tooltip.E"
+ >
+ <Link
+ className="link-no-underline spacer-left"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ <Rating
+ value={5}
+ />
+ </Link>
+ </Tooltip>
+ </div>
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "statuses": "OPEN,REOPENED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 10
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "FIXED",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "WONTFIX",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 0
+ </Link>
+ </td>
+ </tr>
+ </React.Fragment>
+ <React.Fragment
+ key="a3"
+ >
+ <tr>
+ <td
+ className=""
+ >
+ <React.Fragment>
+ A3
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ -
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ </tr>
+ </React.Fragment>
<React.Fragment
key="unknown"
>
</tr>
</React.Fragment>
</React.Fragment>
+ <React.Fragment
+ key="a2"
+ >
+ <tr>
+ <td
+ className=""
+ >
+ <React.Fragment>
+ A2
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ <div
+ className="display-inline-flex-center"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ <Tooltip
+ overlay="metric.security_rating.tooltip.E"
+ >
+ <Link
+ className="link-no-underline spacer-left"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ <Rating
+ value={5}
+ />
+ </Link>
+ </Tooltip>
+ </div>
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "statuses": "OPEN,REOPENED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 10
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "FIXED",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "WONTFIX",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 0
+ </Link>
+ </td>
+ </tr>
+ <React.Fragment
+ key="42"
+ >
+ <tr>
+ <td
+ className="cwe-title-cell"
+ >
+ <React.Fragment>
+ CWE-42
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ <div
+ className="display-inline-flex-center"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ 1
+ </Link>
+ <Tooltip
+ overlay="metric.security_rating.tooltip.A"
+ >
+ <Link
+ className="link-no-underline spacer-left"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ <Rating
+ value={1}
+ />
+ </Link>
+ </Tooltip>
+ </div>
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolved": "false",
+ "statuses": "OPEN,REOPENED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 10
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "FIXED",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a2",
+ "resolutions": "WONTFIX",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 0
+ </Link>
+ </td>
+ </tr>
+ </React.Fragment>
+ </React.Fragment>
+ <React.Fragment
+ key="a3"
+ >
+ <tr>
+ <td
+ className=""
+ >
+ <React.Fragment>
+ A3
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ -
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ <td
+ className="text-right"
+ >
+ -
+ </td>
+ </tr>
+ <React.Fragment
+ key="42"
+ >
+ <tr>
+ <td
+ className="cwe-title-cell"
+ >
+ <React.Fragment>
+ CWE-42
+ </React.Fragment>
+ </td>
+ <td
+ className="text-right"
+ >
+ <div
+ className="display-inline-flex-center"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a3",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ 1
+ </Link>
+ <Tooltip
+ overlay="metric.security_rating.tooltip.A"
+ >
+ <Link
+ className="link-no-underline spacer-left"
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a3",
+ "resolved": "false",
+ "types": "VULNERABILITY",
+ },
+ }
+ }
+ >
+ <Rating
+ value={1}
+ />
+ </Link>
+ </Tooltip>
+ </div>
+ </td>
+ <td
+ className="text-right security-column-separator"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a3",
+ "resolved": "false",
+ "statuses": "OPEN,REOPENED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 10
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a3",
+ "resolutions": "FIXED",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 2
+ </Link>
+ </td>
+ <td
+ className="text-right"
+ >
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to={
+ Object {
+ "pathname": "/project/issues",
+ "query": Object {
+ "cwe": "42",
+ "id": "foo",
+ "owaspTop10": "a3",
+ "resolutions": "WONTFIX",
+ "statuses": "RESOLVED",
+ "types": "SECURITY_HOTSPOT",
+ },
+ }
+ }
+ >
+ 0
+ </Link>
+ </td>
+ </tr>
+ </React.Fragment>
+ </React.Fragment>
<React.Fragment
key="unknown"
>