-
앱 보호하기: 에이전틱 기능에 대한 위험 완화하기
데이터 유출과 의도하지 않은 동작 같은 간접적인 프롬프트 인젝션으로 인한 위협을 평가하는 방법을 살펴보세요. 사용자 확인, 안전한 프롬프트 설계, 인증과 같은 보안 강화 기능 등 앱 인텐트와 Foundation Models 프레임워크 사용을 위한 시스템 보호 기능과 보안 모범 사례를 살펴보세요.
챕터
- 0:00 - Introduction
- 2:06 - Risks
- 6:32 - Threat modeling
- 11:56 - Implementing mitigations
- 12:03 - Foundation Models
- 17:55 - App Intents
리소스
관련 비디오
WWDC26
- 앱 스키마로 지능형 Siri 경험 빌드하기
- Foundation Models 프레임워크로 에이전틱 앱 경험 빌드하기
- Siri 및 Apple Intelligence를 위한 고급 앱 인텐트 기능 살펴보기
WWDC25
WWDC20
-
비디오 검색…
안녕하세요, 저는 Willy입니다 오늘은 앱 내 에이전틱 기능에서 발생할 수 있는 새로운 위험을 식별하고 완화하는 방법을 알려드리겠습니다 이후에는 제 동료 Akshay가 구체적이고 실행 가능한 단계를 플랫폼에서 제공하는 API를 활용해 앱을 보호하는 방법으로 안내해 드릴 예정입니다 대규모 언어 모델, 즉 LLM이 일반화되면서 많은 앱이 LLM을 활용해 새롭고 지능적인 기능을 구현하는 방법을 모색하고 있으며 LLM이 핵심 시스템 구성 요소가 되고 있습니다 앱 내에서 명령과 프롬프트를 보내 사용자의 요청과 추가 컨텍스트를 담아 LLM이 하나 이상의 액션을 실행하도록 하고 중간 결과를 얻어 최종적으로 사용자에게 응답을 제공할 수 있습니다 저희 플랫폼에서는 두 가지 방법으로 에이전틱 경험을 만들 수 있습니다 Foundation Models 프레임워크로 직접 에이전트를 설계하거나 App Intents 프레임워크로 앱이 Siri와 연동되도록 할 수 있습니다
새로운 기능에는 새로운 보안 위험이 따릅니다 LLM은 앱 내에 새로운 확률적 엔진을 도입하는데 강력하지만 속임수에 취약할 수 있습니다 이 발표의 목적은 에이전틱 기능의 새로운 보안 위험을 강조하고 에이전틱 기능에 대한 보안 위험을 사용자를 보호하는 데 활용할 수 있는 기술과 API를 제공하는 것입니다 핵심은, 앱이 의도한 대로 작동하고 사용자 보안을 고려해 운영되도록 보장하는 것입니다 시작하기 전에 이 발표에서 다루지 않는 내용을 명확히 하겠습니다 모델 안전성에 대해서는 다루지 않습니다 모델 안전성은 모델 출력이 안전한지 보장하는 것을 말합니다 또한 모델 가드레일과 우회 시도 방지에 대해서도 논의하지 않습니다 여기서 다루는 일부 원칙들이 이런 케이스를 처리하는 데 활용될 수 있지만 저희는 외부 공격자가 앱을 침해하려는 상황에 집중할 것입니다 모델 안전성을 검토하고 싶다면 아래에 링크된 훌륭한 발표를 확인하세요
에이전틱 시스템과 함께 오는 새로운 위험에 대해 이야기해 보겠습니다 먼저 공격자가 앱을 타깃으로 삼는 이유를 생각해 보겠습니다 앱이 공격자가 관심을 가질 만한 작업을 수행할 수 있습니다 민감한 사용자 데이터 보관, 금융 거래 처리 마이크나 카메라 같은 시스템 리소스 접근 또는 물리적 장치 제어 등이 있습니다 공격자는 앱을 악용해 자신의 목적을 달성하려 할 수 있습니다 공격과 완화 방법을 더 잘 설명하기 위해 Loose Leaf 앱을 활용해 설명하겠습니다 차세대 소셜 네트워크가 될 수 있는 예시 앱으로 핫티, 아이스티, 버블티 등 모든 종류의 차를 위한 앱입니다 Loose Leaf가 소셜 네트워킹의 미래가 될 것이라 확신합니다
Loose Leaf에는 이미 몇 가지 흥미로운 기능이 있습니다 친구에게 차 레시피를 메시지로 보내는 기능이나 멋진 차 파티 사진을 공유하는 기능 등입니다 이전에는 이러한 기존 기능에 대해 위협 모델링하고 완화하는 방법을 이야기했습니다 기본 사항을 잊지 않으려면 해당 영상을 복습해 보세요 이제 Loose Leaf 개발자들이 열심히 준비해 온 새로운 기능을 발표하게 되어 기쁩니다 바로 " "차 파티 준비하기"입니다 Foundation Models 및 App Intents 프레임워크를 활용해 캘린더를 확인해 차 파티를 열기 좋은 최적의 시간을 찾고 어떤 친구들을 초대할지 결정하며 프로필을 기반으로 어떤 차를 제공할지 파악하고 모두가 좋아하는 차를 직접 주문해 드립니다! 와우!
이 새 기능은 Loose Leaf의 에이전틱 루프를 기반으로 하며 두 가지 주목할 만한 속성이 있습니다 첫째, 이 기능은 여러 위치에서 컨텍스트를 가져와 에이전트가 결정을 내리는 데 활용합니다 둘째, 에이전트는 사용자를 대신해 하나 이상의 액션을 수행할 수 있으며 이는 다양한 부작용을 일으킬 수 있습니다
첫 번째 속성부터 시작해 새로운 위험을 소개하겠습니다 바로 간접 프롬프트 인젝션입니다 간접 프롬프트 인젝션이란 제어 흐름을 바꾸려는 의도로 모델에 제공되는 추가 컨텍스트에 삽입된 명령을 말합니다
에이전틱 루프에서 이는 프롬프트의 초기 추가 컨텍스트에 삽입된 명령이거나 툴 결과 내에 삽입된 명령을 말합니다
실제로 이것이 어떤 모습인지 살펴보면 사용자가 캘린더를 첨부해 차 파티 시작을 요청하는데 캘린더에 모델에게 명령을 내리는 이벤트가 포함되어 있어 민감한 사용자 데이터 삭제 같은 다른 액션을 수행하도록 유도하는 경우입니다! 이런! 위협 모델링 과정에서 신뢰할 수 없는 컨텍스트의 모든 소스를 파악하는 것이 중요합니다 에이전틱 시스템의 두 번째 속성은 액션 호출 기능으로 잠재적으로 부작용을 유발할 수 있으며 액션 실행의 의도치 않은 결과를 초래할 수 있습니다
간접 프롬프트 인젝션과 결합되면 공격자가 부작용이 있는 액션을 실행시켜 자신의 목적을 달성할 수 있습니다 사용자 데이터 유출, 금전 탈취 물리적 장치 제어, 데이터 삭제 등이 가능합니다
간접 프롬프트 인젝션이 의도치 않은 액션으로 이어질 때 인젝션이 두 가지 다른 효과를 가져온다고 볼 수 있습니다 첫째는 데이터 포이즈닝입니다 공격자가 실행되는 액션의 매개변수를 조작하는 것을 말합니다 예를 들어 사용자가 엄마에게 메시지를 보내려 하는데 공격자가 메시지를 자신에게 보내도록 명령을 삽입하는 경우입니다
둘째는 액션 포이즈닝입니다 공격자가 실행할 액션 자체를 조작하는 것입니다 사용자는 단순히 이메일 요약을 요청할 수 있지만 공격자가 LLM을 유도해 악성 웹 페이지를 열도록 하고 이메일에 공격자가 선택한 URL을 첨부하는 경우입니다
이 위험들을 개념화하기 위해 Simon Willison의 치명적 트리플렛을 살펴보면 에이전틱 시스템이 다음을 모두 갖출 때 사용자가 가장 위험하다고 설명합니다 개인 데이터 접근 신뢰할 수 없는 콘텐츠 노출 외부 통신 능력 마지막 항목은 더 일반화하여 부작용이 있는 모든 액션의 위험성을 고려할 수 있습니다
이 섹션을 요약하자면 간접 프롬프트 인젝션 해결은 현재 활발히 연구 중인 분야임을 강조하고 싶습니다 즉, 현재로서 최선의 접근 방식은 앱이 얼마나 위험에 노출되어 있는지 이해하고 그 위험을 완화하는 것입니다 에이전틱 시스템에서 발생하는 위험을 논의했으니 이제 위협 모델링 과정을 진행해 보겠습니다 앱에서 신뢰할 수 없는 데이터 소스를 식별하고 잠재적으로 위험한 액션을 파악하는 과정입니다 에이전틱 루프 입력, 즉 프롬프트에 대한 데이터 흐름 분석부터 시작합니다 프롬프트라고도 합니다 프롬프트를 구성하는 데 사용할 데이터 소스를 파악해야 합니다 이 과정에서 프롬프트 인젝션을 포함할 수 있는 신뢰할 수 없는 컨텍스트 소스를 정확히 짚어내야 합니다 Loose Leaf 앱으로 돌아가 보면 프롬프트 구성에 영향을 주는 데이터 소스가 몇 가지 있습니다 첫째는 LLM에 목적과 역할에 대한 안내를 제공하는 명령입니다 목적과 역할에 대한 지침입니다 다음은 사용자 프롬프트입니다 LLM이 수행할 작업과 달성하려는 목표입니다 프롬프트에는 LLM이 목표를 달성하는 데 도움이 되는 추가 컨텍스트도 포함될 수 있습니다 과거 차 주문 내역, 사용자가 저장한 차 레시피 등이 있습니다 차 파티에 최적의 시간을 결정하는 데 도움이 되는 예정된 캘린더 이벤트 그리고 친구들이 공유하는 콘텐츠를 포함하는 친구 피드도 있습니다 프롬프트에 영향을 주는 데이터 소스를 파악했다면 무엇이 신뢰할 수 없는지 파악해야 합니다 일반적인 원칙으로 외부 엔터티에서 오는 모든 입력을 공격 표면으로 볼 수 있습니다 저희의 경우 캘린더 콘텐츠와 친구 피드를 신뢰할 수 없다고 봅니다 누구든지 사용자에게 캘린더 초대장을 보낼 수 있고 그것이 모델에 입력될 수 있으며 사용자의 "친구"가 피드에 무엇이든 게시할 수 있어 프롬프트에 입력될 수 있기 때문입니다 이 모두가 실행할 액션에 영향을 미치는 프롬프트 인젝션을 포함할 수 있습니다
신뢰할 수 없는 컨텍스트 소스를 파악한 후에는 에이전트가 사용할 수 있는 액션을 검토하고 각 액션의 부작용을 살펴봐야 합니다 먼저 OrderTeaTool()이 있습니다 차 파티를 위한 차를 준비하는 필수 액션입니다
PostAndFetchPublicFeedTool()은 모델이 생성한 메시지를 사용자 피드에 게시하고 친구들에게 소식을 알리는 데 유용합니다
BrewingTimerIntent()는 차 파티 중에 차가 올바른 시간 동안 우려지도록 도와줍니다 마지막으로 Delete Photo는 사용자 피드에서 사진을 삭제합니다 찻잎이 예쁘게 나오지 않았을 때를 위한 기능입니다 이 모든 액션을 고려할 때 각 액션의 부작용이 무엇인지 파악해야 합니다
OrderTeaTool()은 금융적 위험이 있습니다 의도치 않게 호출되면 사용자가 돈을 잃을 수 있습니다
반면 PostAndFetchPublicFeedTool()은 데이터 유출 위험이 있습니다 모델이 공개 게시물을 통해 민감한 정보를 노출시킬 수 있습니다
BrewingTimerIntent()는 자체적으로는 부작용이 없을 수 있지만 레이블을 받는 경우 프롬프트 인젝션이 이후 공격을 위한 추가 명령을 작성하도록 허용할 수 있습니다
Delete Photo는 실행 취소 기능이 없을 경우 데이터 손실 위험이 있습니다
이제 악성 입력이 LLM에 어떻게 입력될 수 있는지와 액션이 가질 수 있는 부작용을 파악했으니 사용자를 보호할 완화 방법을 설계하고 구현하기 시작할 수 있습니다 기준으로서 결정론적 완화 방법에 집중하는 것이 중요합니다 보안 보장이 감사하고 추론하기 더 쉽기 때문입니다
모델 기능이 빠르게 발전함에 따라 더 확률적인 보장을 제공하는 다른 완화 방법도 고려할 수 있습니다 여기서는 앱을 보호하는 데 사용할 수 있는 몇 가지 완화 방법을 제시합니다 앱을 보호하는 데 활용할 수 있는 방법들로 프롬프트 수준에서 검사를 추가하거나 액션 실행 단계에서 추가할 수 있습니다 Siri AI를 설계하면서 이 중 일부를 활용했습니다 지금 하나씩 살펴보겠습니다 먼저 프롬프트를 다시 살펴보고 프롬프트 완화 방법을 추가할 수 있습니다 민감한 데이터를 편집할 수 있습니다 예를 들어 과거 주문에 저장된 개인 식별 정보, 즉 PII 같은 것입니다 과거 주문에 저장된 데이터입니다 그렇게 하면 민감한 데이터가 LLM에 도달하지 않아 유출될 수 없습니다 다음으로 모델에 스포트라이팅을 적용할 수 있습니다 이 콘텐츠가 신뢰할 수 없는 것임을 나타내기 위해서입니다 이것은 확률적 완화 방법입니다 프롬프트 인젝션이 스포트라이팅을 무효화하는 방식으로 구성될 수 있기 때문입니다 그래도 적용하는 것을 권장합니다 모델에 따라 이러한 제한을 더 효과적으로 적용할 수 있기 때문입니다
이제 구현할 수 있는 액션 완화 방법을 살펴보겠습니다
먼저 어떤 액션에 사용자 확인이 필요한지 고려하세요 부작용이 있어 계속하기 전에 사람이 확인할 가치가 있는 액션들입니다 부작용 때문에 확인이 필요합니다 다음으로 어떤 툴이 디바이스가 인증되었거나 잠금 해제된 상태에서만 작동해야 하는지 고려하세요 에이전트가 잠금 화면에서도 접근할 수 있기 때문에 사용자에게 상당한 위험이 있는 액션은 접근할 수 없어야 합니다
다양한 종류의 완화 방법과 시스템에 적용하는 방법을 살펴봤지만 더 많은 유형이 존재합니다 직접 탐색하여 앱의 위험을 완화하시기 바랍니다
위협 모델링에서 기억해야 할 핵심은 공격자가 앱에서 원하는 것이 무엇인지 파악하고 프롬프트 수준의 위험을 해결하기 위한 완화 방법을 적용하거나 액션 실행 단계에서 적용하는 것입니다 이제 Akshay가 앱을 보호하는 데 사용할 수 있는 구체적인 툴을 보여드리겠습니다 Akshay, 부탁드립니다!
감사합니다, Willy 안녕하세요, 저는 Akshay입니다 Willy가 방금 논의한 가드레일 중 일부로 에이전틱 앱을 보호하는 방법을 보여드리겠습니다 Foundation Models 프레임워크를 사용해 앱을 빌드하고 있다면 에이전트 실행에 보안 체크포인트를 주입하는 방법을 보여드리겠습니다
App Intents를 사용해 Apple Intelligence와 연동하고 있다면 그곳에서 사용 가능한 보안 완화 방법을 다루겠습니다 Foundation Models부터 시작하겠습니다 Foundation Models 프레임워크는 에이전트 빌드를 위한 강력한 API를 제공합니다 라이프사이클 이벤트 수정자 API를 중점적으로 살펴보고 보안 가드레일 주입에 활용해 보겠습니다 프레임워크에 대한 기본적인 이해가 있다고 가정하겠습니다 더 알고 싶다면 아래 링크된 훌륭한 발표를 확인하세요 먼저 Foundation Models를 사용해 Loose Leaf 앱의 간단한 에이전트를 만들어 보겠습니다 저는 에이전트를 만들기 전에 항상 다르질링 블랙티 한 잔이 필요하더라고요 다르질링 블랙티 한 잔이 없으면 안 되죠 그래서 가장 먼저 차를 주문하는 툴을 만들겠습니다 툴을 정의하려면 Tool 프로토콜을 따릅니다 툴의 이름, 설명, Arguments를 지정합니다 모델은 이 메타데이터를 사용해 툴의 목적과 호출 방법을 파악합니다 그런 다음 툴이 호출될 때 실행되는 실제 Implementation을 제공합니다
툴을 하나 더 정의해 보겠습니다 PostAndFetchPublicFeedTool은 메시지를 공개 피드에 게시하고 새로 게시된 메시지를 가져옵니다 에이전트 빌드의 다음 단계는 Profile을 만드는 것입니다 Profile에 먼저 모델 Instructions를 추가하고 방금 정의한 툴을 추가합니다 그런 다음 사용할 모델 등의 세션 속성을 연결합니다 여기서는 온디바이스 모델을 사용합니다
이 Profile로 LanguageModelSession을 인스턴스화하면 에이전틱 루프에서 사용할 수 있습니다 기본 에이전트를 만들었으니 이제 보안 정책을 주입하겠습니다 이를 위해 라이프사이클 이벤트 수정자를 사용하겠습니다 이 수정자는 결정론적으로 트리거되는 콜백으로 세션 실행의 특정 라이프사이클 지점에서 작동합니다 따라서 이 라이프사이클 이벤트를 체크포인트로 활용해 보안 정책을 구현할 수 있습니다 지금 이 수정자 중 두 가지를 살펴보겠습니다
간략화된 에이전틱 루프로 돌아가 보겠습니다 시시포스처럼 LLM은 각 반복마다 액션을 출력하고 이 액션은 Executor가 실행하며 그 출력이 다음 반복을 위해 LLM에 다시 전달됩니다 첫 번째 수정자는 툴 호출이 실행되기 전에 인터셉트할 수 있게 합니다 바로 .onToolCall 수정자입니다 LLM이 툴 호출을 출력할 때 반드시 트리거되며 executor가 툴을 실행하기 전에 작동합니다 여기서 중요한 점은 이 콜백이 오류를 던지면 툴이 절대 실행되지 않는다는 것입니다 제어가 즉시 루프로 돌아갑니다 이곳이 확인을 강제하기에 완벽한 장소입니다
Loose Leaf 에이전트로 돌아가면 OrderTeaTool이 금융적 영향이 있어 매우 걱정이 됩니다 그래서 항상 사용자 확인을 요청하고 싶습니다 이 툴을 실행하고 돈을 이체하기 전에 말이죠
이를 위해 profile에 .onToolCall 콜백을 추가합니다 이 콜백은 모든 툴 호출 전에 실행되므로 먼저 현재 툴이 OrderTeaTool인지 확인합니다 아니라면 즉시 반환하고 툴이 실행됩니다 맞다면 사용자에게 확인을 요청합니다 사용자가 확인하지 않으면 오류를 던져 툴 실행을 중단합니다 confirmWithUser() 함수를 자체 구현으로 대체하세요 핵심은 확인 로직을 코드의 이 한 지점에만 추가함으로써 코드의 이 한 지점에만 추가함으로써 모든 툴 호출에 대해 완전한 적용 범위를 얻을 수 있다는 것입니다 요약하면, 이 수정자는 모든 툴 실행 전에 실행되며 이 콜백이 반환될 때까지 툴 자체는 실행되지 않습니다 오류를 던져 툴 실행을 차단할 수 있습니다 개념적으로 .onToolCall 수정자는 모델의 출력에서 실행됩니다 이제 모델의 입력을 검사하는 데 도움이 되는 수정자를 살펴보겠습니다 .historyTransform은 추론을 위해 모델에 트랜스크립트가 렌더링되기 전에 실행됩니다 새 사용자 요청이 도착할 때와 루프의 각 반복에서 모두 발생합니다 변환은 트랜스크립트의 꼬리 부분을 수정하며 스포트라이팅과 PII 편집에 활용하겠습니다 예제로 돌아가 보면 PostAndFetchPublicFeedTool()이 공개 피드의 게시물을 반환합니다 공격자가 쉽게 해당 피드에 프롬프트 인젝션을 게시할 수 있습니다 이 피드의 출력을 의심스럽게 다뤄야 합니다 그래서 이 출력에 특수 태그로 표시를 하여 이것이 신뢰할 수 없는 데이터임을 모델에 알리고자 합니다
이를 위해 스포트라이팅 구분자를 추가합니다 .historyTransform 내부에서 합니다 콜백에서 먼저 항목들을 반복하며 해당 툴의 toolOutput 항목에만 집중합니다 다른 모든 항목은 수정 없이 출력 트랜스크립트에 복사됩니다 그런 다음 toolOutput 항목을 수정합니다 세그먼트를 반복하며 각 관련 세그먼트에 구분자 태그를 추가합니다 이 예에서는 꺾쇠 괄호 "<>"를 사용합니다 모델에 적합한 태그를 사용하세요 구현을 건너뛸 delimit() 함수는 텍스트 세그먼트를 구분된 콘텐츠가 있는 형태로 변환합니다 이제 편집을 살펴보겠습니다 실제로 민감한 데이터 편집에도 똑같은 아이디어를 사용할 수 있습니다 단지 delimit() 함수를 편집 함수로 교체하기만 하면 됩니다 민감한 데이터를 플레이스홀더 문자열 리터럴 ""로 교체하는 함수입니다
기억해야 할 중요한 사항이 있습니다 변환된 항목은 현재 추론 반복에만 적용됩니다 즉, 이 수정 사항은 다음 추론 호출에서는 보이지 않습니다 다시 적용해야 합니다 지속시키고 싶은 비용이 높은 변환의 경우 @SessionProperty 어노테이션을 사용하세요 세션 기록에 상태 저장 변환을 적용할 수 있습니다 자세한 내용은 문서를 참조하세요 라이프사이클 이벤트 수정자가 어떻게 보안 정책 주입을 위한 결정론적 훅을 제공하는지 살펴봤습니다 하지만 모든 수정자를 다루지는 않았습니다 프레임워크는 훨씬 더 많은 수정자를 제공하며 에이전틱 루프의 다른 중요 지점에서 트리거됩니다 프레임워크에서는 자체 프로필 수정자를 직접 빌드하고 재사용 가능한 구성 요소로 패키징할 수도 있습니다 Foundation Models 문서를 참조해 이 기능과 다른 강력한 기능들에 대해 더 자세히 알아보세요 이제 App Intents로 주제를 바꾸겠습니다 App Intents를 사용하면 앱을 Apple Intelligence와 연동하고 Siri, Spotlight, 단축어 등 풍부한 시스템 경험을 제공할 수 있습니다 이 발표의 나머지 부분에서는 App Intents와 App Schemas의 기본 사항을 알고 있다고 가정하겠습니다 더 알고 싶다면 아래에 링크된 훌륭한 세션들을 확인하세요 간단히 요약하면, App Intent가 인텐트 스키마를 채택하면 Siri 모델의 툴로 사용 가능해집니다 예를 들어, 여기 DeletePhotoIntent는 photos 도메인의 deleteAssets 스키마를 채택합니다 개념적으로 Delete Photo 액션이 Siri 툴박스에 추가되는 것입니다 이를 통해 Siri가 툴 정의를 추론하고 사용자 쿼리를 처리하기 위해 호출할 수 있습니다 하지만 어떤 인텐트를 호출할지 결정하는 것은 모델이기 때문에 프롬프트 인젝션 공격으로 공격자가 앱을 악용해 데이터 유출이나 다른 악의적인 목적에 이용할 수 있습니다 예를 들어, 여기서는 외부 컨텍스트와 함께 실행 중이며 사용자 의도 없이 Delete Photo 함수를 실행하려 할 수 있습니다 이런 공격이 성공하면 Willy의 강력한 경고에도 불구하고 다른 결정론적 가드레일이 없다면 Willy의 강력한 경고에도 불구하고 실제로 데이터 손실이 발생할 수 있습니다 외부적으로 보이는 부작용이 있거나 파괴적인 액션은 공격자의 매력적인 타깃이 됩니다 App Intents 시스템은 이러한 공격을 완화하는 데 도움이 되는 여러 가드레일을 갖추고 있습니다 그 중 두 가지를 살펴보겠습니다: 확인과 잠금 화면 인증입니다 확인부터 시작하겠습니다 시스템은 위험 기반의 상황별 확인 메커니즘을 사용합니다 앱의 고위험 액션에서 자동으로 확인을 트리거합니다 액션의 위험도는 정적 액션 메타데이터와 동적 시스템 상태를 고려해 결정됩니다 인텐트가 선택되면 실행 전에 시스템이 인텐트의 위험 메타데이터로 위험 평가 시스템을 호출합니다 이 메타데이터는 나중에 다시 살펴보겠습니다 위험 평가 구성 요소는 시스템의 동적 상태도 입력으로 받습니다 두 가지를 결합해 이 인텐트의 전반적인 위험도를 결정합니다 위험도가 높다고 판단되면 사용자에게 확인을 요청합니다 사용자가 이 액션을 확인하면 정상적인 제어 흐름이 계속되어 인텐트가 실행됩니다
반면 사용자가 거부하면 실행이 차단되고 인텐트는 절대 호출되지 않습니다 이제 위험 메타데이터로 돌아가 보겠습니다
위험 메타데이터는 모든 인텐트에 할당되는 내부 위험 데이터입니다 인텐트의 부작용을 기반으로 합니다 특정 부작용은 다른 것보다 더 위험한 것으로 간주됩니다 예를 들어 디바이스 상태를 삭제하는 인텐트는 DeletePhotoIntent처럼 고위험으로 간주될 수 있습니다 데이터를 유출하는 인텐트도 손상을 일으킬 수 있습니다 오염된 컨텍스트에서 실행되는 경우에는요 공유 콘텐츠에서 동작하는 업데이트 인텐트도 위험할 수 있습니다 시스템은 고위험 툴에 대해 더 확인을 트리거할 가능성이 높습니다 그렇다면 위험 메타데이터가 App Intent와 어떻게 연결될까요?
위험 메타데이터는 인텐트가 스키마를 채택할 때 자동으로 할당됩니다 추가 작업이 필요 없습니다 기술적으로는 스키마에 위험 메타데이터가 연결되어 있습니다 예를 들어 deleteAssets 스키마는 사진을 삭제하는 데 사용되므로 파괴적인 부작용이 있습니다 따라서 DeletePhotoIntent에도 이 파괴적인 부작용이 할당됩니다 하지만 위험은 미묘합니다 타이머를 설정하는 새 인텐트를 정의해 보겠습니다 이 인텐트는 createTimer 스키마를 채택합니다 이 스키마의 위험도는 어떻게 생각하시나요? 표면적으로는 공격자가 타이머를 만드는 것으로 큰 피해를 줄 수 없을 것 같아 이 액션을 확인할 필요가 없어 보입니다 하지만 더 살펴보면, 스키마가 타이머의 선택적 String 속성을 레이블로 정의합니다 인텐트의 인수를 결정하는 것은 모델임을 기억하세요 인텐트의 인수를 결정하는 것은 모델임을 기억하세요 따라서 프롬프트 인젝션이 이 레이블을 공격자가 제어하는 값으로 설정할 수 있습니다 이후 타이머 목록 조회 시 이 공격자가 제어하는 데이터를 컨텍스트로 가져와 새 컨텍스트도 오염시킬 수 있습니다 따라서 createTimer 같은 경우에 확인을 완전히 건너뛰는 것은 안전하지 않습니다 시스템은 이러한 중간 상황을 이해합니다 앞서 논의한 동적 시스템 상태가 여기서 역할을 합니다 이 정보는 현재 시스템 컨텍스트에서 확인이 필요한지 판단하는 데 사용됩니다 이 액션의 동적 위험을 포착하는 것입니다 요약하면, 확인 시스템은 상황별이고 위험 기반임을 기억하세요 인텐트는 채택한 인텐트 스키마에서 부작용을 상속받습니다 위험한 부작용이 있는 액션은 확인될 가능성이 더 높습니다 이제 잠금 화면 인증을 살펴보겠습니다 아시다시피 잠금 화면에서 Siri와 상호작용할 수 있습니다 디바이스를 먼저 잠금 해제하지 않아도 됩니다 빠른 작업을 수행하거나 손이 바쁠 때 편리합니다 하지만 이는 잠긴 디바이스를 물리적으로 소유한 공격자가 Siri를 통해 인텐트를 호출할 수 있음을 의미합니다 따라서 주의하지 않으면 앱이 공격자에 의해 데이터 유출이나 악의적인 액션 실행에 사용될 수 있습니다 이런 위협에 대한 주요 완화 방법은 위험한 액션을 실행하기 전에 사용자에게 디바이스 잠금 해제를 요청하는 것입니다 App Intent에서 인증 정책이 어떻게 정의되는지 살펴보겠습니다 사용자 정의 App Intent의 경우 authenticationPolicy 속성을 설정해 인증 동작을 명시적으로 설정할 수 있습니다 예를 들어, DeletePhotoIntent는 파괴적이므로 잠긴 디바이스에서 실행되지 않도록 하고 싶습니다 따라서 authenticationPolicy 속성을 명시적으로 설정합니다 .requiresAuthentication으로 설정합니다 @AppIntent가 인텐트 스키마를 채택할 때는 상황이 약간 다릅니다
스키마에는 자체 기본 authenticationPolicy가 있습니다 이 정책은 내부적으로 설정되며 각 스키마의 민감도와 처리하는 데이터를 기반으로 합니다 부작용과 마찬가지로 인텐트에는 스키마의 기본 정책이 자동으로 할당됩니다 하지만 원한다면 기본값을 명시적으로 재정의할 수 있습니다 유일한 제약은 정책이 더 엄격해야 한다는 것입니다 예를 들어 deleteAssets 스키마의 기본 정책이 .requiresAuthentication이라고 가정해 보겠습니다 여기서 명시적으로 정책을 설정하지 않으면 @AppIntent에 동일한 정책이 할당되어 실행 전에 인증이 필요하게 됩니다
하지만 더 약한 정책을 설정하려 하면 허용되는 최소 정책을 친절하게 알려주는 빌드 오류가 발생합니다 요약하면, 인증은 잠금 화면 공격에 대한 중요한 완화 방법입니다 스키마에는 자체 기본 인증 정책이 있으며 App Intent에 할당됩니다 스키마 정책을 재정의할 수 있지만 더 엄격하게만 가능합니다 잠금 화면 동작을 염두에 두고 인텐트를 검토하세요 다시 Willy에게 넘기겠습니다! 훌륭했습니다, Akshay! 요약하면, 에이전틱 앱의 다음 단계는 위협 모델을 수립하는 것으로 프롬프트에서 신뢰할 수 없는 컨텍스트 소스를 찾고 프롬프트에서 신뢰할 수 없는 컨텍스트 소스를 찾아 각 액션의 부작용을 기반으로 위험 수준을 결정하는 것입니다 부작용을 기반으로 합니다 Akshay의 안내를 통해 앱에 가장 적합한 완화 방법을 구현하는 방법에 대한 발판을 마련했습니다 Foundation Models 프레임워크와 App Intents 프레임워크를 활용해서 말이죠 이제 기준을 높이고 방어를 신속하게 주입하세요!
-
-
12:50 - Tools
// Tools struct OrderTeaTool: Tool { let name = "orderTeaTool" let description: String = "Orders a particular quantity of a tea from the store." // Arguments // Implementation } struct PostAndFetchPublicFeedTool: Tool { let name = "postAndFetchPublicFeedTool" let description: String = "Posts a message to the public feed.” // Arguments // Implementation } -
13:13 - Profile
// Profile class LooseLeafAgent { struct DefaultProfile: LanguageModelSession.DynamicProfile { var body: some DynamicProfile { Profile { Instructions("You are a helpful, tea-loving assistant ... ") OrderTeaTool() PostAndFetchPublicFeedTool() } .model(SystemLanguageModel()) } } } -
13:28 - Session
// Session class LooseLeafAgent { struct DefaultProfile: LanguageModelSession.DynamicProfile { var body: some DynamicProfile { Profile { Instructions("You are a helpful, tea-loving assistant ... ") OrderTeaTool() PostAndFetchPublicFeedTool() } .model(SystemLanguageModel()) } } let session: LanguageModelSession public init() { self.session = LanguageModelSession(profile: DefaultProfile()) } } -
14:33 - Confirmation via onToolCall
// Confirmation via onToolCall var body: some DynamicProfile { Profile { Instructions("You are a helpful, tea-loving assistant ... ") OrderTeaTool() // Financial impact; risky tool. // Other Tools } .onToolCall { call in guard call.toolName == "orderTeaTool" else { return } guard ConfirmationAction.confirmWithUser() else { throw LooseLeafError.userConfirmationDenied } } } -
15:56 - Spotlighting via historyTransform
// Spotlighting via historyTransform var body: some DynamicProfile { Profile { Instructions("You are a helpful, tea-loving assistant ... ") PostAndFetchPublicFeedTool() // Returns untrusted data; requires spotlighting // Other Tools } .historyTransform {γentries in entries.map { entry in guard case .toolOutput(var toolOutput) = entry, toolOutput.toolName == "postAndFetchPublicFeedTool" else { return entry } } toolOutput.segments = toolOutput.segments.map { segment in delimit(segment: segment, startDelimiter: "<<UNTRUSTED>>", endDelimiter: "<</UNTRUSTED>>") } return .toolOutput(toolOutput) } } func delimit(segment: Transcript.Segment, startDelimiter: String, endDelimiter: String) -> Transcript.Segment -
16:48 - Redaction via historyTransform
// Redaction via historyTransform var body: some DynamicProfile { Profile { Instructions("You are a helpful, tea-loving assistant ... ") PostAndFetchPublicFeedTool() // Returns untrusted data; requires spotlighting // Other Tools } .historyTransform {γentries in entries.map { entry in guard case .toolOutput(var toolOutput) = entry, toolOutput.toolName == "postAndFetchPublicFeedTool" else { return entry } } toolOutput.segments = toolOutput.segments.map { segment in redactPII(segment: segment, placeHolder: "[REDACTED]") } return .toolOutput(toolOutput) } } func redactPII(segment: Transcript.Segment, placeHolder: String) -> Transcript.Segment -
23:08 - Intent authentication policy
// Intent authentication policy struct DeletePhotoIntent: DeleteIntent { var entities: [LooseLeafPhoto] static var authenticationPolicy: IntentAuthenticationPolicy = .requiresAuthentication func perform() async throws -> some IntentResult { // Implementation } } -
23:27 - Schema authentication policy
// Schema authentication policy @AppIntent(schema: .photos.deleteAssets) struct DeletePhotoIntent { var entities: [LooseLeafPhoto] // Example: Schema default authentication policy is .requiresAuthentication func perform() async throws -> some IntentResult { // Implementation } }
-
-
- 0:00 - Introduction
Agentic features introduce new security risks. We cover how to identify those risks and introduce techniques and APIs to protect your users.
- 2:06 - Risks
Understand new risks that come with using agentic systems in your app.
- 6:32 - Threat modeling
A threat-modeling exercise for your app can help identify which context sources are untrusted and which actions are potentially risky.
- 11:56 - Implementing mitigations
Learn about concrete tools that you can use to secure your agentic app.
- 12:03 - Foundation Models
If you use the Foundation Models framework, learn how to inject security checkpoints into your agent execution.
- 17:55 - App Intents
Learn about security mitigations available when integrating with Apple Intelligence using App Intents.