1P by GN⁺ | ★ favorite | 댓글 1개
  • 전 세계 브라우저와 스트리밍 인프라에서 미디어를 처리하는 FFmpeg는 복잡하고 신뢰할 수 없는 입력을 파싱해 보안상 중요한 공격 표면이 됨
  • depthfirst의 자율 보안 에이전트는 약 150만 줄의 최적화된 C 코드에서 21개 제로데이를 찾았고, 비용은 약 $1k로 Anthropic의 Mythos 사용 비용 $10k의 10% 수준이었음
  • 발견 항목은 TS demuxer, VP9 decoder, RTP/RTSP/RTMP 처리 경로 등 여러 구성요소에 걸쳐 있으며, 일부 취약점은 15~20년 동안 잠재 상태였음
  • AV1 RTP depacketizer 취약점은 183바이트 RTP 패킷만으로 함수 포인터를 덮어쓰는 PoC로 이어졌고, ffmpeg -i rtsp://attacker/stream 실행만으로 도달 가능함
  • 실질적 보안 검증은 이론적 경고가 아니라 재현 가능한 입력과 실행 확인까지 필요하며, 에이전트형 분석은 대형 C 코드베이스의 숨은 취약점 발굴에 직접 활용될 수 있음

개요

  • FFmpeg는 브라우저와 대형 스트리밍 플랫폼 인프라 등에서 미디어를 처리하는 널리 배포된 소프트웨어임
  • 복잡하고 신뢰할 수 없는 미디어를 지속적으로 파싱하는 라이브러리이기 때문에 보안상 중요하며, 제로클릭 공격의 주요 표적이 됨
  • FFmpeg 저장소는 약 150만 줄의 고도로 최적화된 C 코드로 구성되고, 수백 개의 복잡한 미디어 형식을 파싱함
  • FFmpeg는 20년 넘게 퍼징과 수동 감사를 받아왔으며, 최근 Google Big Sleep 팀은 FFmpeg에서 13개 취약점을 공개함
  • Anthropic은 Mythos 모델로 FFmpeg를 스캔해 보안 이슈 일부를 발견함
  • 이러한 선행 작업 이후 FFmpeg에서 새 취약점을 찾기는 더 어려워졌고, 대형 코드베이스를 깊게 스캔하는 에이전트형 시스템의 역량을 확인하는 대상이 됨

Depthfirst의 보안 에이전트

  • 코딩 에이전트와 보안 에이전트는 같은 기반 모델을 사용할 수 있지만, 목표가 크게 다름
  • 코딩 에이전트는 보통 사람의 과제를 받아 애플리케이션 코드를 작성하는 데 초점을 둠
  • 보안 에이전트는 구체적 지시 없이 기존 시스템에서 실제 악용 가능한 보안 이슈를 찾는 좁고 목표 지향적인 역할을 맡음
  • 보안 에이전트는 코드베이스의 아키텍처, 노출된 파서와 프로토콜 핸들러, 공격자 제어 입력의 진입 지점을 먼저 파악해야 함
  • 이후 저장소를 평면적인 파일 묶음으로 다루지 않고, 공격 표면 코드에서 관련 구성요소를 따라 데이터 흐름을 추적함
  • 실용적인 보안 에이전트에는 누락된 조건을 꾸며내거나, 이론적 버그를 과장하거나, 오탐을 대량으로 내지 못하게 하는 가드레일이 필요함
  • 공격자가 실제로 올바른 입력을 제어하는지, 취약 경로에 도달 가능한지, 의심되는 결함이 재현 가능한지 확인해야 함
  • 필요한 경우 대상 구성요소와 상호작용하는 하네스(harness) 를 식별하거나 생성해 가설을 구체적으로 시험해야 함
  • depthfirst의 특화 보안 에이전트는 코드를 깊게 분석하고, 여러 가설을 병렬로 분기해 시험함
  • 결과물은 이론적 보고서나 모호한 경고가 아니라, 재현 가능한 구체 입력으로 실행 확인된 보안 이슈가 됨

