77
88import json
99import os
10- from multiprocessing .pool import ThreadPool , TimeoutError as PoolTimeoutError
11- from typing import Optional
10+ from multiprocessing .pool import ThreadPool
11+ from multiprocessing .pool import TimeoutError as PoolTimeoutError
12+ from typing import Callable , Optional
1213
1314import typer
1415
1516from cycode .cli .apps .scan .code_scanner import _get_scan_documents_thread_func
1617from cycode .cli .apps .scan .prompt .payload import AIHookPayload
1718from cycode .cli .apps .scan .prompt .policy import get_policy_value
1819from cycode .cli .apps .scan .prompt .response_builders import get_response_builder
19- from cycode .cli .apps .scan .prompt .types import AIHookOutcome , AiHookEventType , BlockReason
20+ from cycode .cli .apps .scan .prompt .types import AiHookEventType , AIHookOutcome , BlockReason
2021from cycode .cli .apps .scan .prompt .utils import (
2122 is_denied_path ,
2223 truncate_utf8 ,
@@ -60,8 +61,11 @@ def handle_before_submit_prompt(ctx: typer.Context, payload: AIHookPayload, poli
6061 try :
6162 violation_summary , scan_id = _scan_text_for_secrets (ctx , clipped , timeout_ms )
6263
63- if violation_summary and get_policy_value (prompt_config , 'action' ,
64- default = 'block' ) == 'block' and mode == 'block' :
64+ if (
65+ violation_summary
66+ and get_policy_value (prompt_config , 'action' , default = 'block' ) == 'block'
67+ and mode == 'block'
68+ ):
6569 outcome = AIHookOutcome .BLOCKED
6670 block_reason = BlockReason .SECRETS_IN_PROMPT
6771 user_message = f'{ violation_summary } . Remove secrets before sending.'
@@ -72,8 +76,9 @@ def handle_before_submit_prompt(ctx: typer.Context, payload: AIHookPayload, poli
7276 response = response_builder .allow_prompt ()
7377 return response
7478 except Exception as e :
75- outcome = AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' ,
76- default = True ) else AIHookOutcome .BLOCKED
79+ outcome = (
80+ AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' , default = True ) else AIHookOutcome .BLOCKED
81+ )
7782 block_reason = BlockReason .SCAN_FAILURE if outcome == AIHookOutcome .BLOCKED else None
7883 raise e
7984 finally :
@@ -133,15 +138,15 @@ def handle_before_read_file(ctx: typer.Context, payload: AIHookPayload, policy:
133138 user_message ,
134139 'Secrets detected; do not send this file to the model.' ,
135140 )
136- else :
137- if violation_summary :
138- outcome = AIHookOutcome .WARNED
139- return response_builder .allow_permission ()
141+ if violation_summary :
142+ outcome = AIHookOutcome .WARNED
143+ return response_builder .allow_permission ()
140144
141145 return response_builder .allow_permission ()
142146 except Exception as e :
143- outcome = AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' ,
144- default = True ) else AIHookOutcome .BLOCKED
147+ outcome = (
148+ AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' , default = True ) else AIHookOutcome .BLOCKED
149+ )
145150 block_reason = BlockReason .SCAN_FAILURE if outcome == AIHookOutcome .BLOCKED else None
146151 raise e
147152 finally :
@@ -197,17 +202,17 @@ def handle_before_mcp_execution(ctx: typer.Context, payload: AIHookPayload, poli
197202 user_message ,
198203 'Do not pass secrets to tools. Use secret references (name/id) instead.' ,
199204 )
200- else :
201- outcome = AIHookOutcome .WARNED
202- return response_builder .ask_permission (
203- f'{ violation_summary } in MCP tool call "{ tool } ". Allow execution?' ,
204- 'Possible secrets detected in tool arguments; proceed with caution.' ,
205- )
205+ outcome = AIHookOutcome .WARNED
206+ return response_builder .ask_permission (
207+ f'{ violation_summary } in MCP tool call "{ tool } ". Allow execution?' ,
208+ 'Possible secrets detected in tool arguments; proceed with caution.' ,
209+ )
206210
207211 return response_builder .allow_permission ()
208212 except Exception as e :
209- outcome = AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' ,
210- default = True ) else AIHookOutcome .BLOCKED
213+ outcome = (
214+ AIHookOutcome .ALLOWED if get_policy_value (policy , 'fail_open' , default = True ) else AIHookOutcome .BLOCKED
215+ )
211216 block_reason = BlockReason .SCAN_FAILURE if outcome == AIHookOutcome .BLOCKED else None
212217 raise e
213218 finally :
@@ -220,7 +225,7 @@ def handle_before_mcp_execution(ctx: typer.Context, payload: AIHookPayload, poli
220225 )
221226
222227
223- def get_handler_for_event (event_type : str ):
228+ def get_handler_for_event (event_type : str ) -> Optional [ Callable [[ typer . Context , AIHookPayload , dict ], dict ]] :
224229 """Get the appropriate handler function for a canonical event type.
225230
226231 Args:
@@ -274,8 +279,8 @@ def _perform_scan(
274279 try :
275280 scan_id , error , local_scan_result = result .get (timeout = timeout_seconds )
276281 except PoolTimeoutError :
277- logger .debug (f 'Scan timed out after { timeout_seconds } seconds' )
278- raise RuntimeError (f'Scan timed out after { timeout_seconds } seconds' )
282+ logger .debug ('Scan timed out after %s seconds' , timeout_seconds )
283+ raise RuntimeError (f'Scan timed out after { timeout_seconds } seconds' ) from None
279284
280285 # Check if scan failed - raise exception to trigger fail_open policy
281286 if error :
@@ -294,9 +299,7 @@ def _perform_scan(
294299 return None , scan_id
295300
296301
297- def _scan_text_for_secrets (
298- ctx : typer .Context , text : str , timeout_ms : int
299- ) -> tuple [Optional [str ], Optional [str ]]:
302+ def _scan_text_for_secrets (ctx : typer .Context , text : str , timeout_ms : int ) -> tuple [Optional [str ], Optional [str ]]:
300303 """
301304 Scan text content for secrets using Cycode CLI.
302305
@@ -322,7 +325,7 @@ def _scan_path_for_secrets(ctx: typer.Context, file_path: str, policy: dict) ->
322325 if not file_path or not os .path .exists (file_path ):
323326 return None , None
324327
325- with open (file_path , 'r' , encoding = 'utf-8' , errors = 'replace' ) as f :
328+ with open (file_path , encoding = 'utf-8' , errors = 'replace' ) as f :
326329 content = f .read ()
327330
328331 # Truncate content based on policy max_bytes
0 commit comments