@@ -251,6 +251,62 @@ fn validate_command_rejects_background_chain_bypass() {
251251 assert ! ( result. unwrap_err( ) . contains( "not allowed" ) ) ;
252252}
253253
254+ // Regression: OPENHUMAN-TAURI-GW (#1813). A multi-byte UTF-8 char straddling
255+ // byte 80 of the command string used to panic the log truncator with
256+ // `byte index 80 is not a char boundary`, killing the core thread. All five
257+ // `&command[..80]` log sites must now round down to a UTF-8 boundary.
258+ #[ test]
259+ fn validate_command_does_not_panic_on_multibyte_char_at_log_truncation_boundary ( ) {
260+ // Real-world Sentry repro: `cmd /c "dir /b "%USERPROFILE%\Desktop\*.lnk"
261+ // 2>nul | findstr /i "Warcraft WoW 魔兽 Battle"` — the 3-byte `'魔'`
262+ // occupies bytes 78..81, so a naked `&command[..80]` panics.
263+ let cmd = "cmd /c \" dir /b \" %USERPROFILE%\\ Desktop\\ *.lnk\" 2>nul | findstr /i \" Warcraft WoW 魔兽 Battle\" " ;
264+ assert ! (
265+ cmd. len( ) > 80 ,
266+ "test fixture must be long enough to trigger truncation"
267+ ) ;
268+ assert ! (
269+ !cmd. is_char_boundary( 80 ) ,
270+ "test fixture must place a multi-byte char across byte 80"
271+ ) ;
272+
273+ // Exercise the allowlist-deny path (cmd starts with "cmd" which is not on
274+ // the default allowlist), which fires the truncating warn! at policy.rs.
275+ let p = default_policy ( ) ;
276+ let result = p. validate_command_execution ( cmd, false ) ;
277+ assert ! (
278+ result. is_err( ) ,
279+ "command should be blocked, but did not panic"
280+ ) ;
281+
282+ // And the high-risk-blocked path: allowlist passes (curl is allowed), then
283+ // risk gate fires (curl is a high-risk command), exercising the truncating
284+ // warn! site at the block_high_risk_commands branch.
285+ let prefix = "curl https://example.com/" ;
286+ let filler = "a" . repeat ( 80 - prefix. len ( ) - 1 ) ;
287+ let high_risk_cmd = format ! ( "{prefix}{filler}魔" ) ;
288+ assert ! (
289+ !high_risk_cmd. is_char_boundary( 80 ) ,
290+ "fixture must straddle byte 80 with a multi-byte char"
291+ ) ;
292+ let high_risk_policy = SecurityPolicy {
293+ allowed_commands : vec ! [ "curl" . into( ) ] ,
294+ ..SecurityPolicy :: default ( )
295+ } ;
296+ let blocked = high_risk_policy. validate_command_execution ( & high_risk_cmd, true ) ;
297+ assert ! ( blocked. is_err( ) ) ;
298+ assert ! ( blocked. unwrap_err( ) . contains( "high-risk" ) ) ;
299+ }
300+
301+ // Pathological short multi-byte command — exercises the boundary logic at the
302+ // edge case where `cmd.len() < 80`.
303+ #[ test]
304+ fn validate_command_handles_short_multibyte_command ( ) {
305+ let p = default_policy ( ) ;
306+ // 6 bytes (two 3-byte CJK chars) — well under the 80-byte log cap.
307+ let _ = p. validate_command_execution ( "魔兽" , false ) ;
308+ }
309+
254310// -- is_path_allowed ----------------------------------------------
255311
256312#[ test]
0 commit comments