발견 결과

  • 에이전트는 총 21개 제로데이를 발견했고, 범위는 TS demuxer부터 VP9 decoder까지 걸쳐 있음
  • 전체 비용은 약 $1k였고, 이는 Anthropic이 Mythos 사용에 쓴 비용의 10% 수준임
  • 비용 비교: {b:1,10}
  • CVE가 할당된 취약점

    • CVE-2026-39210은 TS demuxer에서 두 바이트를 읽기 전 길이 경계 검사가 빠진 힙 버퍼 오버플로이며, 2010년에 들어감
    • CVE-2026-39211은 swscale 리팩터링 중 상한 없는 크기 계수 공식으로 사용자 제어 매개변수가 임의로 큰 스케일링을 유발할 수 있었던 정수 오버플로이며, 2010년에 들어감
    • CVE-2026-39212ffmpeg_opt.c에서 프리셋 파일이 깊이 제한 없이 옵션 파싱을 재귀적으로 트리거할 수 있었던 스택 오버플로이며, 2025년 7월 회귀로 들어감
    • CVE-2026-39213은 yuv4mpegenc rawvideo 입력 경로에서 패킷 크기에 대한 차원 검증이 빠진 힙 버퍼 오버플로이며, 2023년에 들어감
    • CVE-2026-39214는 원래 SDT 구현에서 남은 공간을 추적하지 않고 서비스 엔트리를 쓰는 스택 버퍼 오버플로이며, 2003년에 들어가 23년 동안 잠재 상태였음
    • CVE-2026-39215update_mb_info() 안의 로직 오류로 이후 호출이 할당 버퍼 뒤 12바이트를 쓰게 되는 힙 버퍼 오버플로이며, 2012년에 들어감
    • CVE-2026-39216img2enc.c에서 안전한 크로마 크기를 차원 기반 무제한 크기로 대체해 생긴 힙 버퍼 오버플로이며, 2012년에 들어감
    • CVE-2026-39217은 VP9 decoder에서 리팩터링된 크기 업데이트 함수 때문에 타일 스레드 버퍼가 필요한 재할당을 놓치는 힙 버퍼 오버플로이며, 2025년 3월 회귀로 들어감
    • CVE-2026-39218은 DASH demuxer에서 음수 duration 값을 거부하지 않아 fragment 배열 인덱스가 음수가 되는 힙 버퍼 오버플로이며, 2017년에 들어감
  • 내부 추적 ID로 참조된 취약점

    • DFVULN-127은 RTP AV1 depacketizer의 av1_handle_packet()이 Temporal Delimiter OBU를 건너뛰며 obu_size만큼 출력 위치를 전진시키지만 같은 크기의 공간을 할당하지 않아 다음 OBU가 버퍼 경계 밖에 쓰이는 힙 버퍼 오버플로임
    • DFVULN-126은 swscale graph 코드의 run_legacy_unscaled()가 interlaced YUV420P→NV12 변환을 잘못 처리해 대상 Y-plane을 576바이트 넘겨 쓰는 힙 버퍼 오버플로임
    • DFVULN-125는 RTP JPEG depacketizer의 jpeg_create_header()가 1024바이트 스택 버퍼에 quantization-table 섹션을 만들 때, qtable_len >= 1024 패킷 뒤의 AV_WB16이 끝을 2바이트 넘겨 쓰는 스택 버퍼 오버플로임
    • DFVULN-124는 AVIF overlay 경로의 istg_parse_tile_grid()가 타일 엔트리 0개인 dimg 참조를 거부하지 않아 부호 없는 래핑 뒤 1바이트 힙 할당에서 범위 밖 읽기를 일으키는 힙 버퍼 오버플로임
    • DFVULN-123은 RTP LATM depacketizer의 latm_parse_packet()이 signed 32-bit 덧셈 오버플로로 경계 검사를 우회해 memcpy가 힙 버퍼 끝에서 약 1GB 뒤를 읽게 하는 정수 오버플로임
    • DFVULN-122는 RTP MPEG-4 depacketizer의 aac_parse_packet()이 AU-headers-length 0을 받아 1바이트 할당을 만든 뒤 AU header 존재 확인 없이 4바이트 필드로 읽는 힙 버퍼 오버플로임
    • DFVULN-121은 CAF demuxer의 read_seek()av_index_search_timestamp()의 반환값 -1을 검사하지 않고 배열 인덱스로 사용해 index_entries[-1]에 접근하는 힙 버퍼 언더플로임
    • DFVULN-120은 AVI demuxer의 ff_read_riff_info()size >= 4 확인 없이 size - 4를 받아 LIST chunk 크기 0에서 약 4GB로 언더플로하고 약 2GB 할당을 유발하는 정수 언더플로임
    • DFVULN-119는 option parser의 opt_map()에 있는 불필요한 증가가 link-label을 file index로 잘못 파싱하고 stream index -1을 저장해 이후 루프가 AVStream** 배열 앞을 읽게 하는 힙 버퍼 오버플로임
    • DFVULN-118은 RTSP server 경로의 rtsp_read_announce()가 음수 Content-Length를 유효하게 처리해 원격 ANNOUNCEContent-Length: -1sdp[-1]에 범위 밖 쓰기를 일으키는 힙 버퍼 오버플로임
    • DFVULN-117은 RTMP client의 rtmp_calc_swfhash()in_size < 8 대신 in_size < 3만 검사해 최소 3바이트 버퍼에서 8바이트를 읽는 힙 버퍼 오버플로임
    • DFVULN-116은 RTSP SDP parsing의 sdp_parse_line()이 빈 문자열에서 strlen(control_url) - 1을 계산해 size_tSIZE_MAX로 래핑되고 1바이트 pre-buffer read가 발생하는 힙 버퍼 오버플로임

