Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/common/models/cve.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ class Config:
)


class Epss(BaseModel):
class Config:
extra = Extra.forbid

score: Optional[confloat(ge=0.0, le=1.0)] = Field(
None, description='Epss score.'
)
percentile: Optional[confloat(ge=0.0, le=1.0)] = Field(
None, description='Epss percentile.'
)
date: Optional[date]= None

class Node(BaseModel):
"""
Defines a configuration node in an NVD applicability statement.
Expand All @@ -147,11 +159,13 @@ class Metrics(BaseModel):
"""

class Config:
extra = Extra.forbid
extra = Extra.forbid

cvssMetricV31: Optional[List[CvssV31]] = Field(None, description='CVSS V3.1 score.')
cvssMetricV30: Optional[List[CvssV30]] = Field(None, description='CVSS V3.0 score.')
cvssMetricV2: Optional[List[CvssV2]] = Field(None, description='CVSS V2.0 score.')
epss: Optional[Epss] = Field(None, description='EPSS details.')


class Config(BaseModel):
class Config:
Expand Down
8 changes: 4 additions & 4 deletions src/common/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ class SearchOptions(BaseModel):
cvssV3Metrics: Optional[str] = Field(default=None, description="CVSS V3.x vector string to search for", alias="cvss-metrics-v3")
cvssV2Severity: Optional[CveSeverityV2] = Field(default=None, description="CVSS V2.0 Severity to search for", alias="cvss-severity-v2")
cvssV3Severity: Optional[CveSeverityV3] = Field(default=None, description="CVSS V3.x Severity to search", alias="cvss-severity-v3")
epssScoreGt: Optional[float] = Field(default=None, description="Filter by EPSS score greater than", alias="epss-score-gt", ge=0) # New field for EPSS score greater than
epssScoreLt: Optional[float] = Field(default=None, description="Filter by EPSS score less than", alias="epss-score-lt", ge=0) # New field for EPSS score less than
epssPercGt: Optional[float] = Field(default=None, description="Filter by EPSS percentile greater than", alias="epss-perc-gt", ge=0) # New field for EPSS percentile greater than
epssPercLt: Optional[float] = Field(default=None, description="Filter by EPSS percentile less than", alias="epss-perc-lt", ge=0) # New field for EPSS percentile less than
lastModStartDate: Optional[date] = Field(default=None, description="Last modified start date", alias="last-mod-start-date")
lastModEndDate: Optional[date] = Field(default=None, description="Last modified end date", alias="last-mod-end-date")
pubStartDate: Optional[date] = Field(default=None, description="CVE Published start date", alias="pub-start-date")
Expand All @@ -93,10 +97,6 @@ class SearchOptions(BaseModel):
days: Optional[int] = Field(default=None, description="Number of days back when the CVEs were last modified", alias="days-back", ge=0)
deprecated: Optional[bool] = Field(default=False, description="If set to true, will fetch only the deprecated CPE names", alias="deprecated")
profile: Optional[bool] = Field(default=None, description="Would also run the profile execution of the search and save the results in a file")
epssScoreGt: Optional[float] = Field(default=None, description="Filter by EPSS score greater than", alias="epss-score-gt", gt=0) # New field for EPSS score greater than
epssScoreLt: Optional[float] = Field(default=None, description="Filter by EPSS score less than", alias="epss-score-lt", gt=0) # New field for EPSS score less than
epssPercGt: Optional[float] = Field(default=None, description="Filter by EPSS percentile greater than", alias="epss-perc-gt", ge=0, le=1) # New field for EPSS percentile greater than
epssPercLt: Optional[float] = Field(default=None, description="Filter by EPSS percentile less than", alias="epss-perc-lt", ge=0, le=1) # New field for EPSS percentile less than
output: OutputType = Field(default=OutputType.json, description="Define the output format")

