어제는 내가 개발한 자소서 AI의 첫 개시일이었다. 설레는 마음으로 오픈채팅방에 링크를 뿌리고 유저가 오기만을 기다렸다.
드디어 첫번째 유저가 로그인을 했고, DB에는 나를 제외한 첫 유저가 등록되었다.
그런데 이 유저는 내 의도대로 서비스를 사용하는 것이 아니라 AI가 생성할 자소서의 질문 항목에 악의적인 프롬프트를 입력했다.
LLM API를 사용해 자소서를 작성하는데 채용공고 URL과 자소서 질문을 기반으로 결과를 생성한다.
한 번 시도하는 것도 아니라 자기 마음에 드는 결과가 나올 때까지 계속 시도하는 모습을 나는 실시간으로 지켜봤다. 다행히 프롬프트를 꽤 견고하게 짜놔서 그런지 LLM은 이상한 대답을 하지 않고 버텨줬다...
일단 급하게 서버를 내리고 빠르게 문제를 해결하기 위한 계획을 세웠다.
1번으로 유저를 차단하는 기능을 추가했다.
덕분에 이제 막 서비스를 공개한지 몇분 되지도 않았는데 다른 사용자의 유입을 방해받았다.
유저 차단 기능만 빠르게 추가하고 다시 배포를 한 결과 다행히 더 이상의 악의적인 프롬프트는 입력되지 않았다.
내 머리가 꽃밭이었는지, 이런 경우는 생각도 못했다. 이래서 실 서비스 운영 경험이 중요하다고 하는 건가 싶었다.
아직까지는 수동으로 유저를 차단하는 기능만 넣었기 때문에 더 강한 보안적인 조치가 필요했다.
그래서 다음과 같은 방법으로 악의적인 시도를 하는 유저를 대비하기 위한 준비를 하려고 한다.
처음에는 최대한 많은 사용자가 최대한 많이 이 기능을 사용해보길 원해서 횟수 제한 없이 가려고 했지만, 이런 악의적인 프롬프트는 나에게 도움이 될만한 데이터도 주지 않고 그저 토큰만 낭비할 뿐이었다. 그래서 일단은 횟수 제한을 둬서 다시는 이런 상황이 일어나지 않게 했다.
악성 유저가 악의적인 프롬프트를 포함한 AI 자소서를 다행히 삭제하지 않아서 증거를 남길 수 있었다. 원래 로직대로라면 사용자가 삭제 요청을 하면 DB에서 실제로 삭제되는 구조였지만, 증거를 남기기 위해(후속 조치가 필요할 수도 있다.) soft delete로 수정했다.
이때 Boolean 값으로 삭제 여부를 판단하는 것보다, 삭제일시까지 필요할 수 있는 상황에 대비하기 위해 시간 타입으로 deleted_at 컬럼을 추가했다.
AI 자소서 생성 페이지는 채용공고 URL, 생성할 자소서 항목(질문, 글자제한)으로 이루어져있다.
이때 질문칸에 악의적인 프롬프트를 넣게 되면 LLM은 악성 유저가 원하는 응답을 할 가능성이 있다. 그렇게 되면 큰 문제가 발생할 수 있다. 그렇기 때문에 악의적인 프롬프트에 포함되는 특정 문자들을 뽑아 필터링하고 우선 차단 조치를 한다.
왜 우선 차단조치를 하냐고 하면.. 간단하게 어떤 기업에서도 악의적인 내용이 포함된 자소서 질문 을 하지는 않을 것이기 때문이다.
만약 필터링의 경계가 모호해서 무고한 유저가 차단조치되는 경우도 대비하기 위해 모든 차단 사용자는 슬랙을 통해 문제가 되는 텍스트와 함께 나에게 알림이 오게하고 내가 확인하고 다른 조치를 취한다. 이게 더 안전할 것 같기 때문에 이런 결론을 내린다.
세상에는 정말 다양한 사람이 많다.
내 서비스의 첫 유저이자 악성 유저 덕분에 앞으로 보안에 신경을 많이 쓰게될 것 같다.
사실 compeletion model을 써서 피해는 없었다. 하지만 앞으로 구조가 변경될 수도 있기 때문에 이런 문제는 미리미리 방지하는게 좋다고 생각한다.