건너뛴 프레임 마커에서 PC 제어까지

  • 21개 발견 항목 중 AV1 RTP depacketizer의 힙 버퍼 오버플로가 네트워크에서 특수 플래그 없이 도달 가능함
  • 피해자는 ffmpeg -i rtsp://attacker/stream만 실행하면 되고, 단일 183바이트 패킷으로 실행 흐름을 바꿀 수 있음
  • FFmpeg가 RTSP 스트림을 가져올 때 서버는 인코딩된 비디오를 RTP 패킷 시퀀스로 전달함
  • AV1은 비트스트림을 OBU(Open Bitstream Units)로 구성하고, RTP payload format은 이 OBU를 패킷 여러 개로 나눔
  • FFmpeg의 depacketizer는 나뉜 OBU를 다시 깨끗한 elementary stream으로 이어 붙이는 역할을 함
  • Temporal Delimiter(TD)는 한 temporal unit, 즉 프레임과 다음 프레임을 구분하는 작은 마커임
  • 사양은 payload 안의 TD를 depacketizer가 “ignore and remove”해야 한다고 정함
  • 이 “ignore and remove” 처리가 문제 지점이 됐고, 에이전트가 해당 지점을 포착함

근본 원인

  • depacketizer는 출력 패킷을 점진적으로 만들며, pktpos 커서가 pkt->data 안에서 다음 바이트를 쓸 위치를 추적함
  • pktpos는 패킷의 현재 끝에서 시작함
// libavformat/rtpdec_av1.c:199
pktpos = pkt->size;
  • 코드가 패킷 안의 OBU element를 순회할 때 실제로 내보내는 모든 바이트 앞에는 av_grow_packet 호출이 붙고, 이 호출이 pkt->data의 힙 할당을 키움
  • 전체 루틴이 의존하는 불변식은 pktpospkt->data의 할당 크기보다 앞서 나가면 안 된다는 점임
  • Temporal Delimiter 처리 코드는 이 불변식을 깨뜨림
// libavformat/rtpdec_av1.c:250
if ((obu_type == AV1_OBU_TEMPORAL_DELIMITER) ||
    (obu_type == AV1_OBU_TILE_LIST)) {
    pktpos += obu_size;
    rem_pkt_size -= obu_size;
    obu_cnt++;
    continue;
}
  • TD를 건너뛸 때 pktpos는 공격자가 선언한 obu_size만큼 앞으로 이동하지만, 그 이동을 뒷받침할 메모리는 할당되지 않음
  • 입력 포인터 buf_ptr도 TD 바이트 뒤로 이동하지 않음
  • TD의 obu_size = 148이면 pktpos는 148이 되지만, pkt->data는 여전히 할당되지 않았거나 148바이트보다 훨씬 작을 수 있음
  • 다음 반복은 TD 자체의 바이트를 다시 파싱하고, TD header byte를 새로운 OBU 길이로 다시 읽으며, payload를 조작된 OBU의 내용으로 사용함
  • 다음 정상 OBU에서 패킷은 해당 OBU 크기만큼만 커짐
