Skip to content

Commit fd50f83

Browse files
committed
fix: yapf formatting alignment and caplog logging.disable fix
- Apply yapf formatting to all changed SDK safety files (_scanner, _code_executor, _cli_helpers, _redaction, _rules) - Add logging.disable(NOTSET) to _enable_caplog_logger helper to undo global logging disable from cross-test pollution
1 parent fa9d32d commit fd50f83

7 files changed

Lines changed: 105 additions & 84 deletions

File tree

tests/tools/safety/test_code_executor_wrapper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ async def execute_code(
5353

5454

5555
def _enable_caplog_logger(name: str) -> None:
56+
logging.disable(logging.NOTSET)
5657
target_logger = logging.getLogger(name)
5758
target_logger.disabled = False
5859
target_logger.propagate = True

tests/tools/safety/test_filter_and_audit.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def _ensure_safety_filter_registered() -> None:
4949

5050

5151
def _enable_caplog_logger(name: str) -> None:
52+
logging.disable(logging.NOTSET)
5253
target_logger = logging.getLogger(name)
5354
target_logger.disabled = False
5455
target_logger.propagate = True

trpc_agent_sdk/tools/safety/_cli_helpers.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,10 @@ def scan_file(
122122
content=content,
123123
language=parse_language(language),
124124
tool_name=TOOL_NAME,
125-
tool_metadata={"source": "file", "file_name": file_path.name},
125+
tool_metadata={
126+
"source": "file",
127+
"file_name": file_path.name
128+
},
126129
)
127130
report = SafetyScanner(policy).scan(target)
128131
sample = {
@@ -154,7 +157,8 @@ def build_target_from_sample(sample: dict[str, Any]) -> ScanTarget:
154157
content=_string_field(sample, "content"),
155158
command=_string_field(sample, "command"),
156159
language=parse_language(_string_field(sample, "language")),
157-
env={key: "" for key in env_keys},
160+
env={key: ""
161+
for key in env_keys},
158162
tool_name=TOOL_NAME,
159163
tool_metadata={"sample_id": _string_field(sample, "id")},
160164
)
@@ -202,7 +206,10 @@ def build_aggregate_report(
202206
"policy_name": policy_name,
203207
"generated_at": generated_at,
204208
"sample_count": len(results),
205-
"decision_summary": {decision: decisions.get(decision, 0) for decision in DECISION_VALUES},
209+
"decision_summary": {
210+
decision: decisions.get(decision, 0)
211+
for decision in DECISION_VALUES
212+
},
206213
"results": results,
207214
}
208215

@@ -259,7 +266,5 @@ def _is_subset(expected_rules: list[str], actual_rules: list[str]) -> bool:
259266
def _mismatch_message(result: dict[str, Any]) -> str:
260267
report = result["report"]
261268
actual_rules = [finding["rule_id"] for finding in report.get("findings", [])]
262-
return (
263-
f"{result['sample_id']}: expected decision={result['expected_decision']} "
264-
f"rules={result['expected_rules']}, got decision={report['decision']} rules={actual_rules}"
265-
)
269+
return (f"{result['sample_id']}: expected decision={result['expected_decision']} "
270+
f"rules={result['expected_rules']}, got decision={report['decision']} rules={actual_rules}")

trpc_agent_sdk/tools/safety/_code_executor.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,19 @@ def _build_scan_targets(code_execution_input: CodeExecutionInput) -> list[ScanTa
126126
content=code,
127127
language=_language_from_value(code_block.language),
128128
tool_name=_TOOL_NAME,
129-
tool_metadata={"source": "code_block", "index": index},
130-
)
131-
)
129+
tool_metadata={
130+
"source": "code_block",
131+
"index": index
132+
},
133+
))
132134
elif code_execution_input.code.strip():
133135
targets.append(
134136
ScanTarget(
135137
content=code_execution_input.code,
136138
language=ScriptLanguage.UNKNOWN,
137139
tool_name=_TOOL_NAME,
138140
tool_metadata={"source": "code"},
139-
)
140-
)
141+
))
141142

142143
for input_file in code_execution_input.input_files:
143144
name = input_file.name or ""
@@ -154,9 +155,11 @@ def _build_scan_targets(code_execution_input: CodeExecutionInput) -> list[ScanTa
154155
content=content,
155156
language=_language_from_file_suffix(suffix),
156157
tool_name=_TOOL_NAME,
157-
tool_metadata={"source": "input_file", "file_name": name},
158-
)
159-
)
158+
tool_metadata={
159+
"source": "input_file",
160+
"file_name": name
161+
},
162+
))
160163

