3434from pathlib import Path
3535from typing import Tuple , Union
3636
37- import yara
37+ yara = None
38+ try :
39+ import yara
40+ except ImportError :
41+ pass
3842
3943from nemoguardrails import RailsConfig
4044from nemoguardrails .actions import action
4549log = logging .getLogger (__name__ )
4650
4751
52+ def _check_yara_available ():
53+ if yara is None :
54+ raise ImportError (
55+ "The yara module is required for injection detection. "
56+ "Please install it using: pip install yara-python"
57+ )
58+
59+
4860def _validate_unpack_config (config : RailsConfig ) -> Tuple [str , Path , Tuple [str ]]:
4961 """
5062 Validates and unpacks the injection detection configuration.
@@ -117,7 +129,7 @@ def _validate_unpack_config(config: RailsConfig) -> Tuple[str, Path, Tuple[str]]
117129
118130
119131@lru_cache ()
120- def load_rules (yara_path : Path , rule_names : Tuple ) -> Union [yara .Rules , None ]:
132+ def load_rules (yara_path : Path , rule_names : Tuple ) -> Union [" yara.Rules" , None ]:
121133 """
122134 Loads and compiles YARA rules from the specified path and rule names.
123135
@@ -126,12 +138,15 @@ def load_rules(yara_path: Path, rule_names: Tuple) -> Union[yara.Rules, None]:
126138 rule_names (Tuple): A tuple of YARA rule names to load.
127139
128140 Returns:
129- Union[yara.Rules, None]: The compiled YARA rules object if successful,
141+ Union[' yara.Rules' , None]: The compiled YARA rules object if successful,
130142 or None if no rule names are provided.
131143
132144 Raises:
133145 yara.SyntaxError: If there is a syntax error in the YARA rules.
146+ ImportError: If the yara module is not installed.
134147 """
148+ _check_yara_available ()
149+
135150 if len (rule_names ) == 0 :
136151 log .warning (
137152 "Injection config was provided but no modules were specified. Returning None."
@@ -150,7 +165,7 @@ def load_rules(yara_path: Path, rule_names: Tuple) -> Union[yara.Rules, None]:
150165 return rules
151166
152167
153- def omit_injection (text : str , matches : list [yara .Match ]) -> str :
168+ def omit_injection (text : str , matches : list [" yara.Match" ]) -> str :
154169 """
155170 Attempts to strip the offending injection attempts from the provided text.
156171
@@ -160,11 +175,16 @@ def omit_injection(text: str, matches: list[yara.Match]) -> str:
160175
161176 Args:
162177 text (str): The text to check for command injection.
163- matches (list[yara.Match]): A list of YARA rule matches.
178+ matches (list[' yara.Match' ]): A list of YARA rule matches.
164179
165180 Returns:
166181 str: The text with the detected injections stripped out.
182+
183+ Raises:
184+ ImportError: If the yara module is not installed.
167185 """
186+ _check_yara_available ()
187+
168188 # Copy the text to a placeholder variable
169189 modified_text = text
170190 for match in matches :
@@ -180,7 +200,7 @@ def omit_injection(text: str, matches: list[yara.Match]) -> str:
180200 return modified_text
181201
182202
183- def sanitize_injection (text : str , matches : list [yara .Match ]) -> str :
203+ def sanitize_injection (text : str , matches : list [" yara.Match" ]) -> str :
184204 """
185205 Attempts to sanitize the offending injection attempts in the provided text.
186206 This is done by 'de-fanging' the offending content, transforming it into a state that will not execute
@@ -193,20 +213,23 @@ def sanitize_injection(text: str, matches: list[yara.Match]) -> str:
193213
194214 Args:
195215 text (str): The text to check for command injection.
196- matches (list[yara.Match]): A list of YARA rule matches.
216+ matches (list[' yara.Match' ]): A list of YARA rule matches.
197217
198218 Returns:
199219 str: The text with the detected injections sanitized.
200220
201221 Raises:
202222 NotImplementedError: If the sanitization logic is not implemented.
223+ ImportError: If the yara module is not installed.
203224 """
225+ _check_yara_available ()
226+
204227 raise NotImplementedError (
205228 "Injection sanitization is not yet implemented. Please use 'reject' or 'omit'"
206229 )
207230
208231
209- def reject_injection (text : str , rules : yara .Rules ) -> Tuple [bool , str ]:
232+ def reject_injection (text : str , rules : " yara.Rules" ) -> Tuple [bool , str ]:
210233 """
211234 Detects whether the provided text contains potential injection attempts.
212235
@@ -215,15 +238,18 @@ def reject_injection(text: str, rules: yara.Rules) -> Tuple[bool, str]:
215238
216239 Args:
217240 text (str): The text to check for command injection.
218- rules (yara.Rules): The loaded YARA rules.
241+ rules (' yara.Rules' ): The loaded YARA rules.
219242
220243 Returns:
221244 bool: True if attempted exploitation is detected, False otherwise.
222245 str: list of matches as a string
223246
224247 Raises:
225248 ValueError: If the `action` parameter in the configuration is invalid.
249+ ImportError: If the yara module is not installed.
226250 """
251+ _check_yara_available ()
252+
227253 if rules is None :
228254 log .warning (
229255 "reject_injection guardrail was invoked but no rules were specified in the InjectionDetection config."
0 commit comments