cartography 0.94.0rc2__py3-none-any.whl → 0.94.0rc3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cartography might be problematic. Click here for more details.

@@ -13,47 +13,47 @@
13
13
  },
14
14
  {
15
15
  "__comment__": "not possible to identify if reachable && version specifier is the only flag of the vulnerability (likelihood = rare) && severity in [low, medium, high] -> Risk = Info",
16
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNKNOWN_EXPOSURE', reachability_check:'VERSION_SPECIFIER', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM', 'HIGH'] SET s.reachability_risk = 'INFO' return COUNT(*) as TotalCompleted",
16
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNREACHABLE', reachability_check:'NO REACHABILITY ANALYSIS', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM', 'HIGH'] SET s.reachability_risk = 'INFO' return COUNT(*) as TotalCompleted",
17
17
  "iterative": false
18
18
  },
19
19
  {
20
20
  "__comment__": "not possible to identify if reachable && version specifier is the only flag of the vulnerability (likelihood = rare) && severity = critical -> Risk = Low",
21
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNKNOWN_EXPOSURE', reachability_check:'VERSION_SPECIFIER', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
21
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'UNREACHABLE', reachability_check:'NO REACHABILITY ANALYSIS', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
22
22
  "iterative": false
23
23
  },
24
24
  {
25
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity in [low, medium] -> Risk = Low",
26
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
25
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity in [low, medium] -> Risk = Low",
26
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW', 'MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
27
27
  "iterative": false
28
28
  },
29
29
  {
30
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity = high -> Risk = Medium",
31
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
30
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity = high -> Risk = Medium",
31
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
32
32
  "iterative": false
33
33
  },
34
34
  {
35
- "__comment__": "manual review required to confirm && version specifier is the only flag of the vulnerability (likelihood = possible) && severity = critical -> Risk = High",
36
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'MANUAL_REVIEW_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'HIGH' return COUNT(*) as TotalCompleted",
35
+ "__comment__": "manual review required to confirm exploitation when conditions met && identified version is vulnerable (likelihood = possible) && severity = critical -> Risk = High",
36
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'CONDITIONALLY REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'HIGH' return COUNT(*) as TotalCompleted",
37
37
  "iterative": false
38
38
  },
39
39
  {
40
40
  "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity in [low, medium] -> Risk = Low",
41
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW','MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
41
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity IN ['LOW','MEDIUM'] SET s.reachability_risk = 'LOW' return COUNT(*) as TotalCompleted",
42
42
  "iterative": false
43
43
  },
44
44
  {
45
- "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity = high -> Risk = Low",
46
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
45
+ "__comment__": "adding the vulnerable version flags it reachable (likelihood = likely) && severity = high -> Risk = Medium",
46
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'HIGH' SET s.reachability_risk = 'MEDIUM' return COUNT(*) as TotalCompleted",
47
47
  "iterative": false
48
48
  },
49
49
  {
50
50
  "__comment__": "adding the vulnerable version flags it reachable (special case for critical, if something is so critical that needs to be fixed, likelihood = likely)) && severity = critical -> Risk = Critical",
51
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS_REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'CRITICAL' return COUNT(*) as TotalCompleted",
51
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'ALWAYS REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) WHERE s.severity = 'CRITICAL' SET s.reachability_risk = 'CRITICAL' return COUNT(*) as TotalCompleted",
52
52
  "iterative": false
53
53
  },
54
54
  {
55
55
  "__comment__": "if reachability analysis confirmed that is rechable (likelihood = certain) -> Risk = Severity",
56
- "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'REACHABILITY', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) SET s.reachability_risk = s.severity return COUNT(*) as TotalCompleted",
56
+ "query": "MATCH (g:GitHubRepository{archived:false})<-[:FOUND_IN]-(s:SemgrepSCAFinding{reachability:'REACHABLE', reachability_check:'REACHABLE', lastupdated:$UPDATE_TAG})<-[:RESOURCE]-(:SemgrepDeployment{id:$DEPLOYMENT_ID}) SET s.reachability_risk = s.severity return COUNT(*) as TotalCompleted",
57
57
  "iterative": false
58
58
  },
