cycode 3.12.3.dev2__py3-none-any.whl → 3.12.3.dev4__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.
- cycode/__init__.py +1 -1
- cycode/cli/apps/ai_guardrails/scan/handlers.py +25 -9
- cycode/cli/apps/scan/pre_push/pre_push_command.py +4 -0
- cycode/cli/files_collector/commit_range_documents.py +12 -9
- {cycode-3.12.3.dev2.dist-info → cycode-3.12.3.dev4.dist-info}/METADATA +1 -1
- {cycode-3.12.3.dev2.dist-info → cycode-3.12.3.dev4.dist-info}/RECORD +9 -9
- {cycode-3.12.3.dev2.dist-info → cycode-3.12.3.dev4.dist-info}/WHEEL +0 -0
- {cycode-3.12.3.dev2.dist-info → cycode-3.12.3.dev4.dist-info}/entry_points.txt +0 -0
- {cycode-3.12.3.dev2.dist-info → cycode-3.12.3.dev4.dist-info}/licenses/LICENCE +0 -0
cycode/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = '3.12.3.
|
|
1
|
+
__version__ = '3.12.3.dev4' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -116,7 +116,8 @@ def handle_before_read_file(ctx: typer.Context, payload: AIHookPayload, policy:
|
|
|
116
116
|
|
|
117
117
|
try:
|
|
118
118
|
# Check path-based denylist first
|
|
119
|
-
|
|
119
|
+
is_sensitive_path = is_denied_path(file_path, policy)
|
|
120
|
+
if is_sensitive_path:
|
|
120
121
|
block_reason = BlockReason.SENSITIVE_PATH
|
|
121
122
|
if mode == PolicyMode.BLOCK and action == PolicyMode.BLOCK:
|
|
122
123
|
outcome = AIHookOutcome.BLOCKED
|
|
@@ -125,13 +126,21 @@ def handle_before_read_file(ctx: typer.Context, payload: AIHookPayload, policy:
|
|
|
125
126
|
user_message,
|
|
126
127
|
'This file path is classified as sensitive; do not read/send it to the model.',
|
|
127
128
|
)
|
|
128
|
-
# Warn mode -
|
|
129
|
+
# Warn mode - if content scan is enabled, emit a separate event for the
|
|
130
|
+
# sensitive path so the finally block can independently track the scan result.
|
|
131
|
+
# If content scan is disabled, a single event (from finally) is enough.
|
|
129
132
|
outcome = AIHookOutcome.WARNED
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
if get_policy_value(file_read_config, 'scan_content', default=True):
|
|
134
|
+
ai_client.create_event(
|
|
135
|
+
payload,
|
|
136
|
+
AiHookEventType.FILE_READ,
|
|
137
|
+
outcome,
|
|
138
|
+
block_reason=BlockReason.SENSITIVE_PATH,
|
|
139
|
+
file_path=payload.file_path,
|
|
140
|
+
)
|
|
141
|
+
# Reset for the content scan result tracked by the finally block
|
|
142
|
+
block_reason = None
|
|
143
|
+
outcome = AIHookOutcome.ALLOWED
|
|
135
144
|
|
|
136
145
|
# Scan file content if enabled
|
|
137
146
|
if get_policy_value(file_read_config, 'scan_content', default=True):
|
|
@@ -152,7 +161,14 @@ def handle_before_read_file(ctx: typer.Context, payload: AIHookPayload, policy:
|
|
|
152
161
|
user_message,
|
|
153
162
|
'Possible secrets detected; proceed with caution.',
|
|
154
163
|
)
|
|
155
|
-
|
|
164
|
+
|
|
165
|
+
# If path was sensitive but content scan found no secrets (or scan disabled), still warn
|
|
166
|
+
if is_sensitive_path:
|
|
167
|
+
user_message = f'Cycode flagged {file_path} as sensitive. Allow reading?'
|
|
168
|
+
return response_builder.ask_permission(
|
|
169
|
+
user_message,
|
|
170
|
+
'This file path is classified as sensitive; proceed with caution.',
|
|
171
|
+
)
|
|
156
172
|
|
|
157
173
|
return response_builder.allow_permission()
|
|
158
174
|
except Exception as e:
|
|
@@ -342,7 +358,7 @@ def _scan_path_for_secrets(ctx: typer.Context, file_path: str, policy: dict) ->
|
|
|
342
358
|
Returns tuple of (violation_summary, scan_id) if secrets found, (None, scan_id) if clean.
|
|
343
359
|
Raises exception on error or timeout.
|
|
344
360
|
"""
|
|
345
|
-
if not file_path or not os.path.
|
|
361
|
+
if not file_path or not os.path.isfile(file_path):
|
|
346
362
|
return None, None
|
|
347
363
|
|
|
348
364
|
max_bytes = get_policy_value(policy, 'secrets', 'max_bytes', default=200000)
|
|
@@ -44,6 +44,10 @@ def pre_push_command(
|
|
|
44
44
|
timeout = configuration_manager.get_pre_push_command_timeout(command_scan_type)
|
|
45
45
|
with TimeoutAfter(timeout):
|
|
46
46
|
push_update_details = parse_pre_push_input()
|
|
47
|
+
if not push_update_details:
|
|
48
|
+
logger.info('No pre-push input found, nothing to scan')
|
|
49
|
+
return
|
|
50
|
+
|
|
47
51
|
commit_range = calculate_pre_push_commit_range(push_update_details)
|
|
48
52
|
if not commit_range:
|
|
49
53
|
logger.info(
|
|
@@ -228,7 +228,7 @@ def parse_pre_receive_input() -> str:
|
|
|
228
228
|
return pre_receive_input.splitlines()[0]
|
|
229
229
|
|
|
230
230
|
|
|
231
|
-
def parse_pre_push_input() -> str:
|
|
231
|
+
def parse_pre_push_input() -> Optional[str]:
|
|
232
232
|
"""Parse input to pre-push hook details.
|
|
233
233
|
|
|
234
234
|
Example input:
|
|
@@ -237,13 +237,11 @@ def parse_pre_push_input() -> str:
|
|
|
237
237
|
refs/heads/main 9cf90954ef26e7c58284f8ebf7dcd0fcf711152a refs/heads/main 973a96d3e925b65941f7c47fa16129f1577d499f
|
|
238
238
|
refs/heads/feature-branch 3378e52dcfa47fb11ce3a4a520bea5f85d5d0bf3 refs/heads/feature-branch 59564ef68745bca38c42fc57a7822efd519a6bd9
|
|
239
239
|
|
|
240
|
-
:return: First
|
|
240
|
+
:return: First push update details (input's first line), or None if no input was provided
|
|
241
241
|
""" # noqa: E501
|
|
242
242
|
pre_push_input = _read_hook_input_from_stdin()
|
|
243
243
|
if not pre_push_input:
|
|
244
|
-
|
|
245
|
-
'Pre push input was not found. Make sure that you are using this command only in pre-push hook'
|
|
246
|
-
)
|
|
244
|
+
return None
|
|
247
245
|
|
|
248
246
|
# each line represents a branch push request, handle the first one only
|
|
249
247
|
return pre_push_input.splitlines()[0]
|
|
@@ -332,6 +330,15 @@ def calculate_pre_push_commit_range(push_update_details: str) -> Optional[str]:
|
|
|
332
330
|
"""
|
|
333
331
|
local_ref, local_object_name, remote_ref, remote_object_name = push_update_details.split()
|
|
334
332
|
|
|
333
|
+
# Tag pushes don't contain file diffs that need scanning
|
|
334
|
+
if local_ref.startswith('refs/tags/') or remote_ref.startswith('refs/tags/'):
|
|
335
|
+
logger.info('Skipping scan for tag push: %s -> %s', local_ref, remote_ref)
|
|
336
|
+
return None
|
|
337
|
+
|
|
338
|
+
# If deleting a ref (local_object_name is all zeros), no need to scan
|
|
339
|
+
if local_object_name == consts.EMPTY_COMMIT_SHA:
|
|
340
|
+
return None
|
|
341
|
+
|
|
335
342
|
if remote_object_name == consts.EMPTY_COMMIT_SHA:
|
|
336
343
|
try:
|
|
337
344
|
repo = git_proxy.get_repo(os.getcwd())
|
|
@@ -356,10 +363,6 @@ def calculate_pre_push_commit_range(push_update_details: str) -> Optional[str]:
|
|
|
356
363
|
logger.debug('Failed to get repo for pre-push commit range calculation: %s', exc_info=e)
|
|
357
364
|
return consts.COMMIT_RANGE_ALL_COMMITS
|
|
358
365
|
|
|
359
|
-
# If deleting a branch (local_object_name is all zeros), no need to scan
|
|
360
|
-
if local_object_name == consts.EMPTY_COMMIT_SHA:
|
|
361
|
-
return None
|
|
362
|
-
|
|
363
366
|
# For updates to existing branches, scan from remote to local
|
|
364
367
|
return f'{remote_object_name}..{local_object_name}'
|
|
365
368
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cycode/__init__.py,sha256=
|
|
1
|
+
cycode/__init__.py,sha256=lig0eJ_EAA82PNYTdZ4IwBXVHgUIY39vry0nkPTxcQ4,115
|
|
2
2
|
cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
|
|
3
3
|
cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
cycode/cli/app.py,sha256=bsfXV85RRb1iz19JRC9gkc5Iv30fnEE1cwA8dg552NQ,6482
|
|
@@ -12,7 +12,7 @@ cycode/cli/apps/ai_guardrails/hooks_manager.py,sha256=37IcEMCK60pQ8lnuy8GThlq9oe
|
|
|
12
12
|
cycode/cli/apps/ai_guardrails/install_command.py,sha256=qlklts1Uj6j3urK6jwAWJY-L_DgVaZWuk7vZcpoKPAQ,4571
|
|
13
13
|
cycode/cli/apps/ai_guardrails/scan/__init__.py,sha256=qJc82XiQGiAuc1sYY8Ij_A-qXpxgLPuayQq8xWlouMA,48
|
|
14
14
|
cycode/cli/apps/ai_guardrails/scan/consts.py,sha256=drAslw6vW3kxmbCs2qPCUbUPR7PJouT2lsXtu5sD-lQ,1094
|
|
15
|
-
cycode/cli/apps/ai_guardrails/scan/handlers.py,sha256=
|
|
15
|
+
cycode/cli/apps/ai_guardrails/scan/handlers.py,sha256=e3UlQ6TbFFFAFEAgMUhL5i7bV1mSrmFJuLb9O0FLX2Y,15702
|
|
16
16
|
cycode/cli/apps/ai_guardrails/scan/payload.py,sha256=-r8BsvP-VPD3XibyIPKreCjJNVXGpe_9ENPF78NlnkQ,10178
|
|
17
17
|
cycode/cli/apps/ai_guardrails/scan/policy.py,sha256=39s8hnxgjny1l6XAO59wsRcAlpW-LG00GUnO0PfqvuY,2566
|
|
18
18
|
cycode/cli/apps/ai_guardrails/scan/response_builders.py,sha256=tVFJCnGdqSmyileg-idypOihygct7F6T4KHXYlX8y_c,4653
|
|
@@ -66,7 +66,7 @@ cycode/cli/apps/scan/path/path_command.py,sha256=x4HXqq1Wy6onziKMc6ELQxqeI5k-m3t
|
|
|
66
66
|
cycode/cli/apps/scan/pre_commit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
67
67
|
cycode/cli/apps/scan/pre_commit/pre_commit_command.py,sha256=49vnVAIiLtcG7lsBX2vKhS-5kqC8wKqCUP-3G8ClPVs,465
|
|
68
68
|
cycode/cli/apps/scan/pre_push/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
69
|
-
cycode/cli/apps/scan/pre_push/pre_push_command.py,sha256=
|
|
69
|
+
cycode/cli/apps/scan/pre_push/pre_push_command.py,sha256=i2k1-il7tOtuIj2ZksjdtgnRVXbj0p6tMrMQuxckynY,2554
|
|
70
70
|
cycode/cli/apps/scan/pre_receive/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
71
71
|
cycode/cli/apps/scan/pre_receive/pre_receive_command.py,sha256=v1sXjl9EKTG65065DzJRJ78we96cqLztzDWw89KUb0o,2522
|
|
72
72
|
cycode/cli/apps/scan/remote_url_resolver.py,sha256=JCjaAzDMxGFDT7twBpZzjgEHGwlaGIxWG_Y7DSehsb0,5651
|
|
@@ -95,7 +95,7 @@ cycode/cli/exceptions/handle_errors.py,sha256=za3vQcM_eFTvbT-53tTc6ky-J0wav6lupD
|
|
|
95
95
|
cycode/cli/exceptions/handle_report_sbom_errors.py,sha256=bi0EizHtQLL-ovhHRH98CZ7qXdDPLTYnI59Jn1Y5c0E,926
|
|
96
96
|
cycode/cli/exceptions/handle_scan_errors.py,sha256=1KkBFb7LniflYRr0vMl1FPIZDALPZu1LiXhORGl0jhs,2195
|
|
97
97
|
cycode/cli/files_collector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
98
|
-
cycode/cli/files_collector/commit_range_documents.py,sha256=
|
|
98
|
+
cycode/cli/files_collector/commit_range_documents.py,sha256=ZAU9er6m8_IF9y9KxZoiEaDOiZC35SEfv5VtqKp4AZc,20484
|
|
99
99
|
cycode/cli/files_collector/documents_walk_ignore.py,sha256=G4e-3vfP4WZ7wa9-VbZ66xCKCioTXnPBfbrs4_hh8xY,4705
|
|
100
100
|
cycode/cli/files_collector/file_excluder.py,sha256=5Y7MM6_4x4FRKCV47D_hOXIg9BzYLHqwoWkmtV7Lt4I,7562
|
|
101
101
|
cycode/cli/files_collector/iac/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -198,8 +198,8 @@ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ
|
|
|
198
198
|
cycode/cyclient/scan_client.py,sha256=6TK5FQkfrvV7PHqRnUzEn1PBNd2oPYVamvIixcUfe3c,16755
|
|
199
199
|
cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
|
|
200
200
|
cycode/logger.py,sha256=EfZGRK6VC5rE_LAjIcRrHFiQCueylCDXoG6bvGkrIME,2111
|
|
201
|
-
cycode-3.12.3.
|
|
202
|
-
cycode-3.12.3.
|
|
203
|
-
cycode-3.12.3.
|
|
204
|
-
cycode-3.12.3.
|
|
205
|
-
cycode-3.12.3.
|
|
201
|
+
cycode-3.12.3.dev4.dist-info/METADATA,sha256=-FVJcdUsjkhOaDwzI_MuYfe1W1Fzz_lnGJRLVHZlNoI,84350
|
|
202
|
+
cycode-3.12.3.dev4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
203
|
+
cycode-3.12.3.dev4.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
|
|
204
|
+
cycode-3.12.3.dev4.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
|
|
205
|
+
cycode-3.12.3.dev4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|