1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.owasp.dependencycheck.xml.suppression;
19
20 import java.util.ArrayList;
21 import java.util.Calendar;
22 import java.util.List;
23 import javax.annotation.concurrent.NotThreadSafe;
24 import org.owasp.dependencycheck.exception.ParseException;
25 import org.owasp.dependencycheck.utils.DateUtil;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 import org.xml.sax.Attributes;
29 import org.xml.sax.SAXException;
30 import org.xml.sax.helpers.DefaultHandler;
31
32
33
34
35
36
37 @NotThreadSafe
38 public class SuppressionHandler extends DefaultHandler {
39
40
41
42
43 private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionHandler.class);
44
45
46
47
48 public static final String SUPPRESS = "suppress";
49
50
51
52 public static final String FILE_PATH = "filePath";
53
54
55
56 public static final String SHA1 = "sha1";
57
58
59
60 public static final String CVE = "cve";
61
62
63
64 public static final String VULNERABILITY_NAME = "vulnerabilityName";
65
66
67
68
69 public static final String NOTES = "notes";
70
71
72
73
74 public static final String CPE = "cpe";
75
76
77
78 public static final String CWE = "cwe";
79
80
81
82 public static final String GAV = "gav";
83
84
85
86 public static final String PACKAGE_URL = "packageUrl";
87
88
89
90 public static final String CVSS_BELOW = "cvssBelow";
91
92
93
94 private final List<SuppressionRule> suppressionRules = new ArrayList<>();
95
96
97
98 private SuppressionRule rule;
99
100
101
102 private Attributes currentAttributes;
103
104
105
106 private StringBuilder currentText;
107
108
109
110
111
112
113 public List<SuppressionRule> getSuppressionRules() {
114 return suppressionRules;
115 }
116
117
118
119
120
121
122
123
124
125
126 @Override
127 public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
128 currentAttributes = attributes;
129 currentText = new StringBuilder();
130 if (SUPPRESS.equals(qName)) {
131 rule = new SuppressionRule();
132 final String base = currentAttributes.getValue("base");
133 if (base != null) {
134 rule.setBase(Boolean.parseBoolean(base));
135 } else {
136 rule.setBase(false);
137 }
138 final String until = currentAttributes.getValue("until");
139 if (until != null) {
140 try {
141 rule.setUntil(DateUtil.parseXmlDate(until));
142 } catch (ParseException ex) {
143 throw new SAXException("Unable to parse until date in suppression file: " + until, ex);
144 }
145 }
146 }
147 }
148
149
150
151
152
153
154
155
156
157 @Override
158 public void endElement(String uri, String localName, String qName) throws SAXException {
159 if (null != qName) {
160 switch (qName) {
161 case SUPPRESS:
162 if (rule.getUntil() != null && rule.getUntil().before(Calendar.getInstance())) {
163 LOGGER.info("Suppression is expired for rule: {}", rule);
164 } else {
165 suppressionRules.add(rule);
166 }
167 rule = null;
168 break;
169 case FILE_PATH:
170 rule.setFilePath(processPropertyType());
171 break;
172 case SHA1:
173 rule.setSha1(currentText.toString().trim());
174 break;
175 case GAV:
176 rule.setGav(processPropertyType());
177 break;
178 case PACKAGE_URL:
179 rule.setPackageUrl(processPropertyType());
180 break;
181 case CPE:
182 rule.addCpe(processPropertyType());
183 break;
184 case CWE:
185 rule.addCwe(currentText.toString().trim());
186 break;
187 case CVE:
188 rule.addCve(currentText.toString().trim());
189 break;
190 case VULNERABILITY_NAME:
191 rule.addVulnerabilityName(processPropertyType());
192 break;
193 case NOTES:
194 rule.setNotes(currentText.toString().trim());
195 break;
196 case CVSS_BELOW:
197 final Double cvss = Double.valueOf(currentText.toString().trim());
198 rule.addCvssBelow(cvss);
199 break;
200 default:
201 break;
202 }
203 }
204 }
205
206
207
208
209
210
211
212
213
214 @Override
215 public void characters(char[] ch, int start, int length) throws SAXException {
216 currentText.append(ch, start, length);
217 }
218
219
220
221
222
223
224
225 private PropertyType processPropertyType() {
226 final PropertyType pt = new PropertyType();
227 pt.setValue(currentText.toString().trim());
228 if (currentAttributes != null && currentAttributes.getLength() > 0) {
229 final String regex = currentAttributes.getValue("regex");
230 if (regex != null) {
231 pt.setRegex(Boolean.parseBoolean(regex));
232 }
233 final String caseSensitive = currentAttributes.getValue("caseSensitive");
234 if (caseSensitive != null) {
235 pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
236 }
237 }
238 return pt;
239 }
240 }