59
59
  {
@@ -3,10 +3,11 @@ from typing import Any
3
3
  from typing import Dict
4
4
  from typing import List
5
5
  from typing import Tuple
6
- from urllib.error import HTTPError
7
6
 
8
7
  import neo4j
9
8
  import requests
9
+ from requests.exceptions import HTTPError
10
+ from requests.exceptions import ReadTimeout
10
11
 
11
12
  from cartography.client.core.tx import load
12
13
  from cartography.graph.job import GraphJob
@@ -20,6 +21,7 @@ from cartography.util import timeit
20
21
 
21
22
  logger = logging.getLogger(__name__)
22
23
  stat_handler = get_stats_client(__name__)
24
+ _PAGE_SIZE = 500
23
25
  _TIMEOUT = (60, 60)
24
26
  _MAX_RETRIES = 3
25
27
 
@@ -48,60 +50,91 @@ def get_deployment(semgrep_app_token: str) -> Dict[str, Any]:
48
50
 
49
51
 
50
52
  @timeit
51
- def get_sca_vulns(semgrep_app_token: str, deployment_id: str) -> List[Dict[str, Any]]:
53
+ def get_sca_vulns(semgrep_app_token: str, deployment_slug: str) -> List[Dict[str, Any]]:
52
54
  """
53
55
  Gets the SCA vulns associated with the passed Semgrep App token and deployment id.
54
56
  param: semgrep_app_token: The Semgrep App token to use for authentication.
55
- param: deployment_id: The Semgrep deployment id to use for retrieving SCA vulns.
57
+ param: deployment_slug: The Semgrep deployment slug to use for retrieving SCA vulns.
56
58
  """
57
59
  all_vulns = []
58
- sca_url = f"https://semgrep.dev/api/v1/deployments/{deployment_id}/ssc-vulns"
60
+ sca_url = f"https://semgrep.dev/api/v1/deployments/{deployment_slug}/findings"
59
61
  has_more = True
60
- cursor: Dict[str, str] = {}
61
- page = 1
62
+ page = 0
62
63
  retries = 0
63
64
  headers = {
64
65
  "Content-Type": "application/json",
65
66
  "Authorization": f"Bearer {semgrep_app_token}",
66
67
  }
67
68
 
68
- request_data = {
69
- "deploymentId": deployment_id,
70
- "pageSize": 100,
71
- "exposure": ["UNREACHABLE", "REACHABLE", "UNKNOWN_EXPOSURE"],
72
- "refs": ["_default"],
69
+ request_data: dict[str, Any] = {
70
+ "page": page,
71
+ "page_size": _PAGE_SIZE,
72
+ "issue_type": "sca",
73
+ "exposures": "reachable,always_reachable,conditionally_reachable,unreachable,unknown",
74
+ "ref": "_default",
75
+ "dedup": "true",
73
76
  }
74
-
77
+ logger.info(f"Retrieving Semgrep SCA vulns for deployment '{deployment_slug}'.")
75
78
  while has_more:
76
79
 
77
- if cursor:
78
- request_data.update({
79
- "cursor": {
80
- "vulnOffset": cursor["vulnOffset"],
81
- "issueOffset": cursor["issueOffset"],
82
- },
83
- })
84
80
  try:
85
- response = requests.post(sca_url, json=request_data, headers=headers, timeout=_TIMEOUT)
81
+ response = requests.get(sca_url, params=request_data, headers=headers, timeout=_TIMEOUT)
86
82
  response.raise_for_status()
87
83
  data = response.json()
88
- except HTTPError as e:
84
+ except (ReadTimeout, HTTPError) as e:
89
85
  logger.warning(f"Failed to retrieve Semgrep SCA vulns for page {page}. Retrying...")
90
86
  retries += 1
91
87
  if retries >= _MAX_RETRIES:
92
88
  raise e
93
89
  continue
94
- vulns = data["vulns"]
95
- cursor = data.get("cursor")
96
- has_more = data.get("hasMore", False)
90
+ vulns = data["findings"]
91
+ has_more = len(vulns) > 0
97
92
  if page % 10 == 0:
98
- logger.info(f"Processed {page} pages of Semgrep SCA vulnerabilities so far.")
93
+ logger.info(f"Processed page {page} of Semgrep SCA vulnerabilities.")
99
94
  all_vulns.extend(vulns)
100
95
  retries = 0
96
+ page += 1
97
+ request_data["page"] = page
101
98
 
99
+ logger.info(f"Retrieved {len(all_vulns)} Semgrep SCA vulns in {page} pages.")
102
100
  return all_vulns
103
101
 
104
102
 
103
+ def _get_vuln_class(vuln: Dict) -> str:
104
+ vulnerability_classes = vuln["rule"].get("vulnerability_classes", [])
105
+ if vulnerability_classes:
106
+ return vulnerability_classes[0]
107
+ return "Other"
108
+
109
+
110
+ def _determine_exposure(vuln: Dict[str, Any]) -> str | None:
111
+ # See Semgrep reachability types:
112
+ # https://semgrep.dev/docs/semgrep-supply-chain/overview#types-of-semgrep-supply-chain-findings
113
+ reachability_types = {
114
+ "NO REACHABILITY ANALYSIS": 2,
115
+ "UNREACHABLE": 2,
116
+ "REACHABLE": 0,
117
+ "ALWAYS REACHABLE": 0,
118
+ "CONDITIONALLY REACHABLE": 1,
119
+ }
120
+ reachable_flag = vuln["reachability"]
121
+ if reachable_flag and reachable_flag.upper() in reachability_types:
122
+ reach_score = reachability_types[reachable_flag.upper()]
123
+ if reach_score < reachability_types["UNREACHABLE"]:
124
+ return "REACHABLE"
125
+ else:
126
+ return "UNREACHABLE"
127
+ return None
128
+
129
+
130
+ def _build_vuln_url(vuln: str) -> str | None:
131
+ if 'CVE' in vuln:
132
+ return f"https://nvd.nist.gov/vuln/detail/{vuln}"
133
+ if 'GHSA' in vuln:
134
+ return f"https://github.com/advisories/{vuln}"
135
+ return None
136
+
137
+
105
138
  def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Dict[str, str]]]:
