Reject Bedrock model ids that would produce ambiguous or malformed upstream URL paths. AWS Bedrock encodes the model in `/model/ /invoke`, so the value is interpolated directly into a URL path segment. Without validation, a value containing `/`, `\`, percent escapes, query or fragment delimiters, traversal segments, whitespace, or control characters could break out of the path segment, smuggle
(value: &str)
| 384 | /// for the same reason, and the contract is enforced again at the |
| 385 | /// router layer (`is_valid_bedrock_model_id`) as defense-in-depth. |
| 386 | fn validate_aws_bedrock_model_id(value: &str) -> Result<(), Status> { |
| 387 | let trimmed = value.trim(); |
| 388 | if trimmed.is_empty() { |
| 389 | return Err(Status::invalid_argument("model_id is required")); |
| 390 | } |
| 391 | if value != trimmed { |
| 392 | return Err(Status::invalid_argument(format!( |
| 393 | "AWS Bedrock model_id must not include leading or trailing whitespace: {value:?}" |
| 394 | ))); |
| 395 | } |
| 396 | if value.contains('/') || value.contains('\\') { |
| 397 | return Err(Status::invalid_argument(format!( |
| 398 | "AWS Bedrock model_id must not contain path separators: {value:?}" |
| 399 | ))); |
| 400 | } |
| 401 | if value.chars().any(|c| matches!(c, '?' | '#' | '%')) { |
| 402 | return Err(Status::invalid_argument(format!( |
| 403 | "AWS Bedrock model_id must not contain URL delimiters or percent escapes: {value:?}" |
| 404 | ))); |
| 405 | } |
| 406 | if value.contains("..") { |
| 407 | return Err(Status::invalid_argument(format!( |
| 408 | "AWS Bedrock model_id must not contain traversal segments: {value:?}" |
| 409 | ))); |
| 410 | } |
| 411 | if value.chars().any(|c| c.is_control() || c.is_whitespace()) { |
| 412 | return Err(Status::invalid_argument(format!( |
| 413 | "AWS Bedrock model_id must not contain whitespace or control characters: {value:?}" |
| 414 | ))); |
| 415 | } |
| 416 | Ok(()) |
| 417 | } |
| 418 | |
| 419 | fn validate_vertex_model_id(value: &str) -> Result<(), Status> { |
| 420 | let trimmed = value.trim(); |