66import os
77import re
88from application .utils .external_project_parsers import base_parser_defs
9+ import json
10+ from pathlib import Path
11+ import logging
912from application .utils .external_project_parsers .base_parser_defs import (
1013 ParserInterface ,
1114 ParseResult ,
1619class Cheatsheets (ParserInterface ):
1720 name = "OWASP Cheat Sheets"
1821 cheatsheetseries_base_url = "https://cheatsheetseries.owasp.org/cheatsheets"
22+ supplement_data_file = (
23+ Path (__file__ ).resolve ().parent .parent
24+ / "data"
25+ / "owasp_cheatsheets_supplement.json"
26+ )
27+ logger = logging .getLogger (__name__ )
1928
2029 def cheatsheet (
2130 self , section : str , hyperlink : str , tags : List [str ]
@@ -41,10 +50,22 @@ def official_cheatsheet_url(self, markdown_filename: str) -> str:
4150 def parse (self , cache : db .Node_collection , ph : prompt_client .PromptHandler ):
4251 c_repo = "https://github.com/OWASP/CheatSheetSeries.git"
4352 cheatsheets_path = "cheatsheets/"
44- repo = git .clone (c_repo , sparse_paths = ["cheatsheets" ], sparse_cone = True )
45- cheatsheets = self .register_cheatsheets (
46- repo = repo , cache = cache , cheatsheets_path = cheatsheets_path , repo_path = c_repo
47- )
53+ cheatsheets = []
54+ try :
55+ repo = git .clone (c_repo , sparse_paths = ["cheatsheets" ], sparse_cone = True )
56+ cheatsheets = self .register_cheatsheets (
57+ repo = repo ,
58+ cache = cache ,
59+ cheatsheets_path = cheatsheets_path ,
60+ repo_path = c_repo ,
61+ )
62+ except Exception as exc :
63+ self .logger .warning (
64+ "Unable to clone OWASP CheatSheetSeries, continuing with supplemental cheat sheets only: %s" ,
65+ exc ,
66+ )
67+ cheatsheets .extend (self .register_supplemental_cheatsheets (cache = cache ))
68+ cheatsheets = self .deduplicate_entries (cheatsheets )
4869 results = {self .name : cheatsheets }
4970 base_parser_defs .validate_classification_tags (results )
5071 return ParseResult (results = results )
@@ -80,3 +101,36 @@ def register_cheatsheets(
80101 )
81102 standard_entries .append (cs )
82103 return standard_entries
104+
105+ def register_supplemental_cheatsheets (self , cache : db .Node_collection ):
106+ with self .supplement_data_file .open ("r" , encoding = "utf-8" ) as handle :
107+ supplement_entries = json .load (handle )
108+
109+ standard_entries = []
110+ for entry in supplement_entries :
111+ cs = self .cheatsheet (
112+ section = entry ["section" ],
113+ hyperlink = entry ["hyperlink" ],
114+ tags = [],
115+ )
116+ for cre_id in entry .get ("cre_ids" , []):
117+ cres = cache .get_CREs (external_id = cre_id )
118+ for cre in cres :
119+ try :
120+ cs .add_link (
121+ defs .Link (
122+ document = cre .shallow_copy (),
123+ ltype = defs .LinkTypes .AutomaticallyLinkedTo ,
124+ )
125+ )
126+ except Exception :
127+ continue
128+ if cs .links :
129+ standard_entries .append (cs )
130+ return standard_entries
131+
132+ def deduplicate_entries (self , entries : List [defs .Standard ]) -> List [defs .Standard ]:
133+ deduped = {}
134+ for entry in entries :
135+ deduped [(entry .section , entry .hyperlink )] = entry
136+ return list (deduped .values ())
0 commit comments