Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8bf097cc
Commit
8bf097cc
authored
Dec 08, 2021
by
Savas Vedova
Committed by
Andrew Fontaine
Dec 08, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add details section to new vulnerability page
parent
7c704815
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
366 additions
and
10 deletions
+366
-10
ee/app/assets/javascripts/security_dashboard/store/constants.js
.../assets/javascripts/security_dashboard/store/constants.js
+8
-0
ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/new_vulnerability.vue
...lities/components/new_vulnerability/new_vulnerability.vue
+12
-0
ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/section_details.vue
...bilities/components/new_vulnerability/section_details.vue
+196
-0
ee/app/assets/javascripts/vulnerabilities/constants.js
ee/app/assets/javascripts/vulnerabilities/constants.js
+3
-0
ee/spec/frontend/vulnerabilities/new_vulnerability/new_vulnerability_spec.js
...lnerabilities/new_vulnerability/new_vulnerability_spec.js
+21
-10
ee/spec/frontend/vulnerabilities/new_vulnerability/section_details_spec.js
...vulnerabilities/new_vulnerability/section_details_spec.js
+81
-0
locale/gitlab.pot
locale/gitlab.pot
+45
-0
No files found.
ee/app/assets/javascripts/security_dashboard/store/constants.js
View file @
8bf097cc
...
...
@@ -2,6 +2,14 @@ import { s__ } from '~/locale';
export
const
VULNERABILITIES_PER_PAGE
=
20
;
export
const
DETECTION_METHODS
=
[
s__
(
'
Vulnerability|GitLab Security Report
'
),
s__
(
'
Vulnerability|External Security Report
'
),
s__
(
'
Vulnerability|Bug Bounty
'
),
s__
(
'
Vulnerability|Code Review
'
),
s__
(
'
Vulnerability|Security Audit
'
),
];
export
const
SEVERITY_LEVELS
=
{
critical
:
s__
(
'
severity|Critical
'
),
high
:
s__
(
'
severity|High
'
),
...
...
ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/new_vulnerability.vue
View file @
8bf097cc
...
...
@@ -2,14 +2,17 @@
import
{
GlForm
,
GlFormGroup
,
GlFormInput
,
GlFormTextarea
}
from
'
@gitlab/ui
'
;
import
MarkdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
import
SectionDetails
from
'
./section_details.vue
'
;
export
default
{
name
:
'
NewVulnerabilityForm
'
,
components
:
{
GlForm
,
GlFormGroup
,
GlFormInput
,
GlFormTextarea
,
MarkdownField
,
SectionDetails
,
},
props
:
{
markdownDocsPath
:
{
...
...
@@ -27,9 +30,17 @@ export default {
form
:
{
vulnerabilityName
:
''
,
vulnerabilityDesc
:
''
,
severity
:
''
,
status
:
''
,
detectionMethod
:
''
,
},
};
},
methods
:
{
updateFormValues
(
values
)
{
this
.
form
=
{
...
this
.
form
,
...
values
};
},
},
i18n
:
{
title
:
s__
(
'
VulnerabilityManagement|Add vulnerability finding
'
),
description
:
s__
(
...
...
@@ -106,6 +117,7 @@ export default {
</markdown-field>
</div>
</gl-form-group>
<section-details
@
change=
"updateFormValues"
/>
</gl-form>
</div>
</template>
ee/app/assets/javascripts/vulnerabilities/components/new_vulnerability/section_details.vue
0 → 100644
View file @
8bf097cc
<
script
>
import
{
GlFormGroup
,
GlFormInput
,
GlDropdown
,
GlDropdownItem
,
GlFormRadio
,
GlFormRadioGroup
,
}
from
'
@gitlab/ui
'
;
import
SeverityBadge
from
'
ee/vue_shared/security_reports/components/severity_badge.vue
'
;
import
{
VULNERABILITY_STATE_OBJECTS
}
from
'
ee/vulnerabilities/constants
'
;
import
{
SEVERITY_LEVELS
,
DETECTION_METHODS
}
from
'
ee/security_dashboard/store/constants
'
;
import
{
s__
,
__
}
from
'
~/locale
'
;
export
default
{
components
:
{
GlFormGroup
,
GlFormInput
,
GlDropdown
,
GlDropdownItem
,
GlFormRadio
,
GlFormRadioGroup
,
SeverityBadge
,
},
data
()
{
return
{
// Note: The cvss field is disabled during the MVC because the backend implementation
// is still missing. Since I learned this after implementing the design, I decided to
// hide it from the UI until the backend is ready so that we don't lose the work
// already completed.
showCvss
:
false
,
cvss
:
''
,
statusId
:
''
,
severity
:
''
,
detectionMethod
:
-
1
,
};
},
computed
:
{
selectedSeverity
()
{
return
this
.
severityOptions
.
find
(({
id
})
=>
id
===
this
.
severity
);
},
severityPlaceholder
()
{
return
this
.
selectedSeverity
?.
name
||
this
.
$options
.
i18n
.
severity
.
placeholder
;
},
cvssDescription
()
{
const
scores
=
this
.
$options
.
cvss
[
this
.
selectedSeverity
?.
id
];
if
(
!
scores
)
{
return
''
;
}
return
`
${
this
.
selectedSeverity
.
name
}
:
${
scores
[
0
].
toFixed
(
1
)}
-
${
scores
[
1
].
toFixed
(
1
)}
`
;
},
detectionMethodPlaceholder
()
{
return
(
this
.
detectionMethodOptions
.
find
(({
id
})
=>
id
===
this
.
detectionMethod
)?.
name
||
this
.
$options
.
i18n
.
detectionMethod
.
placeholder
);
},
detectionMethodOptions
()
{
return
Object
.
entries
(
DETECTION_METHODS
).
map
(([
id
,
name
])
=>
({
id
,
name
}));
},
severityOptions
()
{
return
Object
.
entries
(
SEVERITY_LEVELS
).
map
(([
id
,
name
])
=>
({
id
,
name
}));
},
statusOptions
()
{
return
[
{
...
VULNERABILITY_STATE_OBJECTS
.
detected
},
{
...
VULNERABILITY_STATE_OBJECTS
.
confirmed
},
{
...
VULNERABILITY_STATE_OBJECTS
.
resolved
},
];
},
},
methods
:
{
selectSeverity
(
value
)
{
this
.
severity
=
value
;
this
.
emitChanges
();
},
selectDetectionMethod
(
value
)
{
this
.
detectionMethod
=
value
;
this
.
emitChanges
();
},
emitChanges
()
{
this
.
$emit
(
'
change
'
,
{
status
:
this
.
statusId
,
severity
:
this
.
severity
,
detectionMethod
:
this
.
detectionMethod
,
});
},
},
cvss
:
{
none
:
[
0
,
0
],
low
:
[
0.1
,
3.9
],
medium
:
[
4.0
,
6.9
],
high
:
[
7.0
,
8.9
],
critical
:
[
9.0
,
10.0
],
},
i18n
:
{
title
:
s__
(
'
Vulnerability|Details
'
),
description
:
s__
(
'
Vulnerability|Information related how the vulnerability was discovered and its impact to the system.
'
,
),
detectionMethod
:
{
label
:
s__
(
'
Vulnerability|Detection method
'
),
placeholder
:
s__
(
'
VulnerabilityManagement|Select a method
'
),
},
severity
:
{
label
:
s__
(
'
Vulnerability|Severity
'
),
placeholder
:
s__
(
'
Vulnerability|Select a severity
'
),
},
cvssLabel
:
s__
(
'
Vulnerability|CVSS v3
'
),
optional
:
__
(
'
Optional
'
),
status
:
{
label
:
__
(
'
Status
'
),
description
:
s__
(
'
Vulnerability|Set the status of the vulnerability finding based on the information available to you.
'
,
),
},
},
};
</
script
>
<
template
>
<div>
<header
class=
"gl-pt-4 gl-my-6 gl-border-t-gray-100 gl-border-t-solid gl-border-t-1"
>
<h3
class=
"gl-mt-0 gl-mb-3"
>
{{
$options
.
i18n
.
title
}}
</h3>
<p
data-testid=
"section-description"
>
{{
$options
.
i18n
.
description
}}
</p>
</header>
<gl-form-group
:label=
"$options.i18n.detectionMethod.label"
label-for=
"form-detection-method"
class=
"gl-mb-6"
>
<gl-dropdown
id=
"form-detection-method"
:text=
"detectionMethodPlaceholder"
>
<gl-dropdown-item
v-for=
"scanner in detectionMethodOptions"
:key=
"scanner.id"
is-check-item
:is-checked=
"detectionMethod === scanner.id"
@
click=
"selectDetectionMethod(scanner.id)"
>
{{
scanner
.
name
}}
</gl-dropdown-item>
</gl-dropdown>
</gl-form-group>
<div
class=
"gl-display-flex gl-mb-6"
>
<gl-form-group
:label=
"$options.i18n.severity.label"
label-for=
"form-severity"
class=
"gl-mr-6 gl-mb-0"
>
<gl-dropdown
id=
"form-severity"
:text=
"severityPlaceholder"
>
<gl-dropdown-item
v-for=
"
{ id } in severityOptions"
:key="id"
:is-checked="severity === id"
is-check-item
@click="selectSeverity(id)"
>
<severity-badge
:severity=
"id"
/>
</gl-dropdown-item>
</gl-dropdown>
</gl-form-group>
<gl-form-group
v-if=
"showCvss"
:description=
"cvssDescription"
class=
"gl-mb-0"
>
<label
for=
"form-cvss"
class=
"gl-display-block gl-mb-2"
>
{{
$options
.
i18n
.
cvssLabel
}}
<span
class=
"gl-font-weight-300"
>
(
{{
$options
.
i18n
.
optional
}}
)
</span></label
>
<gl-form-input
id=
"form-cvss"
v-model=
"cvss"
class=
"gl-mb-2"
type=
"text"
/>
</gl-form-group>
</div>
<gl-form-group
:label=
"$options.i18n.status.label"
>
<p>
{{
$options
.
i18n
.
status
.
description
}}
</p>
<gl-form-radio-group
:checked=
"statusId"
@
change=
"emitChanges"
>
<label
v-for=
"status in statusOptions"
:key=
"status.state"
class=
"gl-display-flex gl-mb-5 gl-font-weight-normal gl-overflow-break-word"
>
<gl-form-radio
v-model=
"statusId"
:value=
"status.state"
>
{{
status
.
buttonText
}}
<template
#help
>
<span
class=
"gl-text-gray-500"
>
{{
status
.
description
}}
</span>
</
template
>
</gl-form-radio>
</label>
</gl-form-radio-group>
</gl-form-group>
</div>
</template>
ee/app/assets/javascripts/vulnerabilities/constants.js
View file @
8bf097cc
...
...
@@ -20,6 +20,7 @@ export const VULNERABILITY_STATE_OBJECTS = {
buttonText
:
VULNERABILITY_STATES
.
detected
,
dropdownText
:
s__
(
'
VulnerabilityManagement|Needs triage
'
),
dropdownDescription
:
s__
(
'
VulnerabilityManagement|Requires assessment
'
),
description
:
s__
(
'
VulnerabilityManagement|An unverified non-confirmed finding
'
),
},
dismissed
:
{
action
:
'
dismiss
'
,
...
...
@@ -37,6 +38,7 @@ export const VULNERABILITY_STATE_OBJECTS = {
buttonText
:
VULNERABILITY_STATES
.
confirmed
,
dropdownText
:
__
(
'
Confirm
'
),
dropdownDescription
:
s__
(
'
VulnerabilityManagement|A true-positive and will fix
'
),
description
:
s__
(
'
VulnerabilityManagement|A verified true-positive vulnerability
'
),
},
resolved
:
{
action
:
'
resolve
'
,
...
...
@@ -44,6 +46,7 @@ export const VULNERABILITY_STATE_OBJECTS = {
buttonText
:
VULNERABILITY_STATES
.
resolved
,
dropdownText
:
__
(
'
Resolve
'
),
dropdownDescription
:
s__
(
'
VulnerabilityManagement|Verified as fixed or mitigated
'
),
description
:
s__
(
'
VulnerabilityManagement|A removed or remediated vulnerability
'
),
},
};
...
...
ee/spec/frontend/vulnerabilities/new_vulnerability/new_vulnerability_spec.js
View file @
8bf097cc
...
...
@@ -2,12 +2,15 @@ import { GlForm } from '@gitlab/ui';
import
MarkdownField
from
'
~/vue_shared/components/markdown/field.vue
'
;
import
{
mountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
NewVulnerability
from
'
ee/vulnerabilities/components/new_vulnerability/new_vulnerability.vue
'
;
import
SectionDetails
from
'
ee/vulnerabilities/components/new_vulnerability/section_details.vue
'
;
describe
(
'
New vulnerability component
'
,
()
=>
{
let
wrapper
;
const
markdownDocsPath
=
'
/path/to/markdown/docs
'
;
const
markdownPreviewPath
=
'
/path/to/markdown/preview
'
;
const
findSectionDetails
=
()
=>
wrapper
.
findComponent
(
SectionDetails
);
const
createWrapper
=
()
=>
{
return
mountExtended
(
NewVulnerability
,
{
propsData
:
{
...
...
@@ -39,16 +42,14 @@ describe('New vulnerability component', () => {
});
it
(
'
creates markdown editor with correct props
'
,
()
=>
{
expect
(
wrapper
.
findComponent
(
MarkdownField
).
props
()).
toEqual
(
expect
.
objectContaining
({
markdownDocsPath
,
markdownPreviewPath
,
textareaValue
:
''
,
canAttachFile
:
false
,
addSpacingClasses
:
false
,
isSubmitting
:
false
,
}),
);
expect
(
wrapper
.
findComponent
(
MarkdownField
).
props
()).
toMatchObject
({
markdownDocsPath
,
markdownPreviewPath
,
textareaValue
:
''
,
canAttachFile
:
false
,
addSpacingClasses
:
false
,
isSubmitting
:
false
,
});
});
it
.
each
`
...
...
@@ -62,4 +63,14 @@ describe('New vulnerability component', () => {
expect
(
wrapper
.
findByText
(
description
).
exists
()).
toBe
(
true
);
}
});
it
.
each
`
section | selector | fields
${
'
Details
'
}
|
${
findSectionDetails
}
|
${{
severity
:
'
low
'
,
detectionMethod
:
2
,
status
:
'
confirmed
'
}
}
`
(
'
mounts the section $section and reacts on the change event
'
,
({
selector
,
fields
})
=>
{
const
section
=
selector
();
expect
(
section
.
exists
()).
toBe
(
true
);
section
.
vm
.
$emit
(
'
change
'
,
fields
);
expect
(
wrapper
.
vm
.
form
).
toMatchObject
(
fields
);
});
});
ee/spec/frontend/vulnerabilities/new_vulnerability/section_details_spec.js
0 → 100644
View file @
8bf097cc
import
{
nextTick
}
from
'
vue
'
;
import
{
GlDropdown
,
GlDropdownItem
,
GlFormRadio
}
from
'
@gitlab/ui
'
;
import
{
mountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
SectionDetails
from
'
ee/vulnerabilities/components/new_vulnerability/section_details.vue
'
;
import
SeverityBadge
from
'
ee/vue_shared/security_reports/components/severity_badge.vue
'
;
describe
(
'
New vulnerability - Section Details
'
,
()
=>
{
let
wrapper
;
const
findDetectionMethodItem
=
(
at
)
=>
wrapper
.
findAllComponents
(
GlDropdown
).
at
(
0
).
findAllComponents
(
GlDropdownItem
).
at
(
at
);
const
findSeverityMethodItem
=
(
at
)
=>
wrapper
.
findAllComponents
(
GlDropdown
).
at
(
1
).
findAllComponents
(
GlDropdownItem
).
at
(
at
);
const
findStatusItem
=
(
at
)
=>
wrapper
.
findAllComponents
(
GlFormRadio
).
at
(
at
);
const
createWrapper
=
()
=>
{
return
mountExtended
(
SectionDetails
,
{});
};
beforeEach
(()
=>
{
wrapper
=
createWrapper
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
it
.
each
`
value | text
${
0
}
|
${
'
GitLab Security Report
'
}
${
1
}
|
${
'
External Security Report
'
}
${
2
}
|
${
'
Bug Bounty
'
}
${
3
}
|
${
'
Code Review
'
}
${
4
}
|
${
'
Security Audit
'
}
`
(
'
displays and handles detection method field: $text
'
,
({
value
,
text
})
=>
{
const
dropdownItem
=
findDetectionMethodItem
(
value
);
expect
(
dropdownItem
.
text
()).
toBe
(
text
);
dropdownItem
.
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
change
'
)[
0
][
0
]).
toEqual
({
detectionMethod
:
`
${
value
}
`
,
severity
:
''
,
status
:
''
,
});
});
it
.
each
`
index | value
${
0
}
|
${
'
critical
'
}
${
1
}
|
${
'
high
'
}
${
2
}
|
${
'
medium
'
}
${
3
}
|
${
'
low
'
}
${
4
}
|
${
'
unknown
'
}
${
5
}
|
${
'
info
'
}
`
(
'
displays and handles severity field: $value
'
,
({
index
,
value
})
=>
{
const
dropdownItem
=
findSeverityMethodItem
(
index
);
expect
(
dropdownItem
.
findComponent
(
SeverityBadge
).
props
(
'
severity
'
)).
toBe
(
value
);
dropdownItem
.
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
change
'
)[
0
][
0
]).
toEqual
({
detectionMethod
:
-
1
,
severity
:
value
,
status
:
''
,
});
});
it
.
each
`
index | value
${
0
}
|
${
'
detected
'
}
${
1
}
|
${
'
confirmed
'
}
${
2
}
|
${
'
resolved
'
}
`
(
'
displays and handles status field
'
,
async
({
index
,
value
})
=>
{
findStatusItem
(
index
).
trigger
(
'
click
'
);
await
nextTick
();
expect
(
wrapper
.
emitted
(
'
change
'
)[
0
][
0
]).
toEqual
({
detectionMethod
:
-
1
,
severity
:
''
,
status
:
value
,
});
});
});
locale/gitlab.pot
View file @
8bf097cc
...
...
@@ -38795,12 +38795,21 @@ msgstr ""
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
msgstr ""
msgid "VulnerabilityManagement|A removed or remediated vulnerability"
msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
msgid "VulnerabilityManagement|A verified true-positive vulnerability"
msgstr ""
msgid "VulnerabilityManagement|Add vulnerability finding"
msgstr ""
msgid "VulnerabilityManagement|An unverified non-confirmed finding"
msgstr ""
msgid "VulnerabilityManagement|Change status"
msgstr ""
...
...
@@ -38828,6 +38837,9 @@ msgstr ""
msgid "VulnerabilityManagement|Requires assessment"
msgstr ""
msgid "VulnerabilityManagement|Select a method"
msgstr ""
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
...
...
@@ -38897,9 +38909,18 @@ msgstr ""
msgid "Vulnerability|Additional Info"
msgstr ""
msgid "Vulnerability|Bug Bounty"
msgstr ""
msgid "Vulnerability|CVSS v3"
msgstr ""
msgid "Vulnerability|Class"
msgstr ""
msgid "Vulnerability|Code Review"
msgstr ""
msgid "Vulnerability|Comments"
msgstr ""
...
...
@@ -38915,21 +38936,33 @@ msgstr ""
msgid "Vulnerability|Description"
msgstr ""
msgid "Vulnerability|Details"
msgstr ""
msgid "Vulnerability|Detected"
msgstr ""
msgid "Vulnerability|Detection method"
msgstr ""
msgid "Vulnerability|Download"
msgstr ""
msgid "Vulnerability|Evidence"
msgstr ""
msgid "Vulnerability|External Security Report"
msgstr ""
msgid "Vulnerability|False positive detected"
msgstr ""
msgid "Vulnerability|File"
msgstr ""
msgid "Vulnerability|GitLab Security Report"
msgstr ""
msgid "Vulnerability|Identifier"
msgstr ""
...
...
@@ -38939,6 +38972,9 @@ msgstr ""
msgid "Vulnerability|Image"
msgstr ""
msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
msgstr ""
msgid "Vulnerability|Links"
msgstr ""
...
...
@@ -38963,6 +38999,15 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
msgid "Vulnerability|Security Audit"
msgstr ""
msgid "Vulnerability|Select a severity"
msgstr ""
msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
msgstr ""
msgid "Vulnerability|Severity"
msgstr ""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment