‘읽기 전용’ Postgres MCP도 데이터를 바꿨다…1.1.7이 끝이 아닌 이유

AWS의 2026년 9월 4일 보안 공지 는 AWS Labs Postgres MCP Server의 읽기 전용 SQL 검증을 우회해 데이터를 변경할 수 있는 CVE-2026-85787을 공개했다. 영향 대상은 PyPI의 awslabs.postgres-mcp-server 1.1.7 미만이며, 결함은 1.1.7에서 수정됐다.
이 취약점은 인증되지 않은 공격자가 PostgreSQL에 직접 로그인하는 문제는 아니다. 공격자가 조작한 SQL을 콘텐츠에 넣고, 그 콘텐츠가 인증된 사용자의 MCP 상호작용을 통해 서버에 제출되며, MCP 연결 계정에 해당 변경을 실행할 권한까지 있어야 피해로 이어질 수 있다. 따라서 9월 4일 공개에 대한 대응은 패키지 업그레이드와 데이터베이스 권한 축소를 함께 포함해야 한다.
영향 대상은 PostgreSQL이 아니라 1.1.7 미만 MCP 패키지다

점검 범위는 PostgreSQL이나 Amazon Aurora 엔진 전체가 아니라 AWS Labs가 배포한 awslabs.postgres-mcp-server다. 다른 PostgreSQL용 MCP 구현, MySQL·DynamoDB용 서버 또는 일반 SQL 도구를 같은 CVE의 영향 대상으로 확대할 근거는 없다.
버전 확인은 개발자 PC의 임의 Python 환경이 아니라 MCP 프로세스를 실제로 시작하는 환경에서 해야 한다. uvx 인수나 MCP 클라이언트 설정에 고정된 버전, 컨테이너 이미지, 의존성 잠금 파일을 확인하고, 재배포 뒤 실행 중인 프로세스가 새 패키지를 불러왔는지도 구분해야 한다. 호스트의 패키지만 바꾸고 이전 컨테이너를 계속 실행하면 취약 코드가 남을 수 있다.
1.1.7 이상이면 공개된 결함의 영향 범위에서는 벗어나지만, 자체 포크와 파생 구현은 버전 문자열만으로 판단할 수 없다. 공식 수정 사항을 코드에 반영했는지 확인해야 하며, AWS도 1.1.7에 계속 고정하기보다 최신 버전으로 업그레이드하고 파생 코드에 새 수정 사항을 적용하라고 권고했다.
블록리스트를 통과한 SQL이 인증된 세션을 탔다

읽기 전용 모드는 데이터베이스 권한을 제거하는 방식이 아니라 변경 가능성이 있는 키워드와 함수를 애플리케이션에서 차단하는 방식이었다. 목록에 없는 PostgreSQL 표현이나 탐지를 피하는 표기가 들어오면, 읽기 전용으로 보이는 MCP 경로를 통해 데이터 또는 세션 상태를 바꾸는 SQL이 데이터베이스까지 전달될 수 있었다.
독립 기술 분석 은 1.1.6에서 1.1.7로 바뀐 코드를 근거로 기존 검사가 set_config 함수 형태와 인용 식별자 등을 놓쳤다고 설명하고, 1.1.7이 2026년 6월 25일 PyPI에 먼저 배포된 뒤 CVE가 9월 4일 공개됐다고 정리했다. 즉 9월 4일은 수정판의 최초 배포일이 아니라 공개 공지일이며, 해당 분석은 실제 공격이 관측됐다는 주장도 하지 않는다.
공격 성립 조건도 구분해야 한다. 외부인이 데이터베이스 인증을 우회하는 것이 아니라, 신뢰할 수 없는 콘텐츠에 포함된 SQL이 인증된 사용자의 MCP 작업으로 유입돼야 한다. 이후 애플리케이션 검사를 통과하고, 연결된 Postgres 역할이 변경 대상에 대한 권한을 보유해야 실제 데이터 변경으로 이어진다.
이 조건은 제목의 ‘읽기 전용’이 데이터베이스가 보장한 불변 상태가 아니었음을 뜻한다. 애플리케이션이 쓰기 SQL을 걸러낼 것이라는 기대와 연결 계정이 실제로 가진 권한 사이에 틈이 있었고, 취약점은 그 틈을 이용할 수 있게 했다.
1.1.7 이후에도 DB 역할이 최종 실행 경계다

1.1.7은 알려진 검증 누락을 수정하지만 블록리스트를 완전한 권한 경계로 만들지는 않는다. SQL 문법, 확장 기능과 표현 방식은 계속 달라질 수 있으므로 애플리케이션 검사가 모든 위험한 구문을 영구적으로 열거한다고 가정할 수 없기 때문이다.
AWS Labs 프로젝트의 보안 지침 은 쓰기 차단을 보안 경계가 아닌 최선 노력 방식의 심층 방어로 규정하고, 읽기 전용 용도에는 전용 Postgres 역할을 사용해 필요한 데이터베이스의 CONNECT, 필요한 스키마의 USAGE, 필요한 테이블과 시퀀스의 SELECT만 부여하도록 안내한다. 역할 수준에서 읽기 전용 트랜잭션을 강제하는 설정도 함께 제시한다.
MCP 서버를 superuser, rds_superuser, 클러스터 마스터 사용자 또는 BYPASSRLS 권한이 있는 역할로 연결하면 안 된다. 이런 역할은 읽기 전용이라는 업무 목적보다 훨씬 넓은 실행 권한을 가지며, 애플리케이션 검사가 놓친 SQL의 피해 범위를 크게 키울 수 있다.
default_transaction_read_only를 on으로 설정하는 것도 추가 방어선이지 최소 권한 역할의 대체재는 아니다. 연결 역할에서 불필요한 INSERT·UPDATE·DELETE와 객체·역할 관리 권한을 제거한 뒤 읽기 전용 트랜잭션을 결합해야 한다. 패치가 입력 검증을 보강한다면, 역할 권한은 검증을 통과한 SQL이 실제로 할 수 있는 일을 제한한다.
운영 대응은 네 단계로 나뉜다
우선순위는 실행 버전 확인, 배포물 교체, 연결 역할 감사, 노출 기간 조사다. 각각을 별도 항목으로 확인해야 패키지는 갱신됐지만 실행 인스턴스나 데이터베이스 계정은 그대로 남는 공백을 찾을 수 있다.
- 실행 중인 버전을 확인한다. MCP 프로세스가 사용하는 환경에서 설치 버전을 조회한다. 1.1.7 미만은 영향 대상으로 분류하고, uvx 버전 고정과 컨테이너 태그, 잠금 파일, 복제된 배포 설정도 함께 대조한다.
- 패키지와 포크를 갱신한다. 공식 패키지는 현재 제공되는 유지보수 버전으로 올리고 프로세스나 컨테이너를 다시 시작한다. 자체 포크와 파생 코드는 1.1.7의 검증 수정 사항을 실제로 포함했는지 확인한 뒤 다시 배포한다.
- 연결 역할의 권한을 줄인다. 읽기 전용 작업에는 별도 로그인 역할을 사용하고 필요한 범위의 CONNECT·USAGE·SELECT만 남긴다. 기존 객체뿐 아니라 앞으로 생성될 테이블과 시퀀스의 기본 권한, 다른 역할의 상속 여부, superuser·rds_superuser·BYPASSRLS 보유 여부도 감사한다.
- 취약 버전의 운영 기간을 조사한다. MCP 요청 기록과 데이터베이스 감사 로그, 예상하지 못한 데이터 변경 및 역할·세션 설정 변경을 시간순으로 대조한다. 이상 징후가 발견되면 단순 패치 작업과 분리해 사고 대응 절차로 다룬다.
읽기와 쓰기를 모두 허용해야 하는 업무도 최소 권한 원칙의 예외는 아니다. 해당 역할에는 필요한 스키마와 테이블, 작업에 한정해 INSERT·UPDATE·DELETE를 각각 부여해야 한다. 범위를 줄이면 의도하지 않은 SQL이 실행되더라도 영향을 허용된 데이터와 작업 안에 묶을 수 있다.
현재 상태는 수정판 제공, 실제 악용 여부는 미확인이다
공개된 사실은 awslabs.postgres-mcp-server 1.1.7 미만에 검증 누락이 있었고 1.1.7에서 수정됐다는 점이다. 공개 자료에는 실제 악용 사례, 피해 조직 수 또는 피해 규모가 제시되지 않았으므로 취약 가능성을 이미 발생한 침해 사고로 표현해서는 안 된다.
대응 완료 기준도 1.1.7 설치 하나로 끝나지 않는다. 실행 중인 패키지와 포크가 수정됐고, MCP가 업무 범위에 맞는 저권한 역할로 연결되며, 읽기 전용 사용에는 역할 수준의 트랜잭션 제한이 적용돼야 한다. 여기에 취약 버전이 사용된 기간의 변경 기록까지 검토해야 제목이 지적한 ‘1.1.7 이후’의 잔여 위험을 실질적으로 줄일 수 있다.
뉴스레터 구독
최신 Web3, AI, 암호화폐 뉴스를 이메일로 받아보세요.