cycode 3.24.1.dev1__py3-none-any.whl → 3.24.1.dev2__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 +3 -4
- cycode/cli/apps/ai_guardrails/scan/utils.py +59 -1
- cycode/cli/utils/scan_utils.py +0 -23
- {cycode-3.24.1.dev1.dist-info → cycode-3.24.1.dev2.dist-info}/METADATA +1 -1
- {cycode-3.24.1.dev1.dist-info → cycode-3.24.1.dev2.dist-info}/RECORD +9 -9
- {cycode-3.24.1.dev1.dist-info → cycode-3.24.1.dev2.dist-info}/WHEEL +0 -0
- {cycode-3.24.1.dev1.dist-info → cycode-3.24.1.dev2.dist-info}/entry_points.txt +0 -0
- {cycode-3.24.1.dev1.dist-info → cycode-3.24.1.dev2.dist-info}/licenses/LICENCE +0 -0
cycode/__init__.py
CHANGED
|
@@ -5,4 +5,4 @@ import time as _time
|
|
|
5
5
|
# end-to-end scan duration from the moment the user actually triggered it.
|
|
6
6
|
_BOOT_WALL: float = _time.time()
|
|
7
7
|
|
|
8
|
-
__version__ = '3.24.1.
|
|
8
|
+
__version__ = '3.24.1.dev2' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -30,7 +30,7 @@ from cycode.cli.apps.ai_guardrails.scan.types import (
|
|
|
30
30
|
AIHookOutcome,
|
|
31
31
|
BlockReason,
|
|
32
32
|
)
|
|
33
|
-
from cycode.cli.apps.ai_guardrails.scan.utils import is_denied_path, truncate_utf8
|
|
33
|
+
from cycode.cli.apps.ai_guardrails.scan.utils import build_violation_summary, is_denied_path, truncate_utf8
|
|
34
34
|
from cycode.cli.apps.scan.code_scanner import _get_scan_documents_thread_func
|
|
35
35
|
from cycode.cli.apps.scan.scan_parameters import get_scan_parameters
|
|
36
36
|
from cycode.cli.cli_types import ScanTypeOption, SeverityOption
|
|
@@ -38,7 +38,6 @@ from cycode.cli.files_collector.file_excluder import is_path_configured_in_exclu
|
|
|
38
38
|
from cycode.cli.models import Document
|
|
39
39
|
from cycode.cli.utils.host_info import get_hostname, get_serial_number
|
|
40
40
|
from cycode.cli.utils.progress_bar import DummyProgressBar, ScanProgressBarSection
|
|
41
|
-
from cycode.cli.utils.scan_utils import build_violation_summary
|
|
42
41
|
from cycode.logger import get_logger
|
|
43
42
|
|
|
44
43
|
logger = get_logger('AI Guardrails')
|
|
@@ -76,7 +75,7 @@ def handle_before_submit_prompt(ctx: typer.Context, payload: AIHookPayload, poli
|
|
|
76
75
|
block_reason = SECRETS_BLOCK_REASON_BY_EVENT_TYPE[AiHookEventType.PROMPT]
|
|
77
76
|
if effective_mode == GuardrailsMode.BLOCK:
|
|
78
77
|
outcome = AIHookOutcome.BLOCKED
|
|
79
|
-
user_message = f'
|
|
78
|
+
user_message = f'Remove secrets before sending. {violation_summary}'
|
|
80
79
|
return HookDecision.deny(AiHookEventType.PROMPT, user_message)
|
|
81
80
|
outcome = AIHookOutcome.WARNED
|
|
82
81
|
return HookDecision.allow(AiHookEventType.PROMPT)
|
|
@@ -283,7 +282,7 @@ def handle_before_mcp_execution(ctx: typer.Context, payload: AIHookPayload, poli
|
|
|
283
282
|
event_type=AiHookEventType.MCP_EXECUTION,
|
|
284
283
|
deny_message=lambda v: f'Cycode blocked MCP tool call "{tool}". {v}',
|
|
285
284
|
deny_agent_message='Do not pass secrets to tools. Use secret references (name/id) instead.',
|
|
286
|
-
ask_message=lambda v: f'
|
|
285
|
+
ask_message=lambda v: f'Allow MCP tool call "{tool}"? {v}',
|
|
287
286
|
ask_agent_message='Possible secrets detected in tool arguments; proceed with caution.',
|
|
288
287
|
),
|
|
289
288
|
scan_text=args_text,
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Utility functions for AI guardrails.
|
|
3
3
|
|
|
4
|
-
Includes JSON parsing, path matching,
|
|
4
|
+
Includes JSON parsing, path matching, text handling and hook-message utilities.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import json
|
|
8
8
|
import os
|
|
9
9
|
import sys
|
|
10
|
+
from collections import defaultdict
|
|
10
11
|
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
11
13
|
|
|
12
14
|
from cycode.cli.apps.ai_guardrails.scan.policy import get_policy_value
|
|
15
|
+
from cycode.cli.cli_types import SeverityOption
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from cycode.cli.models import LocalScanResult
|
|
19
|
+
|
|
20
|
+
# Keeps the hook message readable when a single file trips dozens of detections
|
|
21
|
+
MAX_VIOLATION_DETAIL_LINES = 5
|
|
13
22
|
|
|
14
23
|
|
|
15
24
|
def read_stdin_text() -> str:
|
|
@@ -87,3 +96,52 @@ def is_denied_path(file_path: str, policy: dict) -> bool:
|
|
|
87
96
|
def output_json(obj: dict) -> None:
|
|
88
97
|
"""Write JSON response to stdout (for IDE to read)."""
|
|
89
98
|
print(json.dumps(obj), end='') # noqa: T201
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _build_detection_lines(
|
|
102
|
+
local_scan_results: list['LocalScanResult'], max_lines: int = MAX_VIOLATION_DETAIL_LINES
|
|
103
|
+
) -> str:
|
|
104
|
+
"""One line per distinct finding: what it is, and the value hash identifying it.
|
|
105
|
+
|
|
106
|
+
The value hash is safe to display; the value itself is not. Detections excluded by an existing
|
|
107
|
+
ignore rule are already gone from `document_detections`, so only what actually blocked is listed.
|
|
108
|
+
"""
|
|
109
|
+
type_by_sha = {}
|
|
110
|
+
for local_scan_result in local_scan_results:
|
|
111
|
+
for document_detections in local_scan_result.document_detections:
|
|
112
|
+
for detection in document_detections.detections:
|
|
113
|
+
sha = detection.detection_details.get('sha512')
|
|
114
|
+
if sha and sha not in type_by_sha:
|
|
115
|
+
type_by_sha[sha] = detection.type or detection.message
|
|
116
|
+
|
|
117
|
+
if not type_by_sha:
|
|
118
|
+
return ''
|
|
119
|
+
|
|
120
|
+
lines = [f' - {detection_type}: {sha}' for sha, detection_type in list(type_by_sha.items())[:max_lines]]
|
|
121
|
+
remaining = len(type_by_sha) - len(lines)
|
|
122
|
+
if remaining:
|
|
123
|
+
lines.append(f' - ...and {remaining} more')
|
|
124
|
+
|
|
125
|
+
return '\n' + '\n'.join(lines)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def build_violation_summary(local_scan_results: list['LocalScanResult']) -> str:
|
|
129
|
+
"""Build violation summary string with severity breakdown and emojis."""
|
|
130
|
+
detections_count = 0
|
|
131
|
+
severity_counts = defaultdict(int)
|
|
132
|
+
|
|
133
|
+
for local_scan_result in local_scan_results:
|
|
134
|
+
for document_detections in local_scan_result.document_detections:
|
|
135
|
+
for detection in document_detections.detections:
|
|
136
|
+
if detection.severity:
|
|
137
|
+
detections_count += 1
|
|
138
|
+
severity_counts[SeverityOption(detection.severity)] += 1
|
|
139
|
+
|
|
140
|
+
severity_parts = []
|
|
141
|
+
for severity in reversed(SeverityOption):
|
|
142
|
+
emoji = SeverityOption.get_member_unicode_emoji(severity)
|
|
143
|
+
count = severity_counts[severity]
|
|
144
|
+
severity_parts.append(f'{emoji} {severity.upper()} - {count}')
|
|
145
|
+
|
|
146
|
+
summary = f'Cycode found {detections_count} violations: {" | ".join(severity_parts)}'
|
|
147
|
+
return summary + _build_detection_lines(local_scan_results)
|
cycode/cli/utils/scan_utils.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import os
|
|
2
|
-
from collections import defaultdict
|
|
3
2
|
from typing import TYPE_CHECKING, Optional
|
|
4
3
|
from uuid import UUID, uuid4
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
|
|
8
7
|
from cycode.cli import consts
|
|
9
|
-
from cycode.cli.cli_types import SeverityOption
|
|
10
8
|
|
|
11
9
|
if TYPE_CHECKING:
|
|
12
10
|
from cycode.cli.models import LocalScanResult
|
|
@@ -41,24 +39,3 @@ def generate_unique_scan_id() -> UUID:
|
|
|
41
39
|
return UUID(os.environ['PYTEST_TEST_UNIQUE_ID'])
|
|
42
40
|
|
|
43
41
|
return uuid4()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def build_violation_summary(local_scan_results: list['LocalScanResult']) -> str:
|
|
47
|
-
"""Build violation summary string with severity breakdown and emojis."""
|
|
48
|
-
detections_count = 0
|
|
49
|
-
severity_counts = defaultdict(int)
|
|
50
|
-
|
|
51
|
-
for local_scan_result in local_scan_results:
|
|
52
|
-
for document_detections in local_scan_result.document_detections:
|
|
53
|
-
for detection in document_detections.detections:
|
|
54
|
-
if detection.severity:
|
|
55
|
-
detections_count += 1
|
|
56
|
-
severity_counts[SeverityOption(detection.severity)] += 1
|
|
57
|
-
|
|
58
|
-
severity_parts = []
|
|
59
|
-
for severity in reversed(SeverityOption):
|
|
60
|
-
emoji = SeverityOption.get_member_unicode_emoji(severity)
|
|
61
|
-
count = severity_counts[severity]
|
|
62
|
-
severity_parts.append(f'{emoji} {severity.upper()} - {count}')
|
|
63
|
-
|
|
64
|
-
return f'Cycode found {detections_count} violations: {" | ".join(severity_parts)}'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cycode/__init__.py,sha256=
|
|
1
|
+
cycode/__init__.py,sha256=TGnaJP0fWShd83OGAGzngPbjXG-1A9ACQThCYV9aIOc,396
|
|
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=AlR2durAEbsa47PDfIj7JtMvJDWA_Dq6wPtVuMJYSCs,10250
|
|
@@ -21,12 +21,12 @@ cycode/cli/apps/ai_guardrails/scan/__init__.py,sha256=qJc82XiQGiAuc1sYY8Ij_A-qXp
|
|
|
21
21
|
cycode/cli/apps/ai_guardrails/scan/consts.py,sha256=8H8JXlgm65sYkgTXqsBInHhHe80UPjqY4vumZXB4GGM,1060
|
|
22
22
|
cycode/cli/apps/ai_guardrails/scan/detach.py,sha256=8BRgBq9Qi8nXEx6NKlE8scSRPkO30XCfsiI5PLvq6Gk,2700
|
|
23
23
|
cycode/cli/apps/ai_guardrails/scan/guardrail_config.py,sha256=QSBwmkTdlC9zXIqI3gIiOlefviJWrpeJHzFu1Cs-zgE,7051
|
|
24
|
-
cycode/cli/apps/ai_guardrails/scan/handlers.py,sha256=
|
|
24
|
+
cycode/cli/apps/ai_guardrails/scan/handlers.py,sha256=i8fJ_K3m2v45DRSfkK0Wt4yEZfYIxOaLtZXiGna--5A,17641
|
|
25
25
|
cycode/cli/apps/ai_guardrails/scan/payload.py,sha256=sWsWq5yXP54MVCajsb180kLuprI_M2kspMOzQGh7r_o,1534
|
|
26
26
|
cycode/cli/apps/ai_guardrails/scan/policy.py,sha256=3HuDoL_NYE3lyHRAlIMleq6pi-stIDQwotHsKhUFhTQ,5000
|
|
27
27
|
cycode/cli/apps/ai_guardrails/scan/scan_command.py,sha256=fgV32phgkBPwqSau7oFDISZ58CVpq214JlYwZQM9bnM,8318
|
|
28
28
|
cycode/cli/apps/ai_guardrails/scan/types.py,sha256=ybQm242QN0l_4SSNX4xMHXxzqEK-MW-hfIOixI7zvGU,1497
|
|
29
|
-
cycode/cli/apps/ai_guardrails/scan/utils.py,sha256=
|
|
29
|
+
cycode/cli/apps/ai_guardrails/scan/utils.py,sha256=4CIZAILS9m5-JsFbUderwBVzFAjqAVVVRhWgE9oLPhM,5292
|
|
30
30
|
cycode/cli/apps/ai_guardrails/session_start_command.py,sha256=oEW-OsHXkf8P7SX1vKa9Ddlv_hASRiQ42JZR3MnJfRg,7171
|
|
31
31
|
cycode/cli/apps/ai_guardrails/status_command.py,sha256=Uqss68TEPCYPXpLix6Bh-4J3g-khxWsAqlIGYH5x4bQ,3203
|
|
32
32
|
cycode/cli/apps/ai_guardrails/uninstall_command.py,sha256=dOmePfZmlHAPy2zEJM1yMtSuDqvzDwtqgmLKYK-T9PI,2698
|
|
@@ -186,7 +186,7 @@ cycode/cli/utils/jwt_utils.py,sha256=EGI-0CKhCGY8hIcZ9b9diq9hqtOUf8Ha8ukeVJIf974
|
|
|
186
186
|
cycode/cli/utils/path_utils.py,sha256=zc48CSU7hxqjSgfH6h5M1B0kIcKW44BOJrUa_6z-mAo,4317
|
|
187
187
|
cycode/cli/utils/progress_bar.py,sha256=bKBWHHdZsVkdDdWMJLfgLGR0cBYeB44P_DpRM8pvWqU,9528
|
|
188
188
|
cycode/cli/utils/scan_batch.py,sha256=5xKGVDVqoRxdKhuZkK11x4QrNqKmU20Q83E_fy8Nndk,5188
|
|
189
|
-
cycode/cli/utils/scan_utils.py,sha256=
|
|
189
|
+
cycode/cli/utils/scan_utils.py,sha256=_VkZ7maLVST6J8dsqDsKYWQj2EVfqI3iPPsA1QJOGEU,1259
|
|
190
190
|
cycode/cli/utils/shell_executor.py,sha256=VkzzQPZCmTkFvDjhgJrkv-Icej3U1wLW9LLN6k6OahA,1848
|
|
191
191
|
cycode/cli/utils/string_utils.py,sha256=KyPSAHDRPEGNCCcKTF0v99vad5z9djpVGc8nxpBqdYo,2445
|
|
192
192
|
cycode/cli/utils/task_timer.py,sha256=wxfM2TtJGjc1F17CIja_Qmt6zd4a1qdMwuz0ltgTDAg,2722
|
|
@@ -217,8 +217,8 @@ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ
|
|
|
217
217
|
cycode/cyclient/scan_client.py,sha256=DqAZ7u6Z_cvw9A9RlLkAQUgLRwPCCAsUq5U9umt4F7Y,16955
|
|
218
218
|
cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
|
|
219
219
|
cycode/logger.py,sha256=EfZGRK6VC5rE_LAjIcRrHFiQCueylCDXoG6bvGkrIME,2111
|
|
220
|
-
cycode-3.24.1.
|
|
221
|
-
cycode-3.24.1.
|
|
222
|
-
cycode-3.24.1.
|
|
223
|
-
cycode-3.24.1.
|
|
224
|
-
cycode-3.24.1.
|
|
220
|
+
cycode-3.24.1.dev2.dist-info/METADATA,sha256=AxXWfRpzaPJHwREMYa_RvGp_-JGo4iGbXkzEPbZBMGM,93687
|
|
221
|
+
cycode-3.24.1.dev2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
222
|
+
cycode-3.24.1.dev2.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
|
|
223
|
+
cycode-3.24.1.dev2.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
|
|
224
|
+
cycode-3.24.1.dev2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|