]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-17393 Add new security tab for OWASP ASVS
authorRevanshu Paliwal <revanshu.paliwal@sonarsource.com>
Thu, 29 Sep 2022 10:08:27 +0000 (12:08 +0200)
committerPhilippe Perrin <philippe.perrin@sonarsource.com>
Fri, 7 Oct 2022 10:13:56 +0000 (12:13 +0200)
14 files changed:
server/sonar-web/src/main/js/apps/issues/__tests__/utils-test.ts
server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/IssuesApp-test.tsx.snap
server/sonar-web/src/main/js/apps/issues/sidebar/StandardFacet.tsx
server/sonar-web/src/main/js/apps/issues/utils.ts
server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsApp-test.tsx.snap
server/sonar-web/src/main/js/apps/security-hotspots/__tests__/__snapshots__/SecurityHotspotsAppRenderer-test.tsx.snap
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotSimpleList-test.tsx
server/sonar-web/src/main/js/apps/security-hotspots/utils.ts
server/sonar-web/src/main/js/helpers/__tests__/security-standard-test.ts
server/sonar-web/src/main/js/helpers/mocks/security-hotspots.ts
server/sonar-web/src/main/js/helpers/security-standard.ts
server/sonar-web/src/main/js/helpers/urls.ts
server/sonar-web/src/main/js/types/security.ts

