| 1053 | } |
| 1054 | |
| 1055 | static bool ha_normalized_tool_path(yyjson_val *root, yyjson_val *tool_input, char *path, |
| 1056 | size_t path_size) { |
| 1057 | if (!root || !tool_input || !yyjson_is_obj(tool_input) || !path || path_size == 0U) { |
| 1058 | return false; |
| 1059 | } |
| 1060 | const char *source = ha_obj_str(tool_input, "file_path"); |
| 1061 | if (!source) { |
| 1062 | source = ha_obj_str(tool_input, "path"); |
| 1063 | } |
| 1064 | if (!source || !source[0] || strlen(source) >= path_size) { |
| 1065 | return false; |
| 1066 | } |
| 1067 | snprintf(path, path_size, "%s", source); |
| 1068 | for (char *cursor = path; *cursor; cursor++) { |
| 1069 | if (*cursor == '\\') { |
| 1070 | *cursor = '/'; |
| 1071 | } |
| 1072 | } |
| 1073 | if (cbm_hook_path_is_abs(path)) { |
| 1074 | return true; |
| 1075 | } |
| 1076 | |
| 1077 | /* An explicitly supplied relative cwd is untrusted and ambiguous. Do not |
| 1078 | * silently reinterpret it against the hook process cwd. */ |
| 1079 | const char *payload_cwd = ha_obj_str(root, "cwd"); |
| 1080 | if (payload_cwd) { |
| 1081 | char supplied[4096]; |
| 1082 | if (strlen(payload_cwd) >= sizeof(supplied)) { |
| 1083 | return false; |
| 1084 | } |
| 1085 | snprintf(supplied, sizeof(supplied), "%s", payload_cwd); |
| 1086 | for (char *cursor = supplied; *cursor; cursor++) { |
| 1087 | if (*cursor == '\\') { |
| 1088 | *cursor = '/'; |
| 1089 | } |
| 1090 | } |
| 1091 | if (!cbm_hook_path_is_abs(supplied)) { |
| 1092 | return false; |
| 1093 | } |
| 1094 | } |
| 1095 | |
| 1096 | char cwd_buffer[4096]; |
| 1097 | const char *cwd = ha_normalized_cwd(root, cwd_buffer, sizeof(cwd_buffer)); |
| 1098 | if (!cwd) { |
| 1099 | return false; |
| 1100 | } |
| 1101 | char relative[4096]; |
| 1102 | snprintf(relative, sizeof(relative), "%s", path); |
| 1103 | int written = snprintf(path, path_size, "%s/%s", cwd, relative); |
| 1104 | return written > 0 && (size_t)written < path_size && cbm_hook_path_is_abs(path); |
| 1105 | } |
| 1106 | |
| 1107 | static const char *ha_active_tier(yyjson_val *root, const char *event) { |
| 1108 | if (!event || strcmp(event, "SubagentStart") != 0) { |
no test coverage detected