// libavformat/rtpdec_av1.c:296
if ((result = av_grow_packet(pkt, output_size)) < 0)
    return result;

// libavformat/rtpdec_av1.c:304 / 336
pkt->data[pktpos++] = *buf_ptr++ | AV1F_OBU_HAS_SIZE_FIELD;
memcpy(pkt->data + pktpos, buf_ptr, obu_payload_size);
  • 조작된 OBU가 17바이트이면 av_grow_packet은 17바이트와 FFmpeg의 64바이트 입력 패딩을 더해 81바이트 버퍼를 할당함
  • 쓰기는 pkt->data[148]에서 시작해 할당 끝보다 67바이트 뒤에서 발생함
  • 이 결함은 공격자가 오프셋과 내용을 모두 제어하는 힙 버퍼 오버플로가 됨

악용 방식

  • 제어 가능한 오버플로가 유용하려면 버퍼 바로 뒤에 덮어쓸 만한 대상이 있어야 하며, FFmpeg의 allocator가 해당 대상을 제공함
  • av_grow_packet이 패킷 데이터 버퍼를 할당할 때 av_buffer_alloc을 거치고, 이 함수는 데이터 버퍼, AVBuffer bookkeeping struct, AVBufferRef를 순서대로 힙에 할당함
  • FFmpeg는 64바이트 정렬의 posix_memalign을 통해 할당하므로, 81바이트 데이터 버퍼는 128바이트 chunk를 차지하고 AVBuffer struct가 바로 뒤에 놓임
  • AVBuffer struct에는 해제 콜백으로 쓰이는 함수 포인터가 있음
// libavutil/buffer_internal.h
struct AVBuffer {
    uint8_t *data;        // +0
    size_t   size;        // +8
    atomic_uint refcount; // +16
    void (*free)(void *opaque, uint8_t *data); // +24
    void    *opaque;      // +32
    ...
};
  • 데이터 버퍼 시작점 기준 AVBuffer.free 포인터는 오프셋 152에 위치함
  • TD의 obu_size = 148이면 쓰기는 pkt->data[148]에서 시작함
  • TD header byte 0x10은 길이 16으로 다시 해석되고, 조작된 16바이트 OBU의 header와 payload가 오프셋 148부터 쓰임
  • AVBuffer.refcount는 오프셋 144–147에 있어 쓰기 시작점 148보다 앞에 남고, 원래 값 1을 유지함
  • 익스플로잇은 TD payload 안에 세 번째 조작 OBU를 넣어 한 번 더 av_grow_packet을 발생시킴
  • 버퍼가 av_buffer_realloc이 아니라 av_buffer_alloc으로 만들어졌기 때문에 reallocatable로 표시되지 않고, FFmpeg는 새 버퍼를 할당한 뒤 기존 버퍼를 해제하는 경로를 택함
// libavutil/buffer.c:209
if (!(buf->buffer->flags_internal & BUFFER_FLAG_REALLOCATABLE) || ...) {
    ret = av_buffer_realloc(&new, size);
    memcpy(new->data, buf->data, ...);
    buffer_replace(pbuf, &new);
    return 0;
}
  • buffer_replace는 기존 버퍼의 refcount를 1에서 0으로 줄이고, 해제 콜백을 호출함
// libavutil/buffer.c:129
if (atomic_fetch_sub_explicit(&b->refcount, 1, memory_order_acq_rel) == 1) {
    b->free(b->opaque, b->data);
}
  • 이 시점에 덮어쓴 free 포인터가 호출되고, instruction pointer 제어가 가능해짐
  • release build에서 단일 183바이트 RTP 패킷은 rip0xdeadbeef로 만들었음
#0  0x00000000deadbeef in ?? ()
rip            0xdeadbeef          0xdeadbeef
#1  buffer_replace (buffer.c:133)
#2  av_buffer_realloc (buffer.c:220)
#3  av_grow_packet (packet.c:151)
#4  av1_handle_packet (rtpdec_av1.c:296)
#5  rtp_parse_packet_internal (rtpdec.c:743)