161164
return targets
162165

@@ -273,19 +276,16 @@ def _blocked_result(report: SafetyReport) -> CodeExecutionResult:
273276
def _blocked_text(report: SafetyReport) -> str:
274277
rules = _ordered_text((finding.rule_id for finding in report.findings), separator=", ") or "none"
275278
evidence = _ordered_text(finding.evidence for finding in report.findings) or _FAIL_CLOSED_EVIDENCE
276-
recommendation = (
277-
_ordered_text(finding.recommendation for finding in report.findings) or _fail_closed_recommendation()
278-
)
279-
return "\n".join(
280-
[
281-
_BLOCKED_HEADING,
282-
f"Decision: {report.decision.value}",
283-
f"Risk level: {report.risk_level.value}",
284-
f"Rules: {rules}",
285-
f"Evidence: {evidence}",
286-
f"Recommendation: {recommendation}",
287-
]
288-
)
279+
recommendation = (_ordered_text(finding.recommendation for finding in report.findings)
280+
or _fail_closed_recommendation())
281+
return "\n".join([
282+
_BLOCKED_HEADING,
283+
f"Decision: {report.decision.value}",
284+
f"Risk level: {report.risk_level.value}",
285+
f"Rules: {rules}",
286+
f"Evidence: {evidence}",
287+
f"Recommendation: {recommendation}",
288+
])
289289

290290

291291
def _ordered_text(values: Any, *, separator: str = "; ") -> str:

trpc_agent_sdk/tools/safety/_redaction.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,8 @@
2020
re.compile(r"\bAKIA[0-9A-Z]{16}\b"),
2121
re.compile(r"\bsk-[A-Za-z0-9_-]{12,}\b"),
2222
re.compile(r"(?i)\bBearer\s+[A-Za-z0-9._~+/=-]{8,}"),
23-
re.compile(
24-
r"(?i)\b(api[_-]?key|access[_-]?token|auth[_-]?token|token|secret|password)\b"
25-
r"\s*[:=]\s*['\"]?[^'\"\s,;]+"
26-
),
23+
re.compile(r"(?i)\b(api[_-]?key|access[_-]?token|auth[_-]?token|token|secret|password)\b"
24+
r"\s*[:=]\s*['\"]?[^'\"\s,;]+"),
2725
)
2826

2927

