-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Desktop alerts when suspicious unicode characters found in Recipe #4080
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9219901
a2b5253
4a627ca
5259aec
4e0720e
fb6735d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ use std::fmt; | |
|
|
||
| use crate::agents::extension::ExtensionConfig; | ||
| use crate::agents::types::RetryConfig; | ||
| use crate::utils::contains_unicode_tags; | ||
| use serde::de::Deserializer; | ||
| use serde::{Deserialize, Serialize}; | ||
| use utoipa::ToSchema; | ||
|
|
@@ -253,6 +254,25 @@ pub struct RecipeBuilder { | |
| } | ||
|
|
||
| impl Recipe { | ||
| /// Returns true if harmful content is detected in instructions, prompt, or activities fields | ||
| pub fn check_for_security_warnings(&self) -> bool { | ||
| if [self.instructions.as_deref(), self.prompt.as_deref()] | ||
| .iter() | ||
| .flatten() | ||
| .any(|&field| contains_unicode_tags(field)) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| if let Some(activities) = &self.activities { | ||
| return activities | ||
| .iter() | ||
| .any(|activity| contains_unicode_tags(activity)); | ||
| } | ||
|
|
||
| false | ||
| } | ||
|
|
||
| /// Creates a new RecipeBuilder to construct a Recipe instance | ||
| /// | ||
| /// # Example | ||
|
|
@@ -746,4 +766,41 @@ isGlobal: true"#; | |
| let extensions = recipe.extensions.unwrap(); | ||
| assert_eq!(extensions.len(), 0); | ||
| } | ||
|
|
||
| #[test] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this test strikes me as too trivial to do any good
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just making sure we're not bypassing any of the places we want to look into |
||
| fn test_check_for_security_warnings() { | ||
| let mut recipe = Recipe { | ||
| version: "1.0.0".to_string(), | ||
| title: "Test".to_string(), | ||
| description: "Test".to_string(), | ||
| instructions: Some("clean instructions".to_string()), | ||
| prompt: Some("clean prompt".to_string()), | ||
| extensions: None, | ||
| context: None, | ||
| settings: None, | ||
| activities: Some(vec!["clean activity 1".to_string()]), | ||
| author: None, | ||
| parameters: None, | ||
| response: None, | ||
| sub_recipes: None, | ||
| retry: None, | ||
| }; | ||
|
|
||
| assert!(!recipe.check_for_security_warnings()); | ||
|
|
||
| // Malicious activities | ||
| recipe.activities = Some(vec![ | ||
| "clean activity".to_string(), | ||
| format!("malicious{}activity", '\u{E0041}'), | ||
| ]); | ||
| assert!(recipe.check_for_security_warnings()); | ||
|
|
||
| // Malicious instructions | ||
| recipe.instructions = Some(format!("instructions{}", '\u{E0041}')); | ||
| assert!(recipe.check_for_security_warnings()); | ||
|
|
||
| // Malicious prompt | ||
| recipe.prompt = Some(format!("prompt{}", '\u{E0042}')); | ||
| assert!(recipe.check_for_security_warnings()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,25 +18,47 @@ interface RecipeWarningModalProps { | |
| description?: string; | ||
| instructions?: string; | ||
| }; | ||
| hasSecurityWarnings?: boolean; | ||
| } | ||
|
|
||
| export function RecipeWarningModal({ | ||
| isOpen, | ||
| onConfirm, | ||
| onCancel, | ||
| recipeDetails, | ||
| hasSecurityWarnings = false, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the default?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assume there's no security warnings until we run the check and find any |
||
| }: RecipeWarningModalProps) { | ||
| return ( | ||
| <Dialog open={isOpen} onOpenChange={(open) => !open && onCancel()}> | ||
| <DialogContent className="sm:max-w-[80vw] max-h-[80vh] flex flex-col p-0"> | ||
| <DialogHeader className="flex-shrink-0 p-6 pb-0"> | ||
| <DialogTitle>⚠️ New Recipe Warning</DialogTitle> | ||
| <DialogTitle> | ||
| {hasSecurityWarnings ? '⚠️ Security Warning' : '⚠️ New Recipe Warning'} | ||
| </DialogTitle> | ||
| <DialogDescription> | ||
| You are about to execute a recipe that you haven't run before. Only proceed if you trust | ||
| the source of this recipe. | ||
| {!hasSecurityWarnings && | ||
| "You are about to execute a recipe that you haven't run before. "} | ||
| Only proceed if you trust the source of this recipe. | ||
| </DialogDescription> | ||
| </DialogHeader> | ||
|
|
||
| {hasSecurityWarnings && ( | ||
| <div className="px-6"> | ||
| <div className="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-4"> | ||
| <div className="flex items-start"> | ||
| <div className="ml-3"> | ||
| <div className="mt-2 text-sm text-yellow-700 dark:text-yellow-300"> | ||
| <p> | ||
| This recipe contains hidden characters that will be ignored for your safety, | ||
| as they could be used for malicious purposes. | ||
| </p> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| </div> | ||
| )} | ||
|
|
||
| <div className="flex-1 overflow-y-auto p-6 pt-4"> | ||
| <div className="bg-background-muted p-4 rounded-lg"> | ||
| <h3 className="font-medium mb-3 text-text-standard">Recipe Preview:</h3> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.