class Config:
Expand Down
8 changes: 4 additions & 4 deletions src/common/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ def search_cves(appctx: ApplicationContext, opts: SearchOptions):
# prepare the search query
query = session.query(cve_table)
# Filter by EPSS score
if opts.epssScoreGt is not None:
if opts.epssScoreGt:
query = query.filter(cast(cve_table.data['metrics']['epss']['score'].astext, Numeric) > opts.epssScoreGt)
if opts.epssScoreLt is not None:
if opts.epssScoreLt:
query = query.filter(cast(cve_table.data['metrics']['epss']['score'].astext, Numeric) < opts.epssScoreLt)

# Filter by EPSS percentile
if opts.epssPercGt is not None:
if opts.epssPercGt:
query = query.filter(cast(cve_table.data['metrics']['epss']['percentile'].astext, Numeric) > opts.epssPercGt)
if opts.epssPercLt is not None:
if opts.epssPercLt:
query = query.filter(cast(cve_table.data['metrics']['epss']['percentile'].astext, Numeric) < opts.epssPercLt)

# filter by the cve IDS, either directly specified in the search options
Expand Down
10 changes: 9 additions & 1 deletion src/web/models/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class StatusOutput(BaseModel):
cve: Optional[StatusItemOutput]
cpe: Optional[StatusItemOutput]
cwe: Optional[StatusItemOutput]

epss: Optional[StatusItemOutput]

class SearchInputCommon:

Expand Down Expand Up @@ -61,6 +61,10 @@ def __init__(self, *,
cvss_v3_severity: Optional[CveSeverityV3] = Query(default=None, description="CVSS V3.x Severity to search", alias="cvss-severity-v3"),
cvss_v2_metrics: Optional[str] = Query(default=None, description="CVSS V2.0 vector string to search for", alias="cvss-metrics-v2"),
cvss_v3_metrics: Optional[str] = Query(default=None, description="CVSS V3.x vector string to search for", alias="cvss-metrics-v3"),
epss_score_gt: Optional[float] = Query(default=None, description="Greater EPSS score float to search for", alias="epss-score-gt", ge=0, le=1),
epss_score_lt: Optional[float] = Query(default=None, description="Less EPSS score float to search for", alias="epss-score-lt", ge=0, le=1),
epss_perc_gt: Optional[float] = Query(default=None, description="Greater EPSS percentile float to search for", alias="epss-perc-gt", ge=0, le=1),
epss_perc_lt: Optional[float] = Query(default=None, description="Less EPSS percentile float to search for", alias="epss-perc-lt", ge=0, le=1),
vulnerable: Optional[bool] = Query(default=True, description="CVEs found by the CPEs that are marked as vulnerable", alias="vulnerable"),
days: Optional[int] = Query(default=None, description="Number of days back when the CVEs were last modified", alias="days-back", ge=0),

Expand All @@ -77,6 +81,10 @@ def __init__(self, *,
self.cvss_v3_severity = cvss_v3_severity
self.cvss_v2_metrics = cvss_v2_metrics
self.cvss_v3_metrics = cvss_v3_metrics
self.epss_Score_Gt = epss_score_gt
self.epss_Score_Lt = epss_score_lt
self.epss_Perc_Gt = epss_perc_gt
self.epss_Perc_Lt = epss_perc_lt
self.vulnerable = vulnerable
self.days = days

Expand Down
5 changes: 5 additions & 0 deletions src/web/routers/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,16 @@ async def search_cve(cmn_opts: SearchInputCommon = Depends(SearchInputCommon),
cvssV3Severity=cve_opts.cvss_v3_severity,
cvssV2Metrics=cve_opts.cvss_v2_metrics,
cvssV3Metrics=cve_opts.cvss_v3_metrics,
epssScoreGt=cve_opts.epss_Score_Gt,
epssScoreLt=cve_opts.epss_Score_Lt,
epssPercGt=cve_opts.epss_Perc_Gt,
epssPercLt=cve_opts.epss_Perc_Lt,
vulnerable=cve_opts.vulnerable,
days=cve_opts.days
)
except PydanticValidationError as exc:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(exc))

return search(appctx, opts)


Expand Down