private final String category;
private final long vulnerabilities;
private final OptionalInt vulnerabiliyRating;
+ private final long inReviewSecurityHotspots;
private final long toReviewSecurityHotspots;
- private final long openSecurityHotspots;
private final long wontFixSecurityHotspots;
private final List<SecurityStandardCategoryStatistics> children;
private long activeRules;
private long totalRules;
- public SecurityStandardCategoryStatistics(String category, long vulnerabilities, OptionalInt vulnerabiliyRating, long toReviewSecurityHotspots, long openSecurityHotspots,
- long wontFixSecurityHotspots, @Nullable List<SecurityStandardCategoryStatistics> children) {
+ public SecurityStandardCategoryStatistics(String category, long vulnerabilities, OptionalInt vulnerabiliyRating, long inReviewSecurityHotspots, long toReviewSecurityHotspots,
+ long wontFixSecurityHotspots, @Nullable List<SecurityStandardCategoryStatistics> children) {
this.category = category;
this.vulnerabilities = vulnerabilities;
this.vulnerabiliyRating = vulnerabiliyRating;
+ this.inReviewSecurityHotspots = inReviewSecurityHotspots;
this.toReviewSecurityHotspots = toReviewSecurityHotspots;
- this.openSecurityHotspots = openSecurityHotspots;
this.wontFixSecurityHotspots = wontFixSecurityHotspots;
this.children = children;
}
return vulnerabiliyRating;
}
- public long getToReviewSecurityHotspots() {
- return toReviewSecurityHotspots;
+ public long getInReviewSecurityHotspots() {
+ return inReviewSecurityHotspots;
}
- public long getOpenSecurityHotspots() {
- return openSecurityHotspots;
+ public long getToReviewSecurityHotspots() {
+ return toReviewSecurityHotspots;
}
public long getWontFixSecurityHotspots() {
import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
import static org.sonar.api.issue.Issue.STATUS_CLOSED;
import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
+import static org.sonar.api.issue.Issue.STATUS_IN_REVIEW;
import static org.sonar.api.issue.Issue.STATUS_OPEN;
import static org.sonar.api.issue.Issue.STATUS_REOPENED;
import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
@Override
public void start() {
StateMachine.Builder builder = StateMachine.builder()
- .states(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED, STATUS_TO_REVIEW);
+ .states(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED, STATUS_TO_REVIEW, STATUS_IN_REVIEW);
buildManualTransitions(builder);
buildAutomaticTransitions(builder);
buildSecurityHotspotTransitions(builder);
private static void buildSecurityHotspotTransitions(StateMachine.Builder builder) {
builder
+ .transition(Transition.builder(DefaultTransitions.SET_AS_IN_REVIEW)
+ .from(STATUS_TO_REVIEW).to(STATUS_IN_REVIEW)
+ .conditions(new HasType(RuleType.SECURITY_HOTSPOT))
+ .requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN)
+ .build())
+
.transition(Transition.builder(DefaultTransitions.DETECT)
.from(STATUS_TO_REVIEW).to(STATUS_OPEN)
.conditions(new HasType(RuleType.SECURITY_HOTSPOT))
.functions(new SetType(RuleType.SECURITY_HOTSPOT))
.requiredProjectPermission(UserRole.SECURITYHOTSPOT_ADMIN)
.build())
- .transition(Transition.builder(DefaultTransitions.REQUEST_REVIEW)
- .from(STATUS_OPEN).to(STATUS_RESOLVED)
- .conditions(IsManualVulnerability.INSTANCE)
- .functions(new SetType(RuleType.SECURITY_HOTSPOT), new SetResolution(RESOLUTION_FIXED))
- .build())
- .transition(Transition.builder(DefaultTransitions.REQUEST_REVIEW)
- .from(STATUS_REOPENED).to(STATUS_RESOLVED)
- .conditions(IsManualVulnerability.INSTANCE)
- .functions(new SetType(RuleType.SECURITY_HOTSPOT), new SetResolution(RESOLUTION_FIXED))
- .build())
.transition(Transition.builder(DefaultTransitions.REJECT)
.from(STATUS_RESOLVED).to(STATUS_REOPENED)
.conditions(new HasType(RuleType.SECURITY_HOTSPOT), new HasResolution(RESOLUTION_FIXED))
.functions(SetClosed.INSTANCE, SetCloseDate.INSTANCE)
.automatic()
.build())
+ .transition(Transition.builder(AUTOMATIC_CLOSE_TRANSITION)
+ .from(STATUS_IN_REVIEW).to(STATUS_CLOSED)
+ .conditions(IsBeingClosed.INSTANCE, new HasType(RuleType.SECURITY_HOTSPOT))
+ .functions(SetClosed.INSTANCE, SetCloseDate.INSTANCE)
+ .automatic()
+ .build())
// Reopen issues that are marked as resolved but that are still alive.
.transition(Transition.builder("automaticreopen")
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.workflow;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.time.DateUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.sonar.api.issue.DefaultTransitions;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rules.RuleType;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.FieldDiffs;
+import org.sonar.core.issue.IssueChangeContext;
+import org.sonar.server.issue.IssueFieldsSetter;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
+import static org.sonar.api.issue.Issue.RESOLUTION_REMOVED;
+import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
+import static org.sonar.api.issue.Issue.STATUS_CLOSED;
+import static org.sonar.api.issue.Issue.STATUS_IN_REVIEW;
+import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
+import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
+import static org.sonar.db.rule.RuleTesting.XOO_X1;
+
+@RunWith(DataProviderRunner.class)
+public class IssueWorkflowForSecurityHotspotsTest {
+
+ private static final String[] ALL_STATUSES_LEADING_TO_CLOSED = new String[] {STATUS_TO_REVIEW, STATUS_IN_REVIEW, STATUS_RESOLVED};
+
+ private static final String[] SUPPORTED_RESOLUTIONS_FOR_UNCLOSING = new String[] {RESOLUTION_FIXED, RESOLUTION_REMOVED};
+
+ private IssueFieldsSetter updater = new IssueFieldsSetter();
+
+ private IssueWorkflow underTest = new IssueWorkflow(new FunctionExecutor(updater), updater);
+
+ @Test
+ public void list_out_transitions_in_status_to_review() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(STATUS_TO_REVIEW);
+
+ List<Transition> transitions = underTest.outTransitions(issue);
+
+ assertThat(keys(transitions)).containsOnly("setinreview", "detect", "clear");
+ }
+
+ @Test
+ public void list_out_transitions_in_status_in_review() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(STATUS_IN_REVIEW);
+
+ List<Transition> transitions = underTest.outTransitions(issue);
+
+ assertThat(keys(transitions)).isEmpty();
+ }
+
+ @Test
+ public void set_as_in_review() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue()
+ .setType(RuleType.SECURITY_HOTSPOT)
+ .setIsFromHotspot(true)
+ .setStatus(STATUS_TO_REVIEW);
+
+ boolean result = underTest.doManualTransition(issue, DefaultTransitions.SET_AS_IN_REVIEW, IssueChangeContext.createUser(new Date(), "USER1"));
+
+ assertThat(result).isTrue();
+ assertThat(issue.getStatus()).isEqualTo(STATUS_IN_REVIEW);
+ assertThat(issue.resolution()).isNull();
+ }
+
+ @Test
+ public void automatically_close_resolved_security_hotspots_in_status_to_review() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue()
+ .setType(RuleType.SECURITY_HOTSPOT)
+ .setResolution(null)
+ .setStatus(STATUS_TO_REVIEW)
+ .setNew(false)
+ .setBeingClosed(true);
+ Date now = new Date();
+
+ underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
+
+ assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED);
+ assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
+ assertThat(issue.closeDate()).isNotNull();
+ assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND));
+ }
+
+ @Test
+ public void automatically_close_resolved_security_hotspots_in_status_in_review() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue()
+ .setType(RuleType.SECURITY_HOTSPOT)
+ .setResolution(null)
+ .setStatus(STATUS_IN_REVIEW)
+ .setNew(false)
+ .setBeingClosed(true);
+ Date now = new Date();
+
+ underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
+
+ assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED);
+ assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
+ assertThat(issue.closeDate()).isNotNull();
+ assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND));
+ }
+
+ @Test
+ @UseDataProvider("allStatusesLeadingToClosed")
+ public void do_not_automatically_reopen_closed_issues_of_security_hotspots(String previousStatus) {
+ DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING)
+ .map(resolution -> {
+ DefaultIssue issue = newClosedIssue(resolution);
+ setStatusPreviousToClosed(issue, previousStatus);
+ issue.setType(RuleType.SECURITY_HOTSPOT);
+ return issue;
+ })
+ .toArray(DefaultIssue[]::new);
+ Date now = new Date();
+ underTest.start();
+
+ Arrays.stream(issues).forEach(issue -> {
+ underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
+
+ assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
+ assertThat(issue.updateDate()).isNull();
+ });
+ }
+
+ @Test
+ public void doAutomaticTransition_does_nothing_on_security_hotspots_in_to_review_status() {
+ DefaultIssue issue = new DefaultIssue()
+ .setKey("ABCDE")
+ .setRuleKey(XOO_X1)
+ .setResolution(null)
+ .setStatus(STATUS_TO_REVIEW);
+
+ underTest.start();
+ underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(new Date()));
+
+ assertThat(issue.status()).isEqualTo(STATUS_TO_REVIEW);
+ assertThat(issue.resolution()).isNull();
+ }
+
+ @Test
+ @UseDataProvider("allStatusesLeadingToClosed")
+ public void do_not_automatically_reopen_closed_issues_of_manual_vulnerability(String previousStatus) {
+ DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING)
+ .map(resolution -> {
+ DefaultIssue issue = newClosedIssue(resolution);
+ setStatusPreviousToClosed(issue, previousStatus);
+ issue.setIsFromHotspot(true);
+ return issue;
+ })
+ .toArray(DefaultIssue[]::new);
+ Date now = new Date();
+ underTest.start();
+
+ Arrays.stream(issues).forEach(issue -> {
+ underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
+
+ assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
+ assertThat(issue.updateDate()).isNull();
+ });
+ }
+
+ @DataProvider
+ public static Object[][] allStatusesLeadingToClosed() {
+ return Arrays.stream(ALL_STATUSES_LEADING_TO_CLOSED)
+ .map(t -> new Object[] {t})
+ .toArray(Object[][]::new);
+ }
+
+ @Test
+ public void do_not_allow_to_doManualTransition_when_condition_fails() {
+ underTest.start();
+ DefaultIssue issue = new DefaultIssue()
+ .setKey("ABCDE")
+ // Detect is only available on hotspot
+ .setType(RuleType.VULNERABILITY)
+ .setIsFromHotspot(true)
+ .setStatus(STATUS_RESOLVED)
+ .setResolution(RESOLUTION_WONT_FIX)
+ .setRuleKey(XOO_X1);
+
+ assertThat(underTest.doManualTransition(issue, DefaultTransitions.DETECT, IssueChangeContext.createScan(new Date()))).isFalse();
+ }
+
+ private static DefaultIssue newClosedIssue(String resolution) {
+ return new DefaultIssue()
+ .setKey("ABCDE")
+ .setRuleKey(RuleKey.of("js", "S001"))
+ .setResolution(resolution)
+ .setStatus(STATUS_CLOSED)
+ .setNew(false)
+ .setCloseDate(new Date(5_999_999L));
+ }
+
+ private static void setStatusPreviousToClosed(DefaultIssue issue, String previousStatus) {
+ addStatusChange(issue, new Date(), previousStatus, STATUS_CLOSED);
+ }
+
+ private static void addStatusChange(DefaultIssue issue, Date date, String previousStatus, String newStatus) {
+ issue.addChange(new FieldDiffs().setCreationDate(date).setDiff("status", previousStatus, newStatus));
+ }
+
+ private Collection<String> keys(List<Transition> transitions) {
+ return Collections2.transform(transitions, new Function<Transition, String>() {
+ @Override
+ public String apply(@Nullable Transition transition) {
+ return transition.key();
+ }
+ });
+ }
+}
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import org.junit.runner.RunWith;
import org.sonar.api.issue.DefaultTransitions;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RuleType;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.FieldDiffs;
import org.sonar.core.issue.IssueChangeContext;
import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
import static org.sonar.api.issue.Issue.STATUS_CLOSED;
import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
+import static org.sonar.api.issue.Issue.STATUS_IN_REVIEW;
import static org.sonar.api.issue.Issue.STATUS_OPEN;
import static org.sonar.api.issue.Issue.STATUS_REOPENED;
import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
-import static org.sonar.db.rule.RuleTesting.XOO_X1;
@RunWith(DataProviderRunner.class)
public class IssueWorkflowTest {
@Test
public void list_statuses() {
underTest.start();
- assertThat(underTest.statusKeys()).containsExactly(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED, STATUS_TO_REVIEW);
+
+ List<String> expectedStatus = new ArrayList<>();
+ // issues statuses
+ expectedStatus.addAll(Arrays.asList(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED));
+ // hostpots statuses
+ expectedStatus.addAll(Arrays.asList(STATUS_TO_REVIEW, STATUS_IN_REVIEW));
+
+ assertThat(underTest.statusKeys()).containsExactlyInAnyOrder(expectedStatus.toArray(new String[]{}));
}
@Test
assertThat(transitions).isEmpty();
}
- @Test
- public void list_out_transitions_from_security_hotspot_in_status_to_review() {
- underTest.start();
- DefaultIssue issue = new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(STATUS_TO_REVIEW);
-
- List<Transition> transitions = underTest.outTransitions(issue);
-
- assertThat(keys(transitions)).containsOnly("detect", "clear");
- }
-
@Test
public void fail_if_unknown_status_when_listing_transitions() {
underTest.start();
assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND));
}
- @Test
- public void automatically_close_resolved_security_hotspots_in_to_review() {
- underTest.start();
- DefaultIssue issue = new DefaultIssue()
- .setKey("ABCDE")
- .setType(RuleType.SECURITY_HOTSPOT)
- .setRuleKey(XOO_X1)
- .setResolution(null)
- .setStatus(STATUS_TO_REVIEW)
- .setNew(false)
- .setBeingClosed(true);
- Date now = new Date();
-
- underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
-
- assertThat(issue.resolution()).isEqualTo(RESOLUTION_FIXED);
- assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
- assertThat(issue.closeDate()).isNotNull();
- assertThat(issue.updateDate()).isEqualTo(DateUtils.truncate(now, Calendar.SECOND));
- }
-
@Test
@UseDataProvider("allStatusesLeadingToClosed")
public void automatically_reopen_closed_issue_to_its_previous_status_from_changelog(String previousStatus) {
});
}
- @Test
- @UseDataProvider("allStatusesLeadingToClosed")
- public void do_not_automatically_reopen_closed_issues_of_security_hotspots(String previousStatus) {
- DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING)
- .map(resolution -> {
- DefaultIssue issue = newClosedIssue(resolution);
- setStatusPreviousToClosed(issue, previousStatus);
- issue.setType(RuleType.SECURITY_HOTSPOT);
- return issue;
- })
- .toArray(DefaultIssue[]::new);
- Date now = new Date();
- underTest.start();
-
- Arrays.stream(issues).forEach(issue -> {
- underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
-
- assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
- assertThat(issue.updateDate()).isNull();
- });
- }
-
- @Test
- public void doAutomaticTransition_does_nothing_on_security_hotspots_in_to_review_status() {
- DefaultIssue issue = new DefaultIssue()
- .setKey("ABCDE")
- .setRuleKey(XOO_X1)
- .setResolution(null)
- .setStatus(STATUS_TO_REVIEW);
-
- underTest.start();
- underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(new Date()));
-
- assertThat(issue.status()).isEqualTo(STATUS_TO_REVIEW);
- assertThat(issue.resolution()).isNull();
- }
-
- @Test
- @UseDataProvider("allStatusesLeadingToClosed")
- public void do_not_automatically_reopen_closed_issues_of_manual_vulnerability(String previousStatus) {
- DefaultIssue[] issues = Arrays.stream(SUPPORTED_RESOLUTIONS_FOR_UNCLOSING)
- .map(resolution -> {
- DefaultIssue issue = newClosedIssue(resolution);
- setStatusPreviousToClosed(issue, previousStatus);
- issue.setIsFromHotspot(true);
- return issue;
- })
- .toArray(DefaultIssue[]::new);
- Date now = new Date();
- underTest.start();
-
- Arrays.stream(issues).forEach(issue -> {
- underTest.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
-
- assertThat(issue.status()).isEqualTo(STATUS_CLOSED);
- assertThat(issue.updateDate()).isNull();
- });
- }
private static final String[] ALL_STATUSES_LEADING_TO_CLOSED = new String[] {STATUS_OPEN, STATUS_REOPENED, STATUS_CONFIRMED, STATUS_RESOLVED};
private static final String[] ALL_RESOLUTIONS_BEFORE_CLOSING = new String[] {
null,
assertThat(issue.assignee()).isNull();
}
- @Test
- public void do_not_allow_to_doManualTransition_when_condition_fails() {
- underTest.start();
- DefaultIssue issue = new DefaultIssue()
- .setKey("ABCDE")
- // Detect is only available on hotspot
- .setType(RuleType.VULNERABILITY)
- .setIsFromHotspot(true)
- .setStatus(STATUS_RESOLVED)
- .setResolution(RESOLUTION_WONT_FIX)
- .setRuleKey(XOO_X1);
-
- assertThat(underTest.doManualTransition(issue, DefaultTransitions.DETECT, IssueChangeContext.createScan(new Date()))).isFalse();
- }
-
private static DefaultIssue newClosedIssue(String resolution) {
return new DefaultIssue()
.setKey("ABCDE")
private static final int MAX_FACET_SIZE = 100;
private static final String AGG_VULNERABILITIES = "vulnerabilities";
private static final String AGG_SEVERITIES = "severities";
- private static final String AGG_OPEN_SECURITY_HOTSPOTS = "openSecurityHotspots";
private static final String AGG_TO_REVIEW_SECURITY_HOTSPOTS = "toReviewSecurityHotspots";
+ private static final String AGG_IN_REVIEW_SECURITY_HOTSPOTS = "inReviewSecurityHotspots";
private static final String AGG_WONT_FIX_SECURITY_HOTSPOTS = "wontFixSecurityHotspots";
private static final String AGG_CWES = "cwes";
private static final BoolQueryBuilder NON_RESOLVED_VULNERABILITIES_FILTER = boolQuery()
.filter(termQuery(FIELD_ISSUE_TYPE, VULNERABILITY.name()))
.mustNot(existsQuery(FIELD_ISSUE_RESOLUTION));
- private static final BoolQueryBuilder NON_RESOLVED_HOTSTPOS_FILTER = boolQuery()
+ private static final BoolQueryBuilder IN_REVIEW_HOTSPOTS_FILTER = boolQuery()
.filter(termQuery(FIELD_ISSUE_TYPE, SECURITY_HOTSPOT.name()))
+ .filter(termQuery(FIELD_ISSUE_STATUS, Issue.STATUS_IN_REVIEW))
.mustNot(existsQuery(FIELD_ISSUE_RESOLUTION));
private static final BoolQueryBuilder TO_REVIEW_HOTSPOTS_FILTER = boolQuery()
.filter(termQuery(FIELD_ISSUE_TYPE, SECURITY_HOTSPOT.name()))
- .filter(termQuery(FIELD_ISSUE_STATUS, Issue.STATUS_RESOLVED))
- .filter(termQuery(FIELD_ISSUE_RESOLUTION, Issue.RESOLUTION_FIXED));
+ .filter(termQuery(FIELD_ISSUE_STATUS, Issue.STATUS_TO_REVIEW))
+ .mustNot(existsQuery(FIELD_ISSUE_RESOLUTION));
private static final BoolQueryBuilder WONT_FIX_HOTSPOTS_FILTER = boolQuery()
.filter(termQuery(FIELD_ISSUE_TYPE, SECURITY_HOTSPOT.name()))
.filter(termQuery(FIELD_ISSUE_STATUS, Issue.STATUS_RESOLVED))
.mapToInt(b -> Severity.ALL.indexOf(b.getKeyAsString()) + 1)
.max();
- long openSecurityHotspots = ((InternalValueCount) ((InternalFilter) categoryBucket.getAggregations().get(AGG_OPEN_SECURITY_HOTSPOTS)).getAggregations().get(AGG_COUNT))
- .getValue();
long toReviewSecurityHotspots = ((InternalValueCount) ((InternalFilter) categoryBucket.getAggregations().get(AGG_TO_REVIEW_SECURITY_HOTSPOTS)).getAggregations().get(AGG_COUNT))
.getValue();
+ long inReviewSecurityHotspots = ((InternalValueCount) ((InternalFilter) categoryBucket.getAggregations().get(AGG_IN_REVIEW_SECURITY_HOTSPOTS)).getAggregations().get(AGG_COUNT))
+ .getValue();
long wontFixSecurityHotspots = ((InternalValueCount) ((InternalFilter) categoryBucket.getAggregations().get(AGG_WONT_FIX_SECURITY_HOTSPOTS)).getAggregations().get(AGG_COUNT))
.getValue();
- return new SecurityStandardCategoryStatistics(categoryName, vulnerabilities, severityRating, toReviewSecurityHotspots, openSecurityHotspots,
+ return new SecurityStandardCategoryStatistics(categoryName, vulnerabilities, severityRating, inReviewSecurityHotspots, toReviewSecurityHotspots,
wontFixSecurityHotspots, children);
}
AggregationBuilders.terms(AGG_SEVERITIES).field(FIELD_ISSUE_SEVERITY)
.subAggregation(
AggregationBuilders.count(AGG_COUNT).field(FIELD_ISSUE_KEY))))
- .subAggregation(AggregationBuilders.filter(AGG_OPEN_SECURITY_HOTSPOTS, NON_RESOLVED_HOTSTPOS_FILTER)
+ .subAggregation(AggregationBuilders.filter(AGG_TO_REVIEW_SECURITY_HOTSPOTS, TO_REVIEW_HOTSPOTS_FILTER)
.subAggregation(
AggregationBuilders.count(AGG_COUNT).field(FIELD_ISSUE_KEY)))
- .subAggregation(AggregationBuilders.filter(AGG_TO_REVIEW_SECURITY_HOTSPOTS, TO_REVIEW_HOTSPOTS_FILTER)
+ .subAggregation(AggregationBuilders.filter(AGG_IN_REVIEW_SECURITY_HOTSPOTS, IN_REVIEW_HOTSPOTS_FILTER)
.subAggregation(
AggregationBuilders.count(AGG_COUNT).field(FIELD_ISSUE_KEY)))
.subAggregation(AggregationBuilders.filter(AGG_WONT_FIX_SECURITY_HOTSPOTS, WONT_FIX_HOTSPOTS_FILTER)
.setQuery(
componentFilter
.should(NON_RESOLVED_VULNERABILITIES_FILTER)
- .should(NON_RESOLVED_HOTSTPOS_FILTER)
.should(TO_REVIEW_HOTSPOTS_FILTER)
+ .should(IN_REVIEW_HOTSPOTS_FILTER)
.should(WONT_FIX_HOTSPOTS_FILTER)
.minimumShouldMatch(1))
.setSize(0);
import org.sonar.server.issue.TransitionService;
import org.sonar.server.user.UserSession;
+import static java.lang.String.format;
+import static org.sonar.api.issue.DefaultTransitions.SET_AS_IN_REVIEW;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_DO_TRANSITION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TRANSITION;
WebService.NewAction action = controller.createAction(ACTION_DO_TRANSITION)
.setDescription("Do workflow transition on an issue. Requires authentication and Browse permission on project.<br/>" +
"The transitions '" + DefaultTransitions.WONT_FIX + "' and '" + DefaultTransitions.FALSE_POSITIVE + "' require the permission 'Administer Issues'.<br/>" +
- "The transitions involving security hotspots (except '" + DefaultTransitions.REQUEST_REVIEW + "') require the permission 'Administer Security Hotspot'.")
+ "The transitions involving security hotspots require the permission 'Administer Security Hotspot'.")
.setSince("3.6")
.setChangelog(
+ new Change("7.8", format("added transition '%s' for security hotspots ", SET_AS_IN_REVIEW)),
+ new Change("7.3", "added transitions for security hotspots"),
new Change("6.5", "the database ids of the components are removed from the response"),
- new Change("6.5", "the response field components.uuid is deprecated. Use components.key instead."),
- new Change("7.3", "added transitions for security hotspots"))
+ new Change("6.5", "the response field components.uuid is deprecated. Use components.key instead."))
.setHandler(this)
.setResponseExample(Resources.getResource(this.getClass(), "do_transition-example.json"))
.setPost(true);
RESOLVED_FP,
RESOLVED_WF,
RESOLVED_FIXED,
- TO_REVIEW;
+ TO_REVIEW,
+ IN_REVIEW;
protected static final Set<Status> CLOSED_STATUSES = EnumSet.of(CONFIRMED, RESOLVED_FIXED, RESOLVED_FP, RESOLVED_WF);
}
return QGChangeEventListener.Status.REOPENED;
case Issue.STATUS_TO_REVIEW:
return QGChangeEventListener.Status.TO_REVIEW;
+ case Issue.STATUS_IN_REVIEW:
+ return QGChangeEventListener.Status.IN_REVIEW;
case Issue.STATUS_RESOLVED:
return statusOfResolved(issue);
default:
ComponentDto project = newPrivateProjectDto(org);
ComponentDto another = newPrivateProjectDto(org);
indexIssues(
- newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN),
- newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
+ newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("anotherProject", another).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
- .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getOpenSecurityHotspots)
+ .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
.contains(
tuple("a1", 1L /* openhotspot1 */));
}
OrganizationDto org = newOrganizationDto();
ComponentDto project = newPrivateProjectDto(org);
indexIssues(
- newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN),
+ newDoc("openhotspot1", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
newDoc("closedHotspot", project).setOwaspTop10(asList("a1")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED));
List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, false);
assertThat(owaspTop10Report)
- .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getOpenSecurityHotspots)
+ .extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots)
.contains(
tuple("a1", 1L /* openhotspot1 */));
}
.collect(Collectors.toMap(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getChildren));
assertThat(cweByOwasp.get("a1")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
- SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
- SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
+ SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
.containsExactlyInAnyOrder(
tuple("123", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
tuple("unknown", 0L, OptionalInt.empty(), 1L /* openhotspot1 */, 0L, 0L));
assertThat(cweByOwasp.get("a3")).extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
- SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
- SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
+ SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
.containsExactlyInAnyOrder(
tuple("123", 2L /* openvul1, openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 0L, 0L),
tuple("456", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 0L, 1L /* toReviewHotspot */, 0L),
private List<SecurityStandardCategoryStatistics> indexIssuesAndAssertOwaspReport(boolean includeCwe) {
OrganizationDto org = newOrganizationDto();
ComponentDto project = newPrivateProjectDto(org);
- ComponentDto another = newPrivateProjectDto(org);
indexIssues(
- newDoc("openvul1", project).setOwaspTop10(asList("a1", "a3")).setCwe(asList("123", "456")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
- .setSeverity(Severity.MAJOR),
- newDoc("openvul2", project).setOwaspTop10(asList("a3", "a6")).setCwe(asList("123")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED)
- .setSeverity(Severity.MINOR),
- newDoc("notowaspvul", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
- .setSeverity(Severity.CRITICAL),
- newDoc("openhotspot1", project).setOwaspTop10(asList("a1", "a3")).setCwe(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT)
- .setStatus(Issue.STATUS_OPEN),
- newDoc("openhotspot2", project).setOwaspTop10(asList("a3", "a6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REOPENED),
- newDoc("toReviewHotspot", project).setOwaspTop10(asList("a5", "a3")).setCwe(asList("456")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_FIXED),
- newDoc("WFHotspot", project).setOwaspTop10(asList("a3", "a8")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_WONT_FIX),
- newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
+ newDoc("openvul1", project).setOwaspTop10(asList("a1", "a3")).setCwe(asList("123", "456")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.MAJOR),
+ newDoc("openvul2", project).setOwaspTop10(asList("a3", "a6")).setCwe(asList("123")).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_REOPENED).setSeverity(Severity.MINOR),
+ newDoc("notowaspvul", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
+ newDoc("toreviewhotspot1", project).setOwaspTop10(asList("a1", "a3")).setCwe(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("toreviewhotspot2", project).setOwaspTop10(asList("a3", "a6")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("inreviewhotspot", project).setOwaspTop10(asList("a5", "a3")).setCwe(asList("456")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
+ newDoc("WFHotspot", project).setOwaspTop10(asList("a3", "a8")).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX),
+ newDoc("notowasphotspot", project).setOwaspTop10(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
List<SecurityStandardCategoryStatistics> owaspTop10Report = underTest.getOwaspTop10Report(project.uuid(), false, includeCwe);
assertThat(owaspTop10Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
- SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
- SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
+ SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
.containsExactlyInAnyOrder(
- tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* openhotspot1 */, 0L, 0L),
+ tuple("a1", 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
tuple("a2", 0L, OptionalInt.empty(), 0L, 0L, 0L),
- tuple("a3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* openhotspot1,openhotspot2 */, 1L /* toReviewHotspot */, 1L /* WFHotspot */),
+ tuple("a3", 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* inReviewHotspot */, 1L /* WFHotspot */),
tuple("a4", 0L, OptionalInt.empty(), 0L, 0L, 0L),
- tuple("a5", 0L, OptionalInt.empty(), 0L, 1L/* toReviewHotspot */, 0L),
- tuple("a6", 1L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* openhotspot2 */, 0L, 0L),
+ tuple("a5", 0L, OptionalInt.empty(), 0L, 1L/* inReviewHotspot */, 0L),
+ tuple("a6", 1L /* openvul2 */, OptionalInt.of(2) /* MINOR = B */, 1L /* toreviewhotspot2 */, 0L, 0L),
tuple("a7", 0L, OptionalInt.empty(), 0L, 0L, 0L),
tuple("a8", 0L, OptionalInt.empty(), 0L, 0L, 1L /* WFHotspot */),
tuple("a9", 0L, OptionalInt.empty(), 0L, 0L, 0L),
newDoc("notopenvul", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity(Severity.BLOCKER),
- newDoc("notsansvul", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
- .setSeverity(Severity.CRITICAL),
- newDoc("openhotspot1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT)
- .setStatus(Issue.STATUS_OPEN),
- newDoc("openhotspot2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT)
- .setStatus(Issue.STATUS_REOPENED),
- newDoc("toReviewHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_FIXED),
- newDoc("WFHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_WONT_FIX),
- newDoc("notowasphotspot", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
+ newDoc("notsansvul", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
+ newDoc("toreviewhotspot1", project).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("toreviewhotspot2", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("inReviewHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
+ newDoc("WFHotspot", project).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX),
+ newDoc("notowasphotspot", project).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(project.uuid(), false, false);
assertThat(sansTop25Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
- SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
- SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
+ SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
.containsExactlyInAnyOrder(
- tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* openhotspot1 */, 0L, 0L),
- tuple(SANS_TOP_25_RISKY_RESOURCE, 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* openhotspot1,openhotspot2 */, 1L /* toReviewHotspot */,
- 1L /* WFHotspot */),
+ tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
+ tuple(SANS_TOP_25_RISKY_RESOURCE, 2L /* openvul1,openvul2 */, OptionalInt.of(3)/* MAJOR = C */, 2L/* toreviewhotspot1,toreviewhotspot2 */, 1L /* inReviewHotspot */,1L /* WFHotspot */),
tuple(SANS_TOP_25_POROUS_DEFENSES, 1L /* openvul2 */, OptionalInt.of(2)/* MINOR = B */, 1L/* openhotspot2 */, 0L, 0L));
assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
newDoc("notopenvul", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED)
.setSeverity(Severity.BLOCKER),
- newDoc("notsansvul", project2).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN)
- .setSeverity(Severity.CRITICAL),
- newDoc("openhotspot1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT)
- .setStatus(Issue.STATUS_OPEN),
- newDoc("openhotspot2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT)
- .setStatus(Issue.STATUS_REOPENED),
- newDoc("toReviewHotspot", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_FIXED),
- newDoc("WFHotspot", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED)
- .setResolution(Issue.RESOLUTION_WONT_FIX),
- newDoc("notowasphotspot", project1).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_OPEN));
+ newDoc("notsansvul", project2).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.VULNERABILITY).setStatus(Issue.STATUS_OPEN).setSeverity(Severity.CRITICAL),
+ newDoc("toreviewhotspot1", project1).setSansTop25(asList(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("toreviewhotspot2", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW),
+ newDoc("inReviewHotspot", project1).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW),
+ newDoc("WFHotspot", project2).setSansTop25(asList(SANS_TOP_25_RISKY_RESOURCE)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX),
+ newDoc("notowasphotspot", project1).setSansTop25(singletonList(UNKNOWN_STANDARD)).setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW));
indexView(portfolio1.uuid(), singletonList(project1.uuid()));
indexView(portfolio2.uuid(), singletonList(project2.uuid()));
List<SecurityStandardCategoryStatistics> sansTop25Report = underTest.getSansTop25Report(portfolio1.uuid(), true, false);
assertThat(sansTop25Report)
.extracting(SecurityStandardCategoryStatistics::getCategory, SecurityStandardCategoryStatistics::getVulnerabilities,
- SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getOpenSecurityHotspots,
- SecurityStandardCategoryStatistics::getToReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
+ SecurityStandardCategoryStatistics::getVulnerabiliyRating, SecurityStandardCategoryStatistics::getToReviewSecurityHotspots,
+ SecurityStandardCategoryStatistics::getInReviewSecurityHotspots, SecurityStandardCategoryStatistics::getWontFixSecurityHotspots)
.containsExactlyInAnyOrder(
- tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* openhotspot1 */, 0L, 0L),
- tuple(SANS_TOP_25_RISKY_RESOURCE, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* openhotspot1 */, 1L /* toReviewHotspot */, 0L),
+ tuple(SANS_TOP_25_INSECURE_INTERACTION, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L /* toreviewhotspot1 */, 0L, 0L),
+ tuple(SANS_TOP_25_RISKY_RESOURCE, 1L /* openvul1 */, OptionalInt.of(3)/* MAJOR = C */, 1L/* toreviewhotspot1 */, 1L /* inReviewHotspot */, 0L),
tuple(SANS_TOP_25_POROUS_DEFENSES, 0L, OptionalInt.empty(), 0L, 0L, 0L));
assertThat(sansTop25Report).allMatch(category -> category.getChildren().isEmpty());
public void test_status_mapping_on_security_hotspots() {
assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW)))
.isEqualTo(QGChangeEventListener.Status.TO_REVIEW);
+ assertThat(ChangedIssueImpl.statusOf(new DefaultIssue().setType(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_IN_REVIEW)))
+ .isEqualTo(QGChangeEventListener.Status.IN_REVIEW);
}
private void verifyListenerCalled(QGChangeEventListener listener, QGChangeEvent changeEvent, DefaultIssue... issues) {
{
"category": "a1",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "a2",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "a3",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a4",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a5",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a6",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a7",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a8",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a9",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a10",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "unknown",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "a1",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
"category": "a2",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"distribution": [],
"activeRules": 1,
{
"category": "a3",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a4",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a5",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a6",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a7",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a8",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a9",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "a10",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "unknown",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "porous-defenses",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "risky-resource",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
"category": "insecure-interaction",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 0,
"distribution": [
{
"cwe": "89",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 0,
"activeRules": 1,
"totalRules": 1
{
"category": "ldap-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "object-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "ssrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "insecure-conf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xxe",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "auth",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xpath-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "weak-cryptography",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "dos",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "open-redirect",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "log-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "csrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
"category": "sql-injection",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"distribution": [],
"activeRules": 1,
{
"category": "file-manipulation",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "expression-lang-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "rce",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xss",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "path-traversal-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "command-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "http-response-splitting",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "ldap-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "object-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "ssrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "insecure-conf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "xxe",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "auth",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "xpath-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "weak-cryptography",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "dos",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "open-redirect",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "log-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "csrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
"category": "sql-injection",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"distribution": [
{
"cwe": "89",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1
}
]
{
"category": "file-manipulation",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "expression-lang-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "rce",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "xss",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "path-traversal-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "command-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
},
{
"category": "http-response-splitting",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": []
}
{
"category": "ldap-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "object-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "ssrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "insecure-conf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xxe",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "auth",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xpath-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "weak-cryptography",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "dos",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "open-redirect",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "log-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "csrf",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
"category": "sql-injection",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"distribution": [
{
"cwe": "89",
"vulnerabilities": 1,
"vulnerabilityRating": 3,
+ "inReviewSecurityHotspots": 1,
"toReviewSecurityHotspots": 1,
- "openSecurityHotspots": 1,
"wontFixSecurityHotspots": 1,
"activeRules": 1,
"totalRules": 1
{
"category": "file-manipulation",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "expression-lang-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "rce",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "xss",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
{
"category": "path-traversal-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "command-injection",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 1,
{
"category": "http-response-splitting",
"vulnerabilities": 0,
+ "inReviewSecurityHotspots": 0,
"toReviewSecurityHotspots": 0,
- "openSecurityHotspots": 0,
"wontFixSecurityHotspots": 0,
"distribution": [],
"activeRules": 0,
import java.util.List;
import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
/**
* @since 3.6
String DETECT = "detect";
String DISMISS = "dismiss";
String REJECT = "reject";
- String REQUEST_REVIEW = "requestreview";
String ACCEPT = "accept";
String CLEAR = "clear";
String REOPEN_HOTSPOT = "reopenhotspot";
+ /**
+ * @since 7.8
+ */
+ String SET_AS_IN_REVIEW = "setinreview";
+
/**
* @since 4.4
*/
- List<String> ALL = asList(CONFIRM, UNCONFIRM, REOPEN, RESOLVE, FALSE_POSITIVE, WONT_FIX, CLOSE, DETECT, DISMISS, REJECT, REQUEST_REVIEW, ACCEPT, CLEAR, REOPEN_HOTSPOT);
+ List<String> ALL = unmodifiableList(asList(CONFIRM, UNCONFIRM, REOPEN, RESOLVE, FALSE_POSITIVE, WONT_FIX, CLOSE,
+ DETECT, DISMISS, REJECT, SET_AS_IN_REVIEW, ACCEPT, CLEAR, REOPEN_HOTSPOT));
}
*/
String STATUS_TO_REVIEW = "TOREVIEW";
+ /**
+ * @since 7.8
+ */
+ String STATUS_IN_REVIEW = "INREVIEW";
+
/**
* Return all available statuses
*
optional string category = 1;
optional int64 vulnerabilities = 2;
optional int64 vulnerabilityRating = 3;
- optional int64 toReviewSecurityHotspots = 4;
- optional int64 openSecurityHotspots = 5;
+ optional int64 inReviewSecurityHotspots = 4;
+ optional int64 toReviewSecurityHotspots = 5;
optional int64 wontFixSecurityHotspots = 6;
repeated CweStatistics distribution = 7;
optional int64 activeRules = 8;
optional string cwe = 1;
optional int64 vulnerabilities = 2;
optional int64 vulnerabilityRating = 3;
- optional int64 toReviewSecurityHotspots = 4;
- optional int64 openSecurityHotspots = 5;
+ optional int64 inReviewSecurityHotspots = 4;
+ optional int64 toReviewSecurityHotspots = 5;
optional int64 wontFixSecurityHotspots = 6;
optional int64 activeRules = 7;
optional int64 totalRules = 8;