index 9b01dc67a2822f36170aa631ba121814cdf66025..2f23a97d038765216ac00c0b0424adeb42718a2a 100644 (file)
@@ -53,6 +53,7 @@ describe('serialize/deserialize', () => {
         'owaspTop10-2021': ['a', 'b'],
         'pciDss-3.2': ['a', 'b'],
         'pciDss-4.0': ['a', 'b'],
+        'owaspAsvs-4.0': ['2'],
         projects: ['a', 'b'],
         resolutions: ['a', 'b'],
         resolved: true,
@@ -83,6 +84,7 @@ describe('serialize/deserialize', () => {
       'owaspTop10-2021': 'a,b',
       'pciDss-3.2': 'a,b',
       'pciDss-4.0': 'a,b',
+      'owaspAsvs-4.0': '2',
       projects: 'a,b',
       resolutions: 'a,b',
       rules: 'a,b',
index 84c81e0689f6655655771a6baabf38e81f41d322..31fcf90c9f7e158b4d610a1d866141152e121f75 100644 (file)
@@ -118,6 +118,7 @@ exports[`should show warnning when not all projects are accessible 1`] = `
               "inNewCodePeriod": false,
               "issues": Array [],
               "languages": Array [],
+              "owaspAsvs-4.0": Array [],
               "owaspTop10": Array [],
               "owaspTop10-2021": Array [],
               "pciDss-3.2": Array [],
index b093d6a73e18562f819033a0a8550e81ec3caf84..02b892f6bb057b848adef34d04cd33eda86ebd15 100644 (file)
@@ -98,7 +98,8 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
       cwe: {},
       sonarsourceSecurity: {},
       'pciDss-3.2': {},
-      'pciDss-4.0': {}
+      'pciDss-4.0': {},
+      'owaspAsvs-4.0': {}
     }
   };
 
@@ -137,7 +138,8 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
         cwe,
         sonarsourceSecurity,
         'pciDss-3.2': pciDss3_2,
-        'pciDss-4.0': pciDss4_0
+        'pciDss-4.0': pciDss4_0,
+        'owaspAsvs-4.0': owaspAsvs4_0
       }: Standards) => {
         if (this.mounted) {
           this.setState({
@@ -148,7 +150,8 @@ export default class StandardFacet extends React.PureComponent<Props, State> {
               cwe,
               sonarsourceSecurity,
               'pciDss-3.2': pciDss3_2,
-              'pciDss-4.0': pciDss4_0
+              'pciDss-4.0': pciDss4_0,
+              'owaspAsvs-4.0': owaspAsvs4_0
             }
           });
         }
index c3023256cb6fba37f41d2ac58bcf482ea667f76f..9eac3657ed8da3fd506896222985641d73ea0a0a 100644 (file)
@@ -38,6 +38,8 @@ import { SecurityStandard } from '../../types/security';
 import { Dict, Issue, Paging, RawQuery } from '../../types/types';
 import { UserBase } from '../../types/users';
 
+const OWASP_ASVS_4_0 = 'owaspAsvs-4.0';
+
 export interface Query {
   assigned: boolean;
   assignees: string[];
@@ -55,6 +57,7 @@ export interface Query {
   'owaspTop10-2021': string[];
   'pciDss-3.2': string[];
   'pciDss-4.0': string[];
+  [OWASP_ASVS_4_0]: string[];
   projects: string[];
   resolutions: string[];
   resolved: boolean;
@@ -95,6 +98,7 @@ export function parseQuery(query: RawQuery): Query {
     'owaspTop10-2021': parseAsArray(query['owaspTop10-2021'], parseAsString),
     'pciDss-3.2': parseAsArray(query['pciDss-3.2'], parseAsString),
     'pciDss-4.0': parseAsArray(query['pciDss-4.0'], parseAsString),
+    [OWASP_ASVS_4_0]: parseAsArray(query[OWASP_ASVS_4_0], parseAsString),
     projects: parseAsArray(query.projects, parseAsString),
     resolutions: parseAsArray(query.resolutions, parseAsString),
     resolved: parseAsBoolean(query.resolved),
@@ -139,6 +143,7 @@ export function serializeQuery(query: Query): RawQuery {
     'owaspTop10-2021': serializeStringArray(query['owaspTop10-2021']),
     'pciDss-3.2': serializeStringArray(query['pciDss-3.2']),
     'pciDss-4.0': serializeStringArray(query['pciDss-4.0']),
+    [OWASP_ASVS_4_0]: serializeStringArray(query[OWASP_ASVS_4_0]),
     projects: serializeStringArray(query.projects),
     resolutions: serializeStringArray(query.resolutions),
     resolved: query.resolved ? undefined : 'false',
@@ -228,9 +233,8 @@ export function getSelectedLocation(
     locations.length >= selectedLocationIndex
   ) {
     return locations[selectedLocationIndex];
-  } else {
-    return undefined;
   }
+  return undefined;
 }
 
 export function allLocationsEmpty(
index 260afe05f416ea443c518de1994f01f9e76b0597..d4669b900650936eaffab6f9225071b0ad999b15 100644 (file)
@@ -99,7 +99,8 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
         [SecurityStandard.SONARSOURCE]: {},
         [SecurityStandard.CWE]: {},
         [SecurityStandard.PCI_DSS_3_2]: {},
-        [SecurityStandard.PCI_DSS_4_0]: {}
+        [SecurityStandard.PCI_DSS_4_0]: {},
+        [SecurityStandard.OWASP_ASVS_4_0]: {}
       },
       filters: {
         ...this.constructFiltersFromProps(props),
@@ -454,6 +455,7 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
         [SecurityStandard.OWASP_TOP10_2021]: undefined,
         [SecurityStandard.PCI_DSS_3_2]: undefined,
         [SecurityStandard.PCI_DSS_4_0]: undefined,
+        [SecurityStandard.OWASP_ASVS_4_0]: undefined,
         file: undefined
       }
     });
index 4b6a0206bfb73c0b030dfc0b1a900415a648bf97..1891d1068b1ae1cf3042c66bfc4a579978203ed4 100644 (file)
@@ -56,6 +56,7 @@ exports[`should render correctly 1`] = `
   standards={
     Object {
       "cwe": Object {},
+      "owaspAsvs-4.0": Object {},
       "owaspTop10": Object {},
       "owaspTop10-2021": Object {},
       "pciDss-3.2": Object {},
index 9a9fc6218915af69b4c1b830b731f1e504176514..6e3c4c9c0db699a2f34120de5ad9c00f5f0c7e43 100644 (file)
@@ -145,6 +145,11 @@ exports[`should render correctly when filtered by category or cwe: category 1`]
               "title": "No CWE associated",
             },
           },
+          "owaspAsvs-4.0": Object {
+            "1": Object {
+              "title": "New OWASP ASVS cat 1",
+            },
+          },
           "owaspTop10": Object {
             "a1": Object {
               "title": "Injection",
@@ -286,6 +291,11 @@ exports[`should render correctly when filtered by category or cwe: cwe 1`] = `
               "title": "No CWE associated",
             },
           },
+          "owaspAsvs-4.0": Object {
+            "1": Object {
+              "title": "New OWASP ASVS cat 1",
+            },
+          },
           "owaspTop10": Object {
             "a1": Object {
               "title": "Injection",
index 9a6602707861b2b79ab7367a0f091388d50e8351..29a57bf93fb07f6c33c93d34299881c87b369e4e 100644 (file)
@@ -79,7 +79,8 @@ function shallowRender(props: Partial<HotspotSimpleListProps> = {}) {
         sansTop25: {},
         sonarsourceSecurity: {},
         'pciDss-3.2': {},
-        'pciDss-4.0': {}
+        'pciDss-4.0': {},
+        'owaspAsvs-4.0': {}
       }}
       {...props}
     />
index 02f28614fd013980ba2f6db4269ab861b405f256..e425b2e8d9429a399e564ca72800f349634a6957 100644 (file)
@@ -20,6 +20,7 @@
 import { flatten, groupBy, sortBy } from 'lodash';
 import {
   renderCWECategory,
+  renderOwaspAsvs40Category,
   renderOwaspTop102021Category,
   renderOwaspTop10Category,
   renderPciDss32Category,
@@ -56,7 +57,8 @@ export const SECURITY_STANDARDS = [
   SecurityStandard.SANS_TOP25,
   SecurityStandard.CWE,
   SecurityStandard.PCI_DSS_3_2,
-  SecurityStandard.PCI_DSS_4_0
+  SecurityStandard.PCI_DSS_4_0,
+  SecurityStandard.OWASP_ASVS_4_0
 ];
 
 export const SECURITY_STANDARD_RENDERER = {
@@ -66,7 +68,8 @@ export const SECURITY_STANDARD_RENDERER = {
   [SecurityStandard.SONARSOURCE]: renderSonarSourceSecurityCategory,
   [SecurityStandard.CWE]: renderCWECategory,
   [SecurityStandard.PCI_DSS_3_2]: renderPciDss32Category,
-  [SecurityStandard.PCI_DSS_4_0]: renderPciDss40Category
+  [SecurityStandard.PCI_DSS_4_0]: renderPciDss40Category,
+  [SecurityStandard.OWASP_ASVS_4_0]: renderOwaspAsvs40Category
 };
 
 export function mapRules(rules: Array<{ key: string; name: string }>): Dict<string> {
index 38c76db01067b2312259caf3a6b44a57e57d48ce..1032221e9719ac0de57fd2553f0402bd6d5ddaec 100644 (file)
@@ -20,6 +20,7 @@
 import { Standards } from '../../types/security';
 import {
   renderCWECategory,
+  renderOwaspAsvs40Category,
   renderOwaspTop102021Category,
   renderOwaspTop10Category,
   renderPciDss32Category,
@@ -43,7 +44,8 @@ describe('renderCWECategory', () => {
     sansTop25: {},
     sonarsourceSecurity: {},
     'pciDss-3.2': {},
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render cwe categories correctly', () => {
     expect(renderCWECategory(standards, '1004')).toEqual(
@@ -66,7 +68,8 @@ describe('renderOwaspTop10Category', () => {
     sansTop25: {},
     sonarsourceSecurity: {},
     'pciDss-3.2': {},
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render owasp categories correctly', () => {
     expect(renderOwaspTop10Category(standards, 'a1')).toEqual('A1 - Injection');
@@ -88,7 +91,8 @@ describe('renderOwaspTop102021Category', () => {
     sansTop25: {},
     sonarsourceSecurity: {},
     'pciDss-3.2': {},
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render owasp categories correctly', () => {
     expect(renderOwaspTop102021Category(standards, 'a1')).toEqual('A1 - Injection');
@@ -110,7 +114,8 @@ describe('renderPciDss32Category', () => {
         title: 'Install and maintain a firewall configuration to protect cardholder data'
       }
     },
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render Pci Dss 3.2 correctly', () => {
     expect(renderPciDss32Category(standards, '1')).toEqual(
@@ -132,7 +137,8 @@ describe('renderPciDss40Category', () => {
       '1': {
         title: 'Install and maintain a firewall configuration to protect cardholder data'
       }
-    }
+    },
+    'owaspAsvs-4.0': {}
   };
   it('should render Pci Dss 4.0 correctly', () => {
     expect(renderPciDss40Category(standards, '1')).toEqual(
@@ -142,6 +148,31 @@ describe('renderPciDss40Category', () => {
   });
 });
 
+describe('renderOwaspAsvs40Category', () => {
+  const standards: Standards = {
+    cwe: {},
+    owaspTop10: {},
+    'owaspTop10-2021': {},
+    sansTop25: {},
+    sonarsourceSecurity: {},
+    'pciDss-3.2': {},
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {
+      '1': {
+        title: 'Main category'
+      },
+      '1.1': {
+        title: 'Sub category',
+        level: '2'
+      }
+    }
+  };
+  it('should render OwaspAsvs 4.0 correctly', () => {
+    expect(renderOwaspAsvs40Category(standards, '1')).toEqual('1 - Main category');
+    expect(renderOwaspAsvs40Category(standards, '1.1')).toEqual('1.1 - Sub category (Level 2)');
+  });
+});
+
 describe('renderSansTop25Category', () => {
   const standards: Standards = {
     cwe: {},
@@ -154,7 +185,8 @@ describe('renderSansTop25Category', () => {
     },
     sonarsourceSecurity: {},
     'pciDss-3.2': {},
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render sans categories correctly', () => {
     expect(renderSansTop25Category(standards, 'insecure-interaction')).toEqual(
@@ -183,7 +215,8 @@ describe('renderSonarSourceSecurityCategory', () => {
       }
     },
     'pciDss-3.2': {},
-    'pciDss-4.0': {}
+    'pciDss-4.0': {},
+    'owaspAsvs-4.0': {}
   };
   it('should render sonarsource categories correctly', () => {
     expect(renderSonarSourceSecurityCategory(standards, 'xss')).toEqual(
index 57026803263092db4875f29861203c0dfbafc84b..6ce02172949212ac8d9d9d7dac792e8c85555c7b 100644 (file)
@@ -193,6 +193,11 @@ export function mockStandards(): Standards {
       '2': {
         title: 'This is useless...'
       }
+    },
+    'owaspAsvs-4.0': {
+      '1': {
+        title: 'New OWASP ASVS cat 1'
+      }
     }
   };
 }
index 870f62e934fbcf31bbc91bb237df19470377a0a0..ab51b5f107ec812b4e3a5f60ea9fd512e7df2ded 100644 (file)
@@ -101,6 +101,15 @@ export function renderPciDss40Category(standards: Standards, category: string):
   return `${category} - ${record.title}`;
 }
 
+export function renderOwaspAsvs40Category(standards: Standards, category: string): string {
+  const record = standards['owaspAsvs-4.0'][category];
+  if (!record) {
+    return category;
+  }
+  const levelInfo = record.level ? ` (Level ${record.level})` : '';
+  return `${category} - ${record.title}${levelInfo}`;
+}
+
 function addPrefix(title: string, prefix: string, withPrefix: boolean) {
   return withPrefix ? `${prefix} ${title}` : title;
 }
index 73d69cfc6bbbed645ee09bf85ceb3887234091bb..c7d6cffd444e09ba2cdd7f4466e7304f9c95748a 100644 (file)
@@ -213,7 +213,8 @@ export function getComponentSecurityHotspotsUrl(componentKey: string, query: Que
         SecurityStandard.SANS_TOP25,
         SecurityStandard.CWE,
         SecurityStandard.PCI_DSS_3_2,
-        SecurityStandard.PCI_DSS_4_0
+        SecurityStandard.PCI_DSS_4_0,
+        SecurityStandard.OWASP_ASVS_4_0
       ])
     }),
     hash: ''
index b77e256874c124e1e65daeb0ea53115a1bbc94fa..eb5992ca939614693402cff42044941cf6fb50af 100644 (file)
@@ -26,11 +26,12 @@ export enum SecurityStandard {
   SONARSOURCE = 'sonarsourceSecurity',
   CWE = 'cwe',
   PCI_DSS_3_2 = 'pciDss-3.2',
-  PCI_DSS_4_0 = 'pciDss-4.0'
+  PCI_DSS_4_0 = 'pciDss-4.0',
+  OWASP_ASVS_4_0 = 'owaspAsvs-4.0'
 }
 
 export type StandardType = SecurityStandard;
 
 export type Standards = {
-  [key in StandardType]: Dict<{ title: string; description?: string }>;
+  [key in StandardType]: Dict<{ title: string; description?: string; level?: string }>;
 };