영향 범위와 PoC

  • 공격자가 영향을 줄 수 있는 RTSP URL을 FFmpeg가 열도록 하는 배포 환경은 이 취약점에 노출됨
  • 사용자 제공 stream URL을 가져오는 미디어 ingest pipeline이 영향 범위에 해당함
  • RTSP feed를 가져오는 surveillance 및 CCTV 시스템이 영향 범위에 해당함
  • 원격 AV1-over-RTP 소스를 처리하는 transcoding service가 영향 범위에 해당함
  • 인증이나 스트림 열기 이상의 사용자 상호작용이 필요하지 않으며, 특이한 command-line flag도 필요하지 않음
  • 취약점은 이러한 클라이언트가 설계상 수행하는 일반 RTSP PLAY 단계에서 트리거됨
  • PoC 코드는 ffmpeg-dfvuln127에 있음

댓글과 토론

Hacker News 의견들
  • FFmpeg는 보안 측면에서 기록이 유난히 나쁨
    오래전부터 퍼저(fuzzer)를 돌릴 때마다 거의 끝없이 메모리 손상 버그가 나왔고, 10년 전 Google 직원의 작업도 있었음: https://security.googleblog.com/2014/01/ffmpeg-and-thousand-...
    그래서 이게 LLM의 능력을 보여주는 데모이긴 해도 놀랄 일은 아님. 신뢰할 수 없거나 사용자가 제공한 콘텐츠를 다룬다면 FFmpeg를 샌드박스 밖에서 실행해서는 안 되고, 그렇게 하는 건 불합리한 위험을 감수하는 것임

    • FFmpeg 쪽은 프로젝트 취약점을 공개하려는 사람은 매우 많은데, 이를 고칠 패치 작업에 나서는 사람은 비교가 안 될 정도로 적다는 데 꾸준히 불만을 표해 왔음
    • 최근 Lex Fridman 팟캐스트에 FFmpeg 개발자들이 나왔고 보안 이야기도 나왔음
      90년대 비디오 게임 하나에서나 쓰이는 극히 틈새적인 코덱에 취약점이 있었는데, 신고자가 큰일처럼 굴었지만 실제로는 거의 쓰이지 않는 코덱이라 별일 아니라는 식으로 말했음
      하지만 공격자가 비디오 파일을 제공할 수 있다면 어떤 비디오 코덱이든 마음대로 고를 수 있다는 사실을 모르는 건가 싶었음. 개발자가 그 코덱이 전혀 쓰이지 않는다고 생각해도, 여전히 사용 가능하다면 공격자는 쓸 수 있음
      혹시 내가 놓친 게 있는지, 이 코덱의 취약점이 정말 별일 아닌 타당한 이유가 있는지 궁금함
    • 물론임. 모두가 FFmpeg 대신 쓸 명백한 대안을 알고 있으니까
    • FFmpeg 자체를 샌드박싱하는 건 어렵지 않지만, FFmpeg를 쓰는 MPV/VLC 같은 경우엔 더 까다로움
      최근까지는 virtio GPU 네이티브 컨텍스트가 없어서 하드웨어 가속을 전부 잃지 않고 비디오 플레이어를 샌드박싱하는 것조차 불가능했음. 적어도 외부에서 강제로 하기는 그랬고, 내부적으로는 Chromium처럼 FFmpeg를 격리하고 seccomp로 강하게 묶을 수는 있었음
    • FFmpeg는 극도로 복잡한 영역에서 동작하고, 성능에 극단적으로 집중해야 하는 매우 복잡한 소프트웨어임
      FFmpeg만의 문제가 아님. Apple도 이미지·비디오 디코더 취약점이 셀 수 없이 많았음. 이 분야 자체가 매우 어렵고, FFmpeg는 그 누구보다 많은 일을 하고 있음
  • 업계가 잘못된 대상을 최적화하고 있다고 봄. Mythos preview 1이나 GPT-5.5 같은 것으로 AI가 쓴 버그 리포트를 수천 개 생성하는 건 쉬움. 어려운 건 버그를 실제로 고치는 것
    몇 달 전부터 치명적인 보안 이슈를 찾아 리포트만 올리는 대신 PR을 여는 시스템을 만들고 있음. 지금까지 수락률은 대략 94% 정도임. 실패 대부분은 취약점 오판이 아니라, 문서화되지 않은 프로젝트별 킬 스위치나 내부 메커니즘 때문이었음
    개발자들은 대체로 이 방식을 더 좋아하는 듯함. 버그 리포트는 일을 만들고, 좋은 PR은 일을 줄임. 당연해 보이지만 많은 보안 제품은 여전히 리포트에서 멈추고 끝낸다고 함

    • 업계는 실제로 속도, 출시 시간, 기능을 최적화하고, 단기 매출을 만들지 않는 것들인 보안 고려, 접근성, 벤더 종속, 상호운용성 등에는 타조처럼 머리를 묻는 모델을 적용함
      업계가 생긴 이래 계속 그래 왔고, 이제야 그 피해와 전체의 취약함을 평가할 적절한 도구가 생기기 시작함
    • 여기서 놓친 게 있는 듯함. Apple 소프트웨어는 오픈소스 코드가 없는데, 어떻게 수정을 제안한다는 건지 모르겠음
  • 이 버그는 도달 범위 때문에 심각함. FFmpeg가 공격자의 영향을 받는 RTSP URL을 바라보는 모든 배포가 노출됨
    사용자가 제공한 스트림 URL을 가져오는 미디어 수집 파이프라인, RTSP 피드를 가져오는 감시·CCTV 시스템, 원격 AV1-over-RTP 소스를 처리하는 트랜스코딩 서비스 등이 해당됨. 실제로 꽤 심각하고, 공개된 게 오히려 놀라울 정도임. 지금 당장 악용 가능해 보이는 서비스가 여럿 떠오름

    • 심각한 취약점을 알고 있다면 공개하는 게 중요하다고 볼 수도 있음. 취약한 방식으로 소프트웨어를 쓰는 사람들이 위험을 줄이기 위한 조치를 할 수 있기 때문임
    • 실제 악용까지 가려면 ASLR 누수 같은 게 추가로 필요함
    • FFmpeg는 버그나 보안 리포트에 신경 쓰지 않는다고 여러 번 밝혀 왔음
  • 이게 보안 회사 광고처럼 보이는 만큼 큰일이 아니더라도, 출시하는 모든 애플리케이션 어딘가에는 보안 구멍이 있고 이제는 스크립트 키디도 출시 5분 뒤 2달러 크레딧으로 그걸 찾을 수 있다는 사실을 상기시켜 줌
    출시 전에 레드팀으로 코드를 검증하지 않으면, 해커들이 출시 후에 대신 하게 됨

  • 제로데이라는 용어가 부풀려 쓰이고 있음. 설명된 취약점 중 실제 제로데이는 없지만, 그렇게 부르면 그럴듯하고 클릭은 잘 나옴

  • “이 시점에서 손상된 free 포인터가 호출되고, 명령 포인터 제어권은 우리에게 있다”는 건 매우 심각함
    다만 실제로는 이 버그만으로 임의 원격 코드 실행까지 되는 것 같지는 않음. 특히 ASLR이 있으면 더 그렇고, 쓰기 가능하면서 실행 가능한 메모리 페이지가 어딘가에 있어야 함

    • 글에서는 이 부분을 대충 넘어가지만, 구조체의 다음 변수가 마침 함수의 첫 번째 인자라서 system() 같은 것으로 임의 코드 실행이 가능해 보임
      그래도 ASLR을 깨려면 다른 익스플로잇이 필요함
  • 그건 “제로데이”의 의미가 아님

    • Stuxnet 보도 이후 대중화되면서 의미를 잃은 듯함
    • 그렇게 말하려면 뜻도 같이 설명해 줬으면 함. 나도 정의를 잘못 알고 있을 수 있음
  • 보안 연구 분야의 인센티브 구조는 깊이 망가져 있음
    이들은 FOSS 세계의 중간관리자 같음. 자원봉사자들에게 더 많은 일을 떠넘기면서 칭찬받고, 그 일이 긴급할수록 더 칭찬받음. 이슈의 현실적 영향이나 실용적 함의를 인정하는 건 그들의 인센티브와 충돌함
    소프트웨어 업계의 밑바닥 청소부처럼 보이지 않기가 어렵고, 이제는 이들을 따돌림받는 존재처럼 대하기 시작했으면 함. PR을 보내든가, 아니면 조용히 하라는 것임

  • FFmpeg를 개인적으로도, 내가 만든 서비스에서도 아주 오래 써 왔음. Fabrice Bellard는 천재이고, FFmpeg를 여기까지 끌고 온 개발자들은 세상을 측정 가능할 만큼 더 풍요롭게 만들었음
    하지만 신뢰할 수 없는 입력으로 실행할 때 FFmpeg만큼 샌드박싱할 가치가 큰 프로그램은 떠오르지 않음. 완전히 정확하게 만들기 악명 높게 어려운 복잡한 비디오·오디오 코덱을 거대한 C 코드가 다루고 있기 때문임
    그래도 실제로는 그렇게 큰 문제는 아님. FFmpeg를 VM이나 gVisor 안에서 실행하고, 최종 결과물은 보통 브라우저에서 재생할 의향이 있는 비디오 파일임. 브라우저에서도 또 다른 샌드박스 안에서 디코딩되니까, 이건 원래 어려운 일임

    • DRM, “신뢰된 플랫폼”, 규제 포획 등을 원하는 저작권 보유 기업들이 여기서 일부 피해를 키울 것 같다는 우울한 예측이 듦
      안전한 샌드박싱은 제한 없는 복사를 가능하게 할 기회가 되기 쉬움
    • “브라우저에서 재생할 의향이 있는 비디오 파일”이라는 게 무슨 뜻인지 모르겠음. 어떤 비디오 파일도 브라우저 디코딩 샌드박스를 탈출할 수 없다고 가정해도 안전한 것 아닌가?
    • 하지만 인코딩에는 하드웨어 가속기가 필요한 경우도 많아서, 결국 다시 C를 써야 하는 경우가 흔함
  • RTP LATM 역패킷화 코드에서 latm_parse_packet()이 부호 있는 32비트 덧셈을 수행하다 오버플로가 나고 경계 검사를 우회한다는 취약점임
    또다시 검사 없는 덧셈 때문에 취약점이 생겼고, 그런데도 Rust나 Go 같은 현대 언어는 오버플로에서 예외를 던지지 않으며, RISC-V 같은 현대 CPU 아키텍처도 오버플로 트랩을 제공하지 않음. C나 C++ 같은 오래된 언어에도 오버플로 검사가 없음
    우스운 일임. 사람이 올바른 산술 코드를 작성한다고 믿을 수 없다는 건 명백함

    • Rust는 디버그 모드에서 오버플로 검사를 켜고, 릴리스 모드에서도 켤 수 있음. 실제로 그렇게 쓰고 있음
      Rust의 릴리스 모드 기본 정수 오버플로 동작도 정의되어 있으며, 단지 래핑될 뿐임. 그래서 취약점으로 이어질 가능성은 낮아짐. 물론 unsafe Rust를 쓰기 시작하면 다름
    • Zig는 오버플로에서 예외를 냄. 포화 덧셈과 래핑 덧셈에는 +|=, +%= 연산자가 있음
      Rust는 기본으로 오버플로 예외를 내지 않지만, 123.checked_add(321)처럼 쓰면 됨. 그러면 코드는 읽기 어려워지지만 오버플로에는 안전함
      솔직히 내가 코드를 쓰는 방식상 줄 끝 주석 같은 형태가 더 좋겠음. 예를 들면 var x = y + z; # wrapped처럼 말임
      한 줄 안에서 래핑·검사·포화 산술을 섞을 가능성은 매우 낮음. Zig에서는 모든 줄이 다른 코드 맥락 없이도 그 자체로 컴파일 가능해야 하므로 doing(wrapped) { x + y } 같은 컴파일러 상태는 안 됨. 함수 이름은 너무 장황하고, 형변환도 너무 장황함. 문장 단위 수정자가 좋은 절충안일 수 있음