AI 코딩 에이전트에게 배포 오류를 고쳐 달라고 맡겼다. 코드를 읽고 테스트까지 돌리는 데는 문제가 없다. 그런데 실제 배포 명령에는 API 키가 필요하다. 키를 채팅에 붙여 넣자니 대화 기록에 남고, .env에 넣자니 에이전트가 파일을 읽을 수 있다.

사람이 배포 명령을 매번 다시 치기 시작하면 자동화할 이유가 흐려진다. 그렇다고 에이전트에 일을 맡기면서 비밀값까지 보여 주고 싶지는 않다. 우리는 그동안 작업과 열쇠를 한 묶음으로 넘겼다.

key-amnesia는 이 둘 사이를 끊으려는 오픈소스 도구다. 에이전트는 비밀값이 필요한 명령을 요청한다. 비밀값은 암호화된 저장소에서 자식 프로세스로 곧장 들어간다. 에이전트는 키를 보지 못한 채 그 키로 실행한 결과만 받는다. 이 프로젝트는 9월 말 Vahta로 이름을 바꾸고 새 저장소로 옮겼다. 다만 패키지와 명령 이름은 아직 key-amnesia와 ka를 그대로 쓴다.

.env가 막는 위협은 Git까지다

기존의 gitignore 보호 범위와 AI 에이전트까지 포함한 새로운 비밀 관리 범위를 비교한 그림
Git에 안 올라간 파일도 에이전트가 읽을 수 있다면 더는 비밀이 아니다.

.env를 .gitignore에 넣는 습관은 여전히 필요하다. 비밀값이 실수로 저장소에 올라가는 일을 막는다. 문제는 그다음이다. 이 방법이 가정한 상대는 Git이었다. 프로젝트 폴더와 셸까지 읽는 AI 에이전트가 들어오면 보호 경계부터 다시 그려야 한다.

설정 파일과 셸 기록, MCP 설정, 자격 증명 JSON은 모두 문제 해결의 단서다. 에이전트가 이런 파일을 살피는 건 자연스럽다. 다만 그 안에 평문 키가 있으면 모델에 들어가는 입력과 대화 기록, 도구 실행 로그에도 그 값이 복사될 수 있다.

key-amnesia는 이렇게 로컬에 노출된 키를 LEAK, 곧 Locally Exposed Agent Key라고 부른다. 에이전트를 공격자로 단정하려는 이야기는 아니다. 에이전트가 읽을 수 있는 영역과 비밀값이 놓인 영역은 처음부터 겹치지 않아야 한다.

저장소 밖으로 파일을 옮기는 것만으로는 부족하다. 에이전트가 같은 사용자 권한으로 그 파일을 다시 읽을 수 있어서다. 비밀값을 암호화하고, 값 자체를 꺼내는 대신 허용된 실행에만 잠깐 연결하는 장치가 필요하다.

값 대신 실행 권한을 건넨다

에이전트의 명령 요청이 사용자 승인과 암호화 저장소를 거쳐 자식 프로세스로 전달되고 검열된 결과만 돌아오는 흐름 그림
에이전트가 받는 것은 키가 아니라 그 키를 사용한 명령의 검열된 결과다.

ka run이 이 과정을 맡는다. 에이전트는 실행할 프로그램과 필요한 비밀의 이름만 지정한다. 그러면 key-amnesia가 사용자 승인을 확인한다. 사용자가 승인한 뒤에야 암호화된 볼트에서 값이 풀린다. 풀린 값은 새로 띄운 자식 프로세스의 환경변수에만 들어간다.

볼트는 Argon2id로 마스터 비밀번호에서 암호화 키를 만들고, SecretBox로 값을 암호화한다. 비밀의 이름은 평문으로 남고 값만 암호화된다. 비밀번호를 잊으면 복구할 방법이 없다. 일부러 뒷문을 두지 않았기 때문이다. 도입 전에 복구 대신 키 재발급 절차를 준비해 둬야 한다.

마스터 비밀번호는 에이전트가 다루는 터미널에 입력하지 않는다. 승인이 필요할 때 별도 콘솔 창이 열리고 사용자가 실제 키보드로 입력한다. 화면이 없는 헤드리스 환경에서는 승인을 받을 수 없어 실행을 거부한다. macOS의 격리 콘솔 실행은 아직 실험 단계다.

명령이 끝나도 출력을 바로 돌려주지 않는다. 전체 출력을 먼저 모은 뒤 비밀값과 정확히 같은 문자열을 가린다. 에이전트가 실수로 printenv 같은 명령을 실행해도 원문 키가 그대로 돌아오는 일을 한 번 더 막는다. 그 대신 오래 걸리는 명령은 끝날 때까지 출력이 보이지 않는다.

기본 per-call 모드는 비밀을 쓸 때마다 비밀번호를 묻는다. 다른 선택지인 cached 모드는 사용자가 ka unlock을 실행한 뒤 기본 30분 동안 다시 묻지 않는다. 대신 승인된 프로세스가 쓸 수 있는 권한도 그만큼 오래 열린다. 가끔 배포하는 노트북과 자동 명령을 연달아 돌리는 환경에 같은 설정이 맞을 리 없다.