trpc_agent_sdk/tools/safety/_rules.py

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,175 +50,197 @@ def _rule(
5050

5151

5252
DEFAULT_RULE_DEFINITIONS: dict[str, RuleDefinition] = {
53-
"FILE_RECURSIVE_DELETE": _rule(
53+
"FILE_RECURSIVE_DELETE":
54+
_rule(
5455
"FILE_RECURSIVE_DELETE",
5556
RiskType.FILE_OPERATION,
5657
RiskLevel.CRITICAL,
5758
SafetyDecision.DENY,
5859
"Recursive deletion of files or directories was detected.",
5960
"Remove recursive deletion or require an isolated workspace with explicit approval.",
6061
),
61-
"FILE_SYSTEM_OVERWRITE": _rule(
62+
"FILE_SYSTEM_OVERWRITE":
63+
_rule(
6264
"FILE_SYSTEM_OVERWRITE",
6365
RiskType.FILE_OPERATION,
6466
RiskLevel.HIGH,
6567
SafetyDecision.DENY,
6668
"Potential overwrite of a protected system path was detected.",
6769
"Avoid writing to system paths; write only inside an approved workspace directory.",
6870
),
69-
"FILE_SENSITIVE_READ": _rule(
71+
"FILE_SENSITIVE_READ":
72+
_rule(
7073
"FILE_SENSITIVE_READ",
7174
RiskType.FILE_OPERATION,
7275
RiskLevel.CRITICAL,
7376
SafetyDecision.DENY,
7477
"Read access to a sensitive credential or configuration file was detected.",
7578
"Remove reads of sensitive files such as .env, SSH keys, or cloud credentials.",
7679
),
77-
"FILE_FORBIDDEN_PATH_ACCESS": _rule(
80+
"FILE_FORBIDDEN_PATH_ACCESS":
81+
_rule(
7882
"FILE_FORBIDDEN_PATH_ACCESS",
7983
RiskType.FILE_OPERATION,
8084
RiskLevel.HIGH,
8185
SafetyDecision.DENY,
8286
"Access to a path denied by the safety policy was detected.",
8387
"Change the command to avoid denied paths or update the policy after review.",
8488
),
85-
"NET_NON_WHITELIST_EGRESS": _rule(
89+
"NET_NON_WHITELIST_EGRESS":
90+
_rule(
8691
"NET_NON_WHITELIST_EGRESS",
8792
RiskType.NETWORK_EGRESS,
8893
RiskLevel.HIGH,
8994
SafetyDecision.DENY,
9095
"Network egress to a non-allowlisted domain was detected.",
9196
"Use an allowlisted domain or add the domain to policy only after review.",
9297
),
93-
"NET_DYNAMIC_EGRESS_REVIEW": _rule(
98+
"NET_DYNAMIC_EGRESS_REVIEW":
99+
_rule(
94100
"NET_DYNAMIC_EGRESS_REVIEW",
95101
RiskType.NETWORK_EGRESS,
96102
RiskLevel.MEDIUM,
97103
SafetyDecision.NEEDS_HUMAN_REVIEW,
98104
"Dynamic network destination construction was detected.",
99105
"Review the destination construction or replace it with a static allowlisted domain.",
100106
),
101-
"PROC_OS_SYSTEM": _rule(
107+
"PROC_OS_SYSTEM":
108+
_rule(
102109
"PROC_OS_SYSTEM",
103110
RiskType.PROCESS_EXECUTION,
104111
RiskLevel.MEDIUM,
105112
SafetyDecision.NEEDS_HUMAN_REVIEW,
106113
"Process execution through os.system or equivalent was detected.",
107114
"Review the command and prefer structured subprocess invocation without shell expansion.",
108115
),
109-
"PROC_SUBPROCESS_SHELL": _rule(
116+
"PROC_SUBPROCESS_SHELL":
117+
_rule(
110118
"PROC_SUBPROCESS_SHELL",
111119
RiskType.PROCESS_EXECUTION,
112120
RiskLevel.HIGH,
113121
SafetyDecision.NEEDS_HUMAN_REVIEW,
114122
"Subprocess execution with shell=True was detected.",
115123
"Avoid shell=True or require human review for the exact command and inputs.",
116124
),
117-
"PROC_SHELL_PIPE_OR_CHAIN": _rule(
125+
"PROC_SHELL_PIPE_OR_CHAIN":
126+
_rule(
118127
"PROC_SHELL_PIPE_OR_CHAIN",
119128
RiskType.PROCESS_EXECUTION,
120129
RiskLevel.MEDIUM,
121130
SafetyDecision.NEEDS_HUMAN_REVIEW,
122131
"Shell pipeline or command chaining was detected.",
123132
"Review shell metacharacters and split commands into explicit safe steps when possible.",
124133
),
125-
"PROC_BACKGROUND_PROCESS": _rule(
134+
"PROC_BACKGROUND_PROCESS":
135+
_rule(
126136
"PROC_BACKGROUND_PROCESS",
127137
RiskType.PROCESS_EXECUTION,
128138
RiskLevel.MEDIUM,
129139
SafetyDecision.NEEDS_HUMAN_REVIEW,
130140
"Background process execution was detected.",
131141
"Avoid background processes unless lifecycle and cleanup are explicitly controlled.",
132142
),
133-
"PROC_PRIVILEGE_ESCALATION": _rule(
143+
"PROC_PRIVILEGE_ESCALATION":
144+
_rule(
134145
"PROC_PRIVILEGE_ESCALATION",
135146
RiskType.PROCESS_EXECUTION,
136147
RiskLevel.HIGH,
137148
SafetyDecision.DENY,
138149
"Privilege escalation or permission-changing command was detected.",
139150
"Remove sudo, su, unsafe chmod, or ownership changes from tool-executed scripts.",
140151
),
141-
"POLICY_DENIED_COMMAND": _rule(
152+
"POLICY_DENIED_COMMAND":
153+
_rule(
142154
"POLICY_DENIED_COMMAND",
143155
RiskType.POLICY_VIOLATION,
144156
RiskLevel.HIGH,
145157
SafetyDecision.DENY,
146158
"Command denied by the safety policy was detected.",
147159
"Remove the denied command or update policy only after review.",
148160
),
149-
"DEP_PIP_INSTALL": _rule(
161+
"DEP_PIP_INSTALL":
162+
_rule(
150163
"DEP_PIP_INSTALL",
151164
RiskType.DEPENDENCY_INSTALL,
152165
RiskLevel.MEDIUM,
153166
SafetyDecision.NEEDS_HUMAN_REVIEW,
154167
"Python dependency installation was detected.",
155168
"Review dependency source and pinning before allowing package installation.",
156169
),
157-
"DEP_NPM_INSTALL": _rule(
170+
"DEP_NPM_INSTALL":
171+
_rule(
158172
"DEP_NPM_INSTALL",
159173
RiskType.DEPENDENCY_INSTALL,
160174
RiskLevel.MEDIUM,
161175
SafetyDecision.NEEDS_HUMAN_REVIEW,
162176
"JavaScript dependency installation was detected.",
163177
"Review package source, lockfile impact, and install scope before proceeding.",
164178
),
165-
"DEP_SYSTEM_INSTALL": _rule(
179+
"DEP_SYSTEM_INSTALL":
180+
_rule(
166181
"DEP_SYSTEM_INSTALL",
167182
RiskType.DEPENDENCY_INSTALL,
168183
RiskLevel.HIGH,
169184
SafetyDecision.DENY,
170185
"System package installation was detected.",
171186
"Do not install system packages from tool execution without an approved runtime image.",
172187
),
173-
"RES_INFINITE_LOOP": _rule(
188+
"RES_INFINITE_LOOP":
189+
_rule(
174190
"RES_INFINITE_LOOP",
175191
RiskType.RESOURCE_ABUSE,
176192
RiskLevel.MEDIUM,
177193
SafetyDecision.NEEDS_HUMAN_REVIEW,
178194
"Potential infinite loop was detected.",
179195
"Add bounded iteration, timeouts, or explicit cancellation conditions.",
180196
),
181-
"RES_FORK_BOMB": _rule(
197+
"RES_FORK_BOMB":
198+
_rule(
182199
"RES_FORK_BOMB",
183200
RiskType.RESOURCE_ABUSE,
184201
RiskLevel.CRITICAL,
185202
SafetyDecision.DENY,
186203
"Fork bomb or explosive process spawning pattern was detected.",
187204
"Remove process spawning recursion and rely on runtime resource limits.",
188205
),
189-
"RES_LONG_SLEEP": _rule(
206+
"RES_LONG_SLEEP":
207+
_rule(
190208
"RES_LONG_SLEEP",
191209
RiskType.RESOURCE_ABUSE,
192210
RiskLevel.MEDIUM,
193211
SafetyDecision.NEEDS_HUMAN_REVIEW,
194212
"Long sleep or wait duration was detected.",
195213
"Shorten waits or use an explicit timeout approved by policy.",
196214
),
197-
"RES_LARGE_WRITE": _rule(
215+
"RES_LARGE_WRITE":
216+
_rule(
198217
"RES_LARGE_WRITE",
199218
RiskType.RESOURCE_ABUSE,
200219
RiskLevel.MEDIUM,
201220
SafetyDecision.NEEDS_HUMAN_REVIEW,
202221
"Potential large or unbounded file write was detected.",
203222
"Bound output size and write only to approved workspace paths.",
204223
),
205-
"LEAK_SECRET_LITERAL": _rule(
224+
"LEAK_SECRET_LITERAL":
225+
_rule(
206226
"LEAK_SECRET_LITERAL",
207227
RiskType.SENSITIVE_LEAK,
208228
RiskLevel.HIGH,
209229
SafetyDecision.DENY,
210230
"Secret-like literal data may be written, logged, or sent.",
211231
"Remove hard-coded secrets and use approved secret management without exposing values.",
212232
),
213-
"LEAK_ENV_SECRET": _rule(
233+
"LEAK_ENV_SECRET":
234+
_rule(
214235
"LEAK_ENV_SECRET",
215236
RiskType.SENSITIVE_LEAK,
216237
RiskLevel.HIGH,
217238
SafetyDecision.DENY,
218239
"Sensitive environment variable output or exfiltration was detected.",
219240
"Do not print, write, or send sensitive environment variable values.",
220241
),
221-
"PARSER_FALLBACK_USED": _rule(
242+
"PARSER_FALLBACK_USED":
243+
_rule(
222244
"PARSER_FALLBACK_USED",
223245
RiskType.PARSER_WARNING,
224246
RiskLevel.LOW,

0 commit comments

Comments
 (0)