106
139
  """
107
140
  Transforms the raw SCA vulns response from Semgrep API into a list of dicts
@@ -112,46 +145,59 @@ def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str,
112
145
  for vuln in raw_vulns:
113
146
  sca_vuln: Dict[str, Any] = {}
114
147
  # Mandatory fields
115
- sca_vuln["id"] = vuln["groupKey"]
116
- sca_vuln["repositoryName"] = vuln["repositoryName"]
117
- sca_vuln["ruleId"] = vuln["advisory"]["ruleId"]
118
- sca_vuln["title"] = vuln["advisory"]["title"]
119
- sca_vuln["description"] = vuln["advisory"]["description"]
120
- sca_vuln["ecosystem"] = vuln["advisory"]["ecosystem"]
121
- sca_vuln["severity"] = vuln["advisory"]["severity"]
122
- sca_vuln["reachability"] = vuln["advisory"]["reachability"]
123
- sca_vuln["reachableIf"] = vuln["advisory"]["reachableIf"]
124
- sca_vuln["exposureType"] = vuln["exposureType"]
125
- dependency = f"{vuln['matchedDependency']['name']}|{vuln['matchedDependency']['versionSpecifier']}"
148
+ repository_name = vuln["repository"]["name"]
149
+ rule_id = vuln["rule"]["name"]
150
+ vulnerability_class = _get_vuln_class(vuln)
151
+ package = vuln['found_dependency']['package']
152
+ sca_vuln["id"] = vuln["id"]
153
+ sca_vuln["repositoryName"] = repository_name
154
+ sca_vuln["branch"] = vuln["ref"]
155
+ sca_vuln["ruleId"] = rule_id
156
+ sca_vuln["title"] = package + ":" + vulnerability_class
157
+ sca_vuln["description"] = vuln["rule"]["message"]
158
+ sca_vuln["ecosystem"] = vuln["found_dependency"]["ecosystem"]
159
+ sca_vuln["severity"] = vuln["severity"].upper()
160
+ sca_vuln["reachability"] = vuln["reachability"].upper() # Check done to determine rechabilitity
161
+ sca_vuln["reachableIf"] = vuln["reachable_condition"].upper() if vuln["reachable_condition"] else None
162
+ sca_vuln["exposureType"] = _determine_exposure(vuln) # Determintes if reachable or unreachable
163
+ dependency = f"{package}|{vuln['found_dependency']['version']}"
126
164
  sca_vuln["matchedDependency"] = dependency
127
- sca_vuln["dependencyFileLocation_path"] = vuln["dependencyFileLocation"]["path"]
128
- sca_vuln["dependencyFileLocation_url"] = vuln["dependencyFileLocation"]["url"]
129
- # Optional fields
130
- sca_vuln["transitivity"] = vuln.get("transitivity", None)
131
- cves = vuln.get("advisory", {}).get("references", {}).get("cveIds")
132
- if len(cves) > 0:
133
- # Take the first CVE
134
- sca_vuln["cveId"] = vuln["advisory"]["references"]["cveIds"][0]
135
- if vuln.get('closestSafeDependency'):
136
- dep_fix = f"{vuln['closestSafeDependency']['name']}|{vuln['closestSafeDependency']['versionSpecifier']}"
165
+ dep_url = vuln["found_dependency"]["lockfile_line_url"]
166
+ if dep_url: # Lock file can be null, need to set
167
+ dep_file = dep_url.split("/")[-1].split("#")[0]
168
+ sca_vuln["dependencyFileLocation_path"] = dep_file
169
+ sca_vuln["dependencyFileLocation_url"] = dep_url
170
+ else:
171
+ if sca_vuln.get("location"):
172
+ sca_vuln["dependencyFileLocation_path"] = sca_vuln["location"]["file_path"]
173
+ sca_vuln["transitivity"] = vuln["found_dependency"]["transitivity"].upper()
174
+ if vuln.get("vulnerability_identifier"):
175
+ vuln_id = vuln["vulnerability_identifier"].upper()
176
+ sca_vuln["cveId"] = vuln_id
177
+ sca_vuln["ref_urls"] = [_build_vuln_url(vuln_id)]
178
+ if vuln.get('fix_recommendations') and len(vuln['fix_recommendations']) > 0:
179
+ fix = vuln['fix_recommendations'][0]
180
+ dep_fix = f"{fix['package']}|{fix['version']}"
137
181
  sca_vuln["closestSafeDependency"] = dep_fix
138
- if vuln["advisory"].get("references", {}).get("urls", []):
139
- sca_vuln["ref_urls"] = vuln["advisory"].get("references", {}).get("urls", [])
140
- sca_vuln["openedAt"] = vuln.get("openedAt", None)
141
- sca_vuln["announcedAt"] = vuln.get("announcedAt", None)
142
- sca_vuln["fixStatus"] = vuln["triage"]["status"]
143
- for usage in vuln.get("usages", []):
182
+ sca_vuln["openedAt"] = vuln["created_at"]
183
+ sca_vuln["fixStatus"] = vuln["status"]
184
+ sca_vuln["triageStatus"] = vuln["triage_state"]
185
+ sca_vuln["confidence"] = vuln["confidence"]
186
+ usage = vuln.get("usage")
187
+ if usage:
144
188
  usage_dict = {}
189
+ url = usage["location"]["url"]
145
190
  usage_dict["SCA_ID"] = sca_vuln["id"]
146
- usage_dict["findingId"] = usage["findingId"]
191
+ usage_dict["findingId"] = hash(url.split("github.com/")[-1])
147
192
  usage_dict["path"] = usage["location"]["path"]
148
- usage_dict["startLine"] = usage["location"]["startLine"]
149
- usage_dict["startCol"] = usage["location"]["startCol"]
150
- usage_dict["endLine"] = usage["location"]["endLine"]
151
- usage_dict["endCol"] = usage["location"]["endCol"]
152
- usage_dict["url"] = usage["location"]["url"]
193
+ usage_dict["startLine"] = usage["location"]["start_line"]
194
+ usage_dict["startCol"] = usage["location"]["start_col"]
195
+ usage_dict["endLine"] = usage["location"]["end_line"]
196
+ usage_dict["endCol"] = usage["location"]["end_col"]
197
+ usage_dict["url"] = url
153
198
  usages.append(usage_dict)
154
199
  vulns.append(sca_vuln)
200
+
155
201
  return vulns, usages
156
202
 
157
203
 
@@ -228,9 +274,10 @@ def sync(
228
274
  logger.info("Running Semgrep SCA findings sync job.")
229
275
  semgrep_deployment = get_deployment(semgrep_app_token)
230
276
  deployment_id = semgrep_deployment["id"]
277
+ deployment_slug = semgrep_deployment["slug"]
231
278
  load_semgrep_deployment(neo4j_sesion, semgrep_deployment, update_tag)
232
279
  common_job_parameters["DEPLOYMENT_ID"] = deployment_id
233
- raw_vulns = get_sca_vulns(semgrep_app_token, deployment_id)
280
+ raw_vulns = get_sca_vulns(semgrep_app_token, deployment_slug)
234
281
  vulns, usages = transform_sca_vulns(raw_vulns)
235
282
  load_semgrep_sca_vulns(neo4j_sesion, vulns, deployment_id, update_tag)
236
283
  load_semgrep_sca_usages(neo4j_sesion, usages, deployment_id, update_tag)
@@ -17,6 +17,7 @@ class SemgrepSCAFindingNodeProperties(CartographyNodeProperties):
17
17
  lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
18
18
  rule_id: PropertyRef = PropertyRef('ruleId', extra_index=True)
19
19
  repository: PropertyRef = PropertyRef('repositoryName', extra_index=True)
20
+ branch: PropertyRef = PropertyRef('branch')
20
21
  summary: PropertyRef = PropertyRef('title', extra_index=True)
21
22
  description: PropertyRef = PropertyRef('description')
22
23
  package_manager: PropertyRef = PropertyRef('ecosystem')
@@ -32,8 +33,9 @@ class SemgrepSCAFindingNodeProperties(CartographyNodeProperties):
32
33
  dependency_file: PropertyRef = PropertyRef('dependencyFileLocation_path', extra_index=True)
33
34
  dependency_file_url: PropertyRef = PropertyRef('dependencyFileLocation_url', extra_index=True)
34
35
  scan_time: PropertyRef = PropertyRef('openedAt')
35
- published_time: PropertyRef = PropertyRef('announcedAt')
36
36
  fix_status: PropertyRef = PropertyRef('fixStatus')
37
+ triage_status: PropertyRef = PropertyRef('triageStatus')
38
+ confidence: PropertyRef = PropertyRef('confidence')
37
39
 
38
40
 
39
41
  @dataclass(frozen=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cartography
3
- Version: 0.94.0rc2
3
+ Version: 0.94.0rc3
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Home-page: https://www.github.com/lyft/cartography
6
6
  Maintainer: Lyft
@@ -118,7 +118,7 @@ cartography/data/jobs/cleanup/okta_groups_cleanup.json,sha256=cBI3f_okl4pnVH48L1
118
118
  cartography/data/jobs/cleanup/okta_import_cleanup.json,sha256=4XQwYpY9vITLhnLpijMVa5PxO0Tm38CcMydnbPdQPm0,3798
119
119
  cartography/data/jobs/cleanup/pagerduty_import_cleanup.json,sha256=RJqG_Uw_QEGTer_-s2IuZ3a2kykhUcCdDNZu0S7SEB4,4457
120
120
  cartography/data/jobs/scoped_analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
121
- cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json,sha256=Nlx4xRISmn_RQjVoRO1qAc2KtkiGy8i4mUB1NBPjCVc,6451
121
+ cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json,sha256=eIYxbl5TdgVzN8En2JozWoyKAiIh3Dp8wUMkTDPGZY0,6485
122
122
  cartography/driftdetect/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
123
123
  cartography/driftdetect/__main__.py,sha256=Sz24Kxy5x6RC3GQEkuUDXzjOV3SvlHVkZdvPl1GLl5E,125
124
124
  cartography/driftdetect/add_shortcut.py,sha256=COtcCW9T0ss-bP1B2y9gEk3kN6HA01kkurSiDBNLzco,2377
@@ -271,7 +271,7 @@ cartography/intel/pagerduty/teams.py,sha256=aRubUXgEVVReyLrXAX_be1E_QBJv3Qlr4n77
271
271
  cartography/intel/pagerduty/users.py,sha256=oltGssxrnzYsV6QTGP1SsPoA1rCUDStj6vGlGWY695g,1623
272
272
  cartography/intel/pagerduty/vendors.py,sha256=WlDHExrWRBegDQKtxBV5nJiYgwoTLxNee4HrQDJ-Pdg,1559
273
273
  cartography/intel/semgrep/__init__.py,sha256=94vjdszGEosvXiKtYWKD34BRKwRbJxlBO1PZcKdxnFA,619
274
- cartography/intel/semgrep/findings.py,sha256=hbH_wL1XJDZDDrbIV_FjPv4A7oS2xM_hhMAbZlRm9po,9025
274
+ cartography/intel/semgrep/findings.py,sha256=9MSbDFrRUqb5nkEWN0R9Fx57RJMt27-9obpIHXNd45Y,10836
275
275
  cartography/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
276
276
  cartography/models/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
277
277
  cartography/models/aws/emr.py,sha256=TkuwoZnw_VHbJ5bwkac7-ZfwSLe_TeK3gxkuwGQOUk4,3037
@@ -330,12 +330,12 @@ cartography/models/lastpass/tenant.py,sha256=TG-9LFo9Sfzb9UgcTt_gFVTKocLItbgQMMP
330
330
  cartography/models/lastpass/user.py,sha256=SMTTYN6jgccc9k76hY3rVImElJOhHhZ9f1aZ6JzcrHw,3487
331
331
  cartography/models/semgrep/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
332
332
  cartography/models/semgrep/deployment.py,sha256=or5qZDuR51MXzINpH15jZrqmSUvXQevCNYWJ7D6v-JI,745
333
- cartography/models/semgrep/findings.py,sha256=xrn8sgXpNMrNJbKQagaAVxaCG9bVjTATSRR2XRBR4rg,5386
333
+ cartography/models/semgrep/findings.py,sha256=RPd-QzvP38fbTIqFARx6XpcZSsd5JM3KIg-ZlJA7NlE,5490
334
334
  cartography/models/semgrep/locations.py,sha256=kSk7Nn5Mn4Ob84MVZOo2GR0YFi-9Okq9pgA3FfC6_bk,3061
335
- cartography-0.94.0rc2.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
336
- cartography-0.94.0rc2.dist-info/METADATA,sha256=UEwu0NxrNz1H3YQWCQT4grTn4p_yvqC1nFoou0HCvig,1991
337
- cartography-0.94.0rc2.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
338
- cartography-0.94.0rc2.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
339
- cartography-0.94.0rc2.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
340
- cartography-0.94.0rc2.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
341
- cartography-0.94.0rc2.dist-info/RECORD,,
335
+ cartography-0.94.0rc3.dist-info/LICENSE,sha256=489ZXeW9G90up6ep-D1n-lJgk9ciNT2yxXpFgRSidtk,11341
336
+ cartography-0.94.0rc3.dist-info/METADATA,sha256=tLpNTYrbgBx0vbHg8TJxQjZNBaxVddNXi4O6ON5F-wk,1991
337
+ cartography-0.94.0rc3.dist-info/NOTICE,sha256=YOGAsjFtbyKj5tslYIg6V5jEYRuEvnSsIuDOUKj0Qj4,97
338
+ cartography-0.94.0rc3.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
339
+ cartography-0.94.0rc3.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
340
+ cartography-0.94.0rc3.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
341
+ cartography-0.94.0rc3.dist-info/RECORD,,