설치보다 중요한 것은 경계 확인이다

pip install key-amnesia로 설치한 다음 ka setup을 실행한다. 이 명령은 Claude Code, Cursor, Codex, OpenCode에 필요한 스킬과 안전 훅을 넣는다. 훅은 에이전트가 ka set이나 ka reveal처럼 비밀을 바꾸거나 꺼내는 명령을 실행하지 못하게 막는다. 볼트는 ka init --project로 만든다. 평문 값은 사람이 직접 ka import .env를 실행해 옮겨야 한다.

이 훅은 편의를 위한 정책선이지 완전한 보안 경계가 아니다. 공식 문서도 에이전트가 실행 환경의 설정을 쓸 수 있다면 훅을 제거하거나 끌 수 있다고 밝힌다. 별칭이나 이름을 바꾼 실행 파일로 ka를 부르는 명령도 알아보지 못한다. 그래서 프로젝트 파일 쓰기 권한, 명령 승인 규칙, 화면 제어 권한을 함께 점검해야 한다. 도구 하나를 설치했다고 에이전트 전체가 안전해지지는 않는다.

ka scan은 평문 비밀의 흔적을 찾는다. 평소에는 프로젝트 안만 살피지만 --deep을 붙이면 알려진 홈 디렉터리 후보와 셸·MCP 설정, 일부 에이전트 세션 기록까지 확인한다. 결과에는 이름과 경로, 개수만 나오고 비밀값은 보여 주지 않는다. 다만 이름 모양으로 찾기 때문에 오탐이 섞일 수 있고, 홈 디렉터리 전체를 훑는 검사도 아니다. 결과를 자동 삭제 목록으로 쓰지 말고 사람이 경로를 하나씩 확인해야 한다.

가려진 키도 명령을 통해 샐 수 있다

key-amnesia가 막는 직접 노출과 막지 못하는 변형 출력 및 같은 사용자 권한 위험을 층별로 나눈 그림
직접 열람을 막아도 허용한 명령의 행동과 운영체제 권한까지 통제되지는 않는다.

가장 뚜렷한 한계는 출력 검열이다. 검열기는 비밀값과 정확히 같은 문자열만 찾는다. 실행한 프로그램이 키를 Base64로 바꾸거나 여러 조각으로 나눠 내보내면 잡지 못한다. key-amnesia는 명령이 비밀을 그대로 반환하는 일은 줄여도, 그 값을 받은 프로그램의 행동까지 보증하지 않는다.

같은 운영체제 사용자로 실행되는 프로세스는 같은 권한을 쓴다. 승인 범위를 넓히는 옵션이 위험한 이유다. --pre-admit은 잠깐 열린 시간 동안 가장 먼저 연결한 프로세스를 묻지 않고 들여보낸다. 그 프로세스가 내 에이전트라는 보장은 없다. --admit-tree는 고른 상위 프로세스와 그 아래 자식 프로세스 전체를 허용한다. 둘 다 반복 승인을 줄이지만 신뢰 범위도 그만큼 넓힌다.

별도 콘솔도 에이전트가 화면을 보거나 마우스와 키보드를 조작하지 못한다는 전제가 필요하다. 화면 제어 권한까지 준 에이전트라면 승인 창의 격리가 약해진다. 마스터 비밀번호 입력값은 숨겨져도, 에이전트가 승인 창에 대신 응답할 가능성은 남는다.

비밀값을 숨기는 일과 그 값으로 할 수 있는 일을 제한하는 일은 서로 다르다. API 제공자의 최소 권한 키, 짧은 만료 시간, 사용처 제한, 감사 로그는 여전히 필요하다. 읽기 전용 키로 충분한 작업에 관리자 키를 연결하면 값이 보이지 않아도 피해 범위는 그대로 크다. 키가 의심스럽게 사용됐다면 볼트 암호만 바꿀 게 아니라 제공자 쪽에서 기존 키를 폐기하고 새로 발급해야 한다.

비밀을 주지 말고 필요한 능력만 연다

key-amnesia의 문구는 짧다.

The agent gets amnesia. That’s the whole point.

이 도구가 바꾸려는 건 파일 위치가 아니라 접근 방식이다. 에이전트가 키를 읽은 뒤 명령을 실행하던 순서를 끊는다. 사용자가 실행을 승인하면 별도 도구가 키를 주입하고, 에이전트에는 필요한 결과만 돌려준다.

도입 첫 단계는 ka scan으로 평문 키가 남은 위치를 찾는 일이다. 그 뒤 에이전트가 꼭 실행해야 하는 명령과 필요한 비밀을 좁힌다. 기본 per-call 모드로 시작하고, 승인 횟수가 실제로 문제가 될 때만 캐시와 승인 범위를 조정하는 편이 안전하다.

key-amnesia는 .gitignore나 최소 권한 키를 대신하지 않는다. 그 사이에 한 겹을 더 놓을 뿐이다. AI가 비밀을 알아야 일을 할 수 있다는 전제를 버리고, 비밀로 할 수 있는 한 가지 행동만 잠시 허용한다.


원문: Vahta(옛 key-amnesia) 공식 저장소 / GeekNews 소개