cve/
published.rs

1use super::state::ConstValue;
2use super::*;
3use crate::common::{Description, ProblemType, Product, ProviderMetadata, Reference, Tag};
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6use std::ops::{Deref, DerefMut};
7use uuid::Uuid;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct State;
11
12const STATE_VALUE: &str = "PUBLISHED";
13
14impl Serialize for State {
15    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
16    where
17        S: Serializer,
18    {
19        serializer.serialize_str(STATE_VALUE)
20    }
21}
22
23impl<'de> Deserialize<'de> for State {
24    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
25    where
26        D: Deserializer<'de>,
27    {
28        deserializer
29            .deserialize_str(ConstValue(STATE_VALUE))
30            .map(|()| State)
31    }
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
35#[serde(rename_all = "camelCase")]
36pub struct Metadata {
37    pub state: State,
38
39    #[serde(flatten)]
40    pub common: common::Metadata,
41}
42
43impl Deref for Metadata {
44    type Target = common::Metadata;
45
46    fn deref(&self) -> &Self::Target {
47        &self.common
48    }
49}
50
51impl DerefMut for Metadata {
52    fn deref_mut(&mut self) -> &mut Self::Target {
53        &mut self.common
54    }
55}
56
57#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
58#[serde(rename_all = "camelCase")]
59pub struct Containers {
60    pub cna: CnaContainer,
61
62    #[serde(default, skip_serializing_if = "Vec::is_empty")]
63    pub adp: Vec<AdpContainer>,
64}
65
66#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
67#[serde(rename_all = "camelCase")]
68pub struct CnaContainer {
69    #[serde(flatten)]
70    pub common: common::CnaContainer,
71
72    /// The date/time this CVE ID was associated with a vulnerability by a CNA.
73    #[serde(default, skip_serializing_if = "Option::is_none")]
74    pub date_assigned: Option<Timestamp>,
75
76    /// If known, the date/time the vulnerability was disclosed publicly.
77    #[serde(default, skip_serializing_if = "Option::is_none")]
78    pub date_public: Option<Timestamp>,
79
80    /// A title, headline, or a brief phrase summarizing the CVE record. Eg., Buffer overflow in Example Soft.
81    #[serde(default, skip_serializing_if = "Option::is_none")]
82    pub title: Option<String>,
83
84    /// A list of multi-lingual descriptions of the vulnerability. E.g., [PROBLEMTYPE] in [COMPONENT] in [VENDOR] [PRODUCT] [VERSION] on [PLATFORMS] allows [ATTACKER] to [IMPACT] via [VECTOR]. OR [COMPONENT] in [VENDOR] [PRODUCT] [VERSION] [ROOT CAUSE], which allows [ATTACKER] to [IMPACT] via [VECTOR].
85    pub descriptions: Vec<Description>,
86
87    /// List of affected products.
88    pub affected: Vec<Product>,
89
90    /// This is problem type information (e.g. CWE identifier). Must contain: At least one entry, can be text, OWASP, CWE, please note that while only one is required you can use more than one (or indeed all three) as long as they are correct). (CNA requirement: [PROBLEMTYPE]).
91    #[serde(default, skip_serializing_if = "Vec::is_empty")]
92    pub problem_types: Vec<ProblemType>,
93
94    #[serde(default, skip_serializing_if = "Vec::is_empty")]
95    pub references: Vec<Reference>,
96
97    /// Collection of impacts of this vulnerability.
98    #[serde(default, skip_serializing_if = "Vec::is_empty")]
99    pub impacts: Vec<Impact>,
100
101    /// Collection of impact scores with attribution.
102    #[serde(default, skip_serializing_if = "Vec::is_empty")]
103    pub metrics: Vec<Metric>,
104
105    /// Configurations required for exploiting this vulnerability.
106    #[serde(default, skip_serializing_if = "Vec::is_empty")]
107    pub configurations: Vec<Description>,
108
109    /// Workarounds and mitigations for this vulnerability.
110    #[serde(default, skip_serializing_if = "Vec::is_empty")]
111    pub workarounds: Vec<Description>,
112
113    /// Information about solutions or remediations available for this vulnerability.
114    #[serde(default, skip_serializing_if = "Vec::is_empty")]
115    pub solutions: Vec<Description>,
116
117    /// Information about exploits of the vulnerability.
118    #[serde(default, skip_serializing_if = "Vec::is_empty")]
119    pub exploits: Vec<Description>,
120
121    /// This is timeline information for significant events about this vulnerability or changes to the CVE Record.
122    #[serde(default, skip_serializing_if = "Vec::is_empty")]
123    pub timeline: Vec<Timeline>,
124
125    /// Statements acknowledging specific people, organizations, or tools recognizing the work done in researching, discovering, remediating or helping with activities related to this CVE.
126    #[serde(default, skip_serializing_if = "Vec::is_empty")]
127    pub credits: Vec<Credit>,
128
129    /// This is the source information (who discovered it, who researched it, etc.) and optionally a chain of CNA information (e.g. the originating CNA and subsequent parent CNAs who have processed it before it arrives at the MITRE root).\n Must contain: IF this is in the root level it MUST contain a CNA_chain entry, IF this source entry is NOT in the root (e.g. it is part of a vendor statement) then it must contain at least one type of data entry.
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub source: Option<Value>,
132
133    #[serde(default, skip_serializing_if = "Vec::is_empty")]
134    pub tags: Vec<Tag>,
135
136    /// List of taxonomy items related to the vulnerability.
137    #[serde(default, skip_serializing_if = "Vec::is_empty")]
138    pub taxonomy_mappings: Vec<TaxonomyMapping>,
139}
140
141#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
142#[serde(rename_all = "camelCase")]
143pub struct Impact {
144    /// CAPEC ID that best relates to this impact.
145    #[serde(default, skip_serializing_if = "Option::is_none")]
146    pub capec_id: Option<String>,
147
148    /// Prose description of the impact scenario. At a minimum provide the description given by CAPEC.
149    #[serde(default, skip_serializing_if = "Vec::is_empty")]
150    pub descriptions: Vec<Description>,
151}
152
153/// This is impact type information (e.g. a text description, CVSSv2, CVSSv3, CVSSv4, etc.). Must contain: At least one entry, can be text, CVSSv2, CVSSv3, others may be added.
154#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
155#[serde(rename_all = "camelCase")]
156pub struct Metric {
157    /// Name of the scoring format. This provides a bit of future proofing. Additional properties are not prohibited, so this will support the inclusion of proprietary formats. It also provides an easy future conversion mechanism when future score formats become part of the schema. example: cvssV44, format = 'cvssV44', other = cvssV4_4 JSON object. In the future, the other properties can be converted to score properties when they become part of the schema.
158    #[serde(default, skip_serializing_if = "Option::is_none")]
159    pub format: Option<String>,
160
161    /// Description of the scenarios this metrics object applies to. If no specific scenario is given, GENERAL is used as the default and applies when no more specific metric matches.
162    #[serde(default, skip_serializing_if = "Vec::is_empty")]
163    pub scenarios: Vec<Scenario>,
164
165    #[serde(default, skip_serializing_if = "Option::is_none")]
166    #[serde(rename = "cvssV4_0")]
167    pub cvss_v4_0: Option<Value>,
168
169    #[serde(default, skip_serializing_if = "Option::is_none")]
170    #[serde(rename = "cvssV3_1")]
171    pub cvss_v3_1: Option<Value>,
172
173    #[serde(default, skip_serializing_if = "Option::is_none")]
174    #[serde(rename = "cvssV3_0")]
175    pub cvss_v3_0: Option<Value>,
176
177    #[serde(default, skip_serializing_if = "Option::is_none")]
178    #[serde(rename = "cvssV2_0")]
179    pub cvss_v2_0: Option<Value>,
180
181    #[serde(default, skip_serializing_if = "Option::is_none")]
182    pub other: Option<OtherMetric>,
183}
184
185/// A non-standard impact description, may be prose or JSON block.
186#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
187#[serde(rename_all = "camelCase")]
188pub struct OtherMetric {
189    /// Name of the non-standard impact metrics format used.
190    pub r#type: String,
191    /// JSON object not covered by another metrics format.
192    pub content: Value,
193}
194
195#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
196#[serde(rename_all = "camelCase")]
197pub struct Scenario {
198    #[serde(rename = "lang")]
199    pub language: String,
200
201    /// Description of the scenario this metrics object applies to. If no specific scenario is given, GENERAL is used as the default and applies when no more specific metric matches.
202    #[serde(default = "Scenario::default_value")]
203    pub value: String,
204}
205
206impl Scenario {
207    pub fn default_value() -> String {
208        "GENERAL".to_string()
209    }
210}
211
212#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
213#[serde(rename_all = "camelCase")]
214pub struct Timeline {
215    /// Timestamp representing when the event in the timeline occurred. The timestamp format is based on RFC3339 and ISO ISO8601, with an optional timezone. yyyy-MM-ddTHH:mm:ssZZZZ - if the timezone offset is not given, GMT (0000) is assumed.
216    pub time: Timestamp,
217
218    /// The language used in the description of the event. The language field is included so that CVE Records can support translations. The value must be a BCP 47 language code.
219    #[serde(rename = "lang")]
220    pub language: String,
221
222    /// A summary of the event.
223    pub value: String,
224}
225
226#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
227#[serde(rename_all = "camelCase")]
228pub struct Credit {
229    /// The language used when describing the credits. The language field is included so that CVE Records can support translations. The value must be a BCP 47 language code.
230    #[serde(rename = "lang")]
231    pub language: String,
232
233    pub value: String,
234
235    /// UUID of the user being credited if present in the CVE User Registry (optional). This UUID can be used to lookup the user record in the user registry service.
236    #[serde(default, skip_serializing_if = "Option::is_none")]
237    pub user: Option<Uuid>,
238
239    /// Type or role of the entity being credited (optional).
240    #[serde(default, skip_serializing_if = "is_default_credit_type")]
241    pub r#type: CreditType,
242}
243
244fn is_default_credit_type(value: &CreditType) -> bool {
245    *value == CreditType::Finder
246}
247
248/// Type or role of the entity being credited.
249#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
250#[serde(rename_all = "lowercase")]
251pub enum CreditType {
252    /// identifies the vulnerability.
253    #[default]
254    Finder,
255    /// notifies the vendor of the vulnerability to a CNA.
256    Reporter,
257    /// validates the vulnerability to ensure accuracy or severity.
258    Analyst,
259    /// facilitates the coordinated response process.
260    Coordinator,
261    /// prepares a code change or other remediation plans.
262    #[serde(rename = "remediation developer")]
263    RemediationDeveloper,
264    /// reviews vulnerability remediation plans or code changes for effectiveness and completeness.
265    #[serde(rename = "remediation reviewer")]
266    RemediationReviewer,
267    /// tests and verifies the vulnerability or its remediation.
268    #[serde(rename = "remediation verifier")]
269    RemediationVerifier,
270    /// names of tools used in vulnerability discovery or identification.
271    Tool,
272    /// supports the vulnerability identification or remediation activities.
273    Sponsor,
274    Other,
275}
276
277#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
278#[serde(rename_all = "camelCase")]
279pub struct TaxonomyMapping {
280    /// The name of the taxonomy.
281    #[serde(rename = "taxonomyName")]
282    pub name: String,
283
284    /// The version of taxonomy the identifiers come from.
285    #[serde(default, skip_serializing_if = "Option::is_none")]
286    #[serde(rename = "taxonomyVersion")]
287    pub version: Option<String>,
288
289    /// List of relationships to the taxonomy for the vulnerability.  Relationships can be between the taxonomy and the CVE or two taxonomy items.
290    #[serde(rename = "taxonomyRelations")]
291    pub relations: Vec<TaxonomyRelation>,
292}
293
294#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
295#[serde(rename_all = "camelCase")]
296pub struct TaxonomyRelation {
297    /// Identifier of the item in the taxonomy.  Used as the subject of the relationship.
298    #[serde(rename = "taxonomyId")]
299    pub id: String,
300
301    /// A description of the relationship.
302    #[serde(rename = "relationshipName")]
303    pub name: String,
304
305    /// The target of the relationship.  Can be the CVE ID or another taxonomy identifier.
306    #[serde(rename = "relationshipValue")]
307    pub value: String,
308}
309
310#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
311#[serde(rename_all = "camelCase")]
312pub struct AdpContainer {
313    pub provider_metadata: ProviderMetadata,
314
315    /// If known, the date/time the vulnerability was disclosed publicly.
316    #[serde(default, skip_serializing_if = "Option::is_none")]
317    pub date_public: Option<Timestamp>,
318
319    /// A title, headline, or a brief phrase summarizing the information in an ADP container.
320    #[serde(default, skip_serializing_if = "Option::is_none")]
321    pub title: Option<String>,
322
323    /// A list of multi-lingual descriptions of the vulnerability. E.g., [PROBLEMTYPE] in [COMPONENT] in [VENDOR] [PRODUCT] [VERSION] on [PLATFORMS] allows [ATTACKER] to [IMPACT] via [VECTOR]. OR [COMPONENT] in [VENDOR] [PRODUCT] [VERSION] [ROOT CAUSE], which allows [ATTACKER] to [IMPACT] via [VECTOR].
324    #[serde(default, skip_serializing_if = "Vec::is_empty")]
325    pub descriptions: Vec<Description>,
326
327    /// List of affected products.
328    #[serde(default, skip_serializing_if = "Vec::is_empty")]
329    pub affected: Vec<Product>,
330
331    /// This is problem type information (e.g. CWE identifier). Must contain: At least one entry, can be text, OWASP, CWE, please note that while only one is required you can use more than one (or indeed all three) as long as they are correct). (CNA requirement: [PROBLEMTYPE]).
332    #[serde(default, skip_serializing_if = "Vec::is_empty")]
333    pub problem_types: Vec<ProblemType>,
334
335    #[serde(default, skip_serializing_if = "Vec::is_empty")]
336    pub references: Vec<Reference>,
337
338    /// Collection of impacts of this vulnerability.
339    #[serde(default, skip_serializing_if = "Vec::is_empty")]
340    pub impacts: Vec<Impact>,
341
342    /// Collection of impact scores with attribution.
343    #[serde(default, skip_serializing_if = "Vec::is_empty")]
344    pub metrics: Vec<Metric>,
345
346    /// Configurations required for exploiting this vulnerability.
347    #[serde(default, skip_serializing_if = "Vec::is_empty")]
348    pub configurations: Vec<Description>,
349
350    /// Workarounds and mitigations for this vulnerability.
351    #[serde(default, skip_serializing_if = "Vec::is_empty")]
352    pub workarounds: Vec<Description>,
353
354    /// Information about solutions or remediations available for this vulnerability.
355    #[serde(default, skip_serializing_if = "Vec::is_empty")]
356    pub solutions: Vec<Description>,
357
358    /// Information about exploits of the vulnerability.
359    #[serde(default, skip_serializing_if = "Vec::is_empty")]
360    pub exploits: Vec<Description>,
361
362    /// This is timeline information for significant events about this vulnerability or changes to the CVE Record.
363    #[serde(default, skip_serializing_if = "Vec::is_empty")]
364    pub timeline: Vec<Timeline>,
365
366    /// Statements acknowledging specific people, organizations, or tools recognizing the work done in researching, discovering, remediating or helping with activities related to this CVE.
367    #[serde(default, skip_serializing_if = "Vec::is_empty")]
368    pub credits: Vec<Credit>,
369
370    /// This is the source information (who discovered it, who researched it, etc.) and optionally a chain of CNA information (e.g. the originating CNA and subsequent parent CNAs who have processed it before it arrives at the MITRE root).\n Must contain: IF this is in the root level it MUST contain a CNA_chain entry, IF this source entry is NOT in the root (e.g. it is part of a vendor statement) then it must contain at least one type of data entry.
371    #[serde(default, skip_serializing_if = "Option::is_none")]
372    pub source: Option<Value>,
373
374    #[serde(default, skip_serializing_if = "Vec::is_empty")]
375    pub tags: Vec<Tag>,
376
377    /// List of taxonomy items related to the vulnerability.
378    #[serde(default, skip_serializing_if = "Vec::is_empty")]
379    pub taxonomy_mappings: Vec<TaxonomyMapping>,
380}
381
382#[cfg(test)]
383mod test {
384    use super::*;
385
386    #[test]
387    fn parse_metadata() {
388        let input = r#"
389{
390    "assignerOrgId": "8254265b-2729-46b6-b9e3-3dfca2d5bfca",
391    "assignerShortName": "mitre",
392    "cveId": "CVE-2013-7088",
393    "datePublished": "2019-11-15T14:19:48",
394    "dateReserved": "2013-12-12T00:00:00",
395    "dateUpdated": "2019-11-15T14:19:48",
396    "state": "PUBLISHED"
397}
398
399"#;
400        let _metadata: Metadata = serde_json::from_str(input).unwrap();
401    }
402
403    #[test]
404    fn default_value_returns_general() {
405        let value = Scenario::default_value();
406        assert_eq!(value, "GENERAL");
407    }
408}