서론
무엇이 ‘같음’일까요?
이 겉보기에 간단해 보이는 질문은 컴퓨터 시스템에서 수많은 함정을 내포하고 있습니다. 2025년 4월, 리누스 토발즈(Linus Torvalds)는 Linux 커널 메일링 리스트에서 bcachefs의 케이스 폴딩(case-folding) 기능에 대해 격렬한 어조의 메일을 보냈습니다1. 그의 핵심 논점은 한 문장으로 요약될 수 있습니다. 파일 이름은 단지 바이트의 연속(a string of bytes)이어야 하며, 파일 시스템이 이를 ‘이해’하려고 시도해서는 안 된다는 것입니다.
이것은 단순히 기술적 선호도의 문제가 아닙니다. 우리가 파일 이름에 의미(Semantics)를 부여하기 시작할 때, 예를 들어 시스템이 A와 a가 같다거나, é와 e+´가 같다고 이해하게 만드는 순간, 우리는 판도라의 상자를 여는 것과 같습니다.
이 문제의 본질을 더 자세히 이해해 봅시다.
파일 이름의 본질: 식별자인가 이름인가?
도서관에서 각 책은 두 가지 방식으로 식별됩니다. 도서명과 청구기호입니다. 도서명은 의미가 있으며 그 책이 무엇에 관한 것인지 알려주지만, 청구기호는 불투명(Opaque)하며 서가에서 책의 위치를 찾기 위한 고유한 식별자일 뿐입니다.
Unix 설계자들은 ‘청구기호’ 모델을 선택했습니다.
Unix의 설계 철학에서 파일 이름은 불투명한 바이트 시퀀스입니다. 커널의 역할은 간단합니다. 이 바이트 시퀀스를 inode(색인 노드)에 매핑하는 것입니다. O’Reilly에서 출판된 「Understanding the Linux Kernel」에 기술된 바와 같이, “Unix 파일은 바이트 시퀀스로 구성된 정보 컨테이너이며, 커널은 파일의 내용을 해석하지 않습니다.”2 이러한 ‘해석하지 않음’의 철학은 파일 이름에도 동일하게 적용됩니다.
이러한 설계 선택의 심층적인 이유는 무엇일까요?
단순함은 예측 가능성을 가져옵니다. 파일 이름이 단지 바이트 시퀀스일 때, 시스템의 동작은 완전히 결정론적입니다. 두 파일 이름은 바이트 시퀀스가 완전히 일치할 때만 동일합니다. 모호함도, 특수 상황도, 문화적 의존성도 없습니다. VFS(Virtual File System) 계층은 dentry 캐시를 통해 경로명을 inode로 해석하지만, 이 과정은 순수한 바이트 매칭입니다3.
하지만 macOS는 다른 길을 선택했습니다.
동치 관계: 같음이 복잡해질 때
수학에서 동치 관계(Equivalence relation)는 반사성(a ~ a), 대칭성(a ~ b이면 b ~ a), 이행성(a ~ b이고 b ~ c이면 a ~ c)의 세 가지 성질을 만족하는 관계입니다. 우리가 대소문자를 구분하지 않는다고 말할 때, 우리는 실제로 A ~ a, B ~ b와 같은 동치 관계를 정의하고 있는 것입니다.
간단해 보이지 않나요?
하지만 문제는 ‘누가 이 동치 관계를 정의하느냐’입니다. 시스템마다 정의가 다를 수 있습니다.
영어에서 i의 대문자는 I이며, 이는 자명해 보입니다. 하지만 터키어에는 네 가지 서로 다른 i가 있습니다.
| 형태 | 점 있음 | 점 없음 |
|---|---|---|
| 대문자 | İ (U+0130) | I (U+0049) |
| 소문자 | i (U+0069) | ı (U+0131) |
터키어에서 i의 대문자는 İ(점이 있는 대문자 I)이고, I의 소문자는 ı(점이 없는 소문자 i)입니다4. 이는 보안 검사 프로그램이 영어 규칙을 사용하여 FILE을 소문자로 변환해 file을 얻고, 파일 시스템이 터키어 규칙을 사용하여 fıle을 얻는다면, 이 두 문자열은 일치하지 않게 됨을 의미합니다. 비록 그것들이 같은 파일 이름이어야 ‘함에도’ 말이죠.
WARNING
이것은 이론적인 문제가 아닙니다. Jeff Atwood는 Coding Horror 블로그에서 실제 사례를 기록했습니다. 애플리케이션이 터키어 로케일(locale)에서 실행될 때, 문자열 INTEGER를 소문자로 변환하면 integer가 아닌 ınteger가 되어 프로그램 로직이 완전히 무너지는 사례가 있었습니다5.
이는 심각한 문제를 드러냅니다. 대소문자 변환은 보편적이고 문화 중립적인 작업이 아닙니다. 파일 시스템 계층에서 대소문자 비구분을 구현할 때, 우리는 특정 규칙을 선택해야만 하며, 이 선택은 사용자 공간 프로그램이 사용하는 규칙과 일치하지 않을 수 있습니다.
유니코드 정규화: 더 깊은 토끼굴
대소문자 비구분만으로도 충분히 복잡하지만, 유니코드 정규화(Unicode Normalization)는 문제를 또 다른 차원으로 끌어올립니다.
간단한 질문부터 시작해 봅시다. é는 하나의 문자인가요, 아니면 두 개의 문자인가요?
유니코드에서 답은 “둘 다 가능함”입니다. é는 단일 코드 포인트 U+00E9(LATIN SMALL LETTER E WITH ACUTE)로 표현될 수도 있고, 두 개의 코드 포인트 U+0065(LATIN SMALL LETTER E) + U+0301(COMBINING ACUTE ACCENT)로 표현될 수도 있습니다. 이 두 표현은 시각적으로는 완전히 동일하지만, 바이트 수준에서는 완전히 다릅니다.
정규화 결합 형식(NFC): C3 A9 -> é정규화 분해 형식(NFD): 65 CC 81 -> e + ́ → é유니코드 표준은 네 가지 정규화 형식(NFC, NFD, NFKC, NFKD)을 정의합니다6. NFC는 완성형 문자를 사용하는 경향이 있고, NFD는 문자를 기본 문자와 결합 표시로 분해하는 경향이 있습니다.
HFS+는 NFD를 선택했습니다. Apple의 기술 문서에 따르면, HFS+는 “유니코드 정규화 형식 D(NFD)와 매우 유사한” 정규화 형식을 사용합니다7. 즉, café라는 이름의 파일을 생성하면 시스템은 자동으로 é를 e + ´라는 두 개의 코드 포인트로 분해합니다.
이 설계 결정은 나름의 타당성이 있습니다. 강제 정규화를 통해 HFS+는 동일한 ‘문자’가 단 하나의 표현 방식만 갖도록 보장하며, 이를 통해 사용자가 ‘시각적으로는 같지만 실제로는 다른’ 두 개의 파일을 생성하는 것을 방지합니다.
하지만 여기서 핵심적인 문제가 발생합니다. HFS+의 정규화 규칙은 유니코드 3.2를 기반으로 하며, 이 규칙은 유니코드 표준의 발전에 따라 업데이트될 수 없습니다. 왜냐하면 “이러한 진화가 기존 HFS+ 볼륨을 무효화할 수 있기 때문”입니다8.
IMPORTANT
이것은 1998년에 멈춘 정규화 구현이 2025년의 사용자를 서비스하고 있는 상황입니다. 유니코드 표준은 3.2에서 17.0(2025년 9월 9일 발표)까지 진화하며 수만 개의 문자가 추가되었지만, HFS+의 정규화 규칙은 영원히 과거에 머물러 있습니다.
2017년, Apple은 HFS+를 대체하기 위해 APFS를 출시했습니다. APFS는 중요한 변화를 주었습니다. 더 이상 유니코드 정규화를 강제하지 않고, 정규화 보존적이지만 정규화 비구분적(normalization-preserving but normalization-insensitive)인 방식을 택했습니다9. 즉, APFS는 입력한 원래의 바이트 시퀀스를 보존하지만, 파일 이름을 비교할 때는 여전히 정규화 동등성을 고려합니다.
이 변화는 일부 문제를 해결했지만 새로운 문제도 가져왔습니다. HFS+에서 APFS로 마이그레이션할 때 기존에 정규화된 파일 이름은 NFD 형식을 유지하는 반면, 새로 생성된 파일은 NFC 형식을 사용할 수 있습니다. 특정 엣지 케이스에서는 ‘시각적으로는 같지만 실제로는 다른’ 파일 이름이 동일한 디렉토리에 공존하게 될 수도 있습니다.
보안 취약점의 본질: 동치 관계의 불일치
이제 보안 취약점의 본질을 이해할 수 있습니다.
보안 검사 프로그램과 파일 시스템이 서로 다른 동치 관계를 사용할 때 ‘틈새’가 발생합니다. 공격자는 보안 검사 프로그램 입장에서는 안전해 보이지만, 파일 시스템 입장에서는 위험한 파일 이름과 동일하게 간주되는 파일 이름을 구성할 수 있습니다.
토발즈는 메일에서 이 문제를 정확하게 묘사했습니다.
“사용자 공간에서 파일 이름이 보안에 민감한 패턴과 일치하지 않는지 확인했는데, 멍청한 파일 시스템이 결국 그 패턴과 일치시켜 버리는…” 식의 보안 문제들.
구체적인 예를 들어보겠습니다.
2021년 3월, Git 프로젝트는 심각한 취약점 CVE-2021-21300을 공개했습니다10. 이 취약점은 특히 대소문자를 구분하지 않는 파일 시스템을 사용하는 Windows 및 macOS 사용자에게 영향을 미쳤습니다.
취약점의 원리는 Git의 lstat 캐시 메커니즘과 관련이 있습니다. Git이 파일을 체크아웃할 때 시스템 호출을 줄이기 위해 캐시를 유지합니다. 공격자는 A와 a라는 두 파일을 포함하는 악성 저장소를 구성할 수 있습니다. 대소문자를 구분하는 파일 시스템에서는 서로 다른 두 파일이지만, 대소문자를 구분하지 않는 파일 시스템에서는 충돌이 발생합니다.
공격의 핵심은 Git의 내부 로직(대소문자 구분 가정)과 파일 시스템의 동작(대소문자 비구분) 사이의 불일치에 있습니다. 공격자는 이 불일치를 이용하여 Git이 체크아웃 과정에서 임의의 코드를 실행하도록 만들 수 있습니다.
유니코드 정규화로 인한 보안 문제는 더욱 미묘합니다. Black Hat USA 2019의 연구 논문 「Host/Split: Exploitable Antipatterns in Unicode Normalization」에 따르면, 보안 결정이 유니코드 문자열을 기반으로 내려지고 후속 처리가 다른 정규화 형식을 사용할 때 이용 가능한 취약점이 발생합니다11.
이런 시나리오를 생각해 봅시다. 보안 소프트웨어가 파일 이름이 /etc/passwd와 같은 민감한 경로와 일치하는지 검사합니다.
공격자는 보이지 않는 문자나 유니코드 변체(variant)를 포함한 파일 이름을 생성합니다. 보안 소프트웨어는 문자열을 검사하고 /etc/passwd와 일치하지 않는다고 판단하여 통과시킵니다.
그러나 파일 시스템이 하위 계층에서 이를 처리할 때, 이러한 유니코드 변체를 /etc/passwd와 동등한 형식으로 정규화하여 보안 검사를 우회하게 될 수 있습니다.
CERT/CC는 VU#999008에서 유사한 문제를 기록했습니다. 컴파일러가 소스 코드에 유니코드 제어 문자나 동형 이의어(homoglyph)를 허용할 경우, 코드 리뷰 시 악성 코드를 숨기는 데 사용될 수 있습니다12.
TOCTOU: 시간 차원의 동치 관계 문제
더욱 미묘한 유형의 취약점인 TOCTOU(Time-of-Check to Time-of-Use)가 있습니다.
TOCTOU 취약점의 본질은 검사(Check)와 사용(Use) 사이에 시간적 창(Window)이 존재하며, 공격자가 이 창 안에서 시스템 상태를 변경하여 검사 결과를 무효화할 수 있다는 점입니다13.
파일 시스템의 맥락에서 이 문제는 파일 이름의 의미론적 해석과 밀접하게 관련되어 있습니다. 파일 액세스 과정을 생각해 봅시다.
- 프로그램이 파일 이름을 사용하여 파일 액세스를 요청함
- 커널이 파일 이름을 inode로 해석함
- 커널이 권한을 검사함
- 커널이 파일 서술자(File Descriptor)를 반환함
문제는 1단계와 2단계 사이에서 파일 이름과 inode 사이의 매핑이 변경될 수 있다는 것입니다. 공격자는 이 창 안에서 파일 이름이 다른 파일을 가리키도록 바꿀 수 있습니다.
NOTE
여기서 중요한 기술적 세부 사항이 있습니다. 파일 이름과 inode의 매핑은 가변적이지만, inode와 파일 서술자의 매핑은 안정적입니다14. 일단 파일 서술자를 획득하면 그것은 직접 inode를 가리키며 더 이상 파일 이름에 의존하지 않습니다. 이것이 바로 CERT SEI가 “중요한 파일은 한 번만 열고, 파일 이름이 아닌 파일 서술자를 통해 필요한 모든 작업을 수행하라”고 권고하는 이유입니다.
macOS의 대소문자 비구분 및 유니코드 정규화는 TOCTOU 문제를 더욱 복잡하게 만듭니다. 보안 검사가 한 가지 형식의 파일 이름을 사용하고 실제 파일 작업이 동등하지만 다른 형식의 파일 이름을 사용할 때 TOCTOU 창이 확장될 수 있습니다.
USENIX FAST’23의 논문 「Unsafe at Any Copy: Name Collisions from Mixing Case Sensitivity」는 이 문제를 체계적으로 연구했습니다15. 연구 결과, 서로 다른 파일 시스템의 케이스 폴딩 규칙과 정규화 기술 사이에 차이가 있음이 밝혀졌습니다. 예를 들어, temp_200K(여기서 K는 켈빈 기호 U+212A)와 temp_200k는 NTFS와 APFS에서는 동일하게 간주되지만, ZFS에서는 다르게 간주됩니다.
이러한 불일치는 보안 취약점의 온상이 됩니다.
심층 방어: 파일 이름을 믿을 수 없을 때
파일 이름을 신뢰할 수 없다는 현실에 직면하여, Apple은 심층 방어(Defense in Depth) 전략을 선택했습니다.
이 전략의 핵심 아이디어는 파일 이름을 신뢰할 수 있게 만들 수 없다면, 신뢰 구축을 위해 파일 이름에 의존하지 말라는 것입니다. 대신 여러 계층에서 독립적인 보안 장벽을 구축하고, 각 장벽은 서로 다른 신뢰 기반을 사용합니다.
Apple이 이 전략을 어떻게 구현했는지 살펴봅시다.
머클 트리와 서명된 시스템 볼륨
macOS Big Sur(11.0)는 서명된 시스템 볼륨(Signed System Volume, SSV) 메커니즘을 도입했습니다16. SSV의 핵심 아이디어는 파일 이름에 의존하는 대신 암호화 해시를 사용하여 시스템 무결성을 검증하는 것입니다.
SSV의 기술적 구현은 머클 트리(Merkle Tree)를 기반으로 합니다. 머클 트리는 고정된 크기의 ‘루트 해시’를 사용하여 임의 크기의 데이터 세트 무결성을 검증할 수 있게 해주는 우아한 데이터 구조입니다17.
머클 트리의 작동 원리는 다음과 같습니다.
- 데이터를 여러 블록으로 나누고 각 블록의 해시값을 계산함(리프 노드)
- 인접한 해시값을 쌍으로 묶어 결합 해시를 계산함(내부 노드)
- 해시값이 하나만 남을 때까지 2단계를 반복함(루트 노드)
이 구조의 핵심 특징은 어떤 데이터 블록이라도 수정되면 해당 리프 노드에서 루트 노드까지의 경로에 있는 모든 해시값이 변경된다는 것입니다. 따라서 루트 해시만 신뢰할 수 있다면 전체 데이터 세트의 무결성을 검증할 수 있습니다.
TIP
머클 트리의 검증 효율성은 로그 수준(Logarithmic)입니다.
특정 데이터 블록의 무결성을 검증하려면 해당 리프 노드에서 루트 노드까지의 경로에 있는 해시값만 확인하면 됩니다. n개의 데이터 블록에 대해 번의 해시 계산만 필요합니다. 이를 통해 SSV는 부팅 시간을 크게 늘리지 않고도 부팅 시 시스템 무결성을 신속하게 검증할 수 있습니다.
SSV 구현에서 시스템 볼륨의 각 파일은 파일 시스템 메타데이터에 저장된 SHA-256 해시값을 가집니다. 루트 노드의 해시값은 실(Seal)이라고 불리며, SSV의 모든 바이트를 아우릅니다.
이 실(Seal)은 Mac이 부팅될 때마다 부트 로더에 의해 검증됩니다. 검증에 실패하면 부팅이 중단되고 사용자에게 운영체제 재설치 안내가 표시됩니다18.
이것이 무엇을 의미할까요? 공격자가 어떤 대소문자 혼동이나 유니코드 변체를 사용하든, 심지어 Root 권한을 획득하더라도 시스템 볼륨의 내용을 수정하려고 시도하는 순간 해시값이 일치하지 않게 되어 시스템은 부팅을 거부합니다. 파일 이름의 의미론적 해석 문제는 여기서 무의미해집니다. 전체 볼륨의 무결성이 파일 이름이 아닌 암호화 해시를 통해 보장되기 때문입니다.
메타데이터 마킹과 SIP
SSV 이전에도 macOS에는 SIP(System Integrity Protection), 일명 rootless가 있었습니다19. SIP의 핵심 아이디어는 파일 이름에 의존하는 대신 메타데이터 마킹을 사용하여 주요 파일을 보호하는 것입니다.
SIP는 새로운 restricted 파일 플래그를 도입했습니다. restricted로 마킹된 파일은 root 사용자라 할지라도 수정할 수 없습니다20.
핵심은 SIP의 검사가 파일 이름이 아닌 inode의 메타데이터 마킹을 기반으로 한다는 점입니다. 임의의 프로세스가 보호된 디렉토리에 쓰기를 시도할 때, 커널은 해당 inode가 ‘SIP 보호’ 마킹이 되어 있는지 확인합니다. 공격자가 유니코드 변체나 대소문자 혼동으로 상위 계층의 검사를 속였더라도, 요청이 커널에 도달하면 커널은 inode의 restricted 플래그를 확인하고 작업을 거부합니다.
이는 중요한 설계 원칙입니다. 신뢰의 기반을 파일 이름에서 inode의 메타데이터로 옮기는 것입니다. 파일 이름은 혼동될 수 있지만, inode의 메타데이터는 커널에 의해 직접 관리되며 파일 이름의 의미론적 해석에 영향을 받지 않습니다.
파일 서술자: 파일 이름 우회하기
Apple은 개발자 문서에서 파일 경로 문자열을 직접 사용하는 대신 NSURL(객체) 및 파일 서술자(File Descriptor)를 사용할 것을 권장합니다21.
이 설계 선택 뒤에는 깊은 보안적 고려가 깔려 있습니다.
샌드박스(Sandbox) 메커니즘 하에서 사용자가 앱에 특정 파일 액세스 권한을 부여하면, 시스템은 앱에 경로가 아닌 토큰(Token)을 제공합니다. 앱은 이 토큰을 통해 커널에 파일 액세스를 요청하고, 커널은 inode를 통해 파일을 찾습니다.
이러한 설계는 복잡한 경로 해석, 대소문자 매칭, 유니코드 정규화 문제를 회피합니다. 더 중요한 것은 파일 서술자가 파일 이름을 통한 간접 참조가 아닌 inode를 직접 가리키기 때문에 TOCTOU 취약점의 가능성을 근본적으로 제거한다는 점입니다.
TCC: 프로세스 신원 기반의 액세스 제어
TCC(Transparency, Consent, and Control)는 macOS에서 애플리케이션의 민감한 데이터 액세스를 관리하는 프레임워크입니다22. TCC의 핵심은 /Library/Application Support/com.apple.TCC/TCC.db에 저장된 SQLite 데이터베이스입니다.
TCC의 핵심 보안 특징은 파일 이름이 아닌 프로세스 신원(Identity)을 기반으로 액세스를 차단한다는 점입니다. 공격자가 사용자의 개인정보 디렉토리를 읽으려 할 때, TCC는 단순히 파일 경로 문자열을 검사하는 것이 아니라 요청하는 프로세스의 신원과 권한을 확인합니다.
TCC 데이터베이스 자체는 SIP에 의해 보호되므로 직접 수정할 수 없습니다23. 이 데이터베이스를 조작하려면 공격자는 SIP를 비활성화하거나 신뢰할 수 있는 시스템 프로세스에 대한 액세스 권한을 획득해야만 합니다.
설계 철학에 대한 반성
리누스 토발즈의 비판으로 돌아가 보면, 이것이 단순한 기술적 문제가 아니라 설계 철학의 문제임을 알 수 있습니다.
Unix의 설계 철학은 단순성과 직교성(Orthogonality)을 강조합니다. 파일 이름은 바이트 시퀀스이며 커널은 그 의미를 해석하지 않습니다. 이 설계의 장점은 예측 가능성과 보안성입니다. 숨겨진 의미 변환도, 예상치 못한 동치 관계도 없습니다.
macOS는 사용자에게 더 친숙한 경험을 제공하기 위해 다른 길을 선택했습니다. 대소문자 비구분 덕분에 사용자는 Document.txt와 document.txt의 차이를 걱정할 필요가 없습니다. 유니코드 정규화 덕분에 사용자는 NFD와 NFC의 차이를 이해할 필요가 없습니다.
하지만 이러한 친절함에는 대가가 따릅니다. 파일 시스템이 파일 이름을 이해하기 시작할 때, ‘같음’을 정의해야 하는 책임을 지게 됩니다. 그리고 같음의 정의는 복잡하고 문화 의존적이며 끊임없이 진화합니다.
더 깊은 문제는 시스템의 서로 다른 계층에서 서로 다른 ‘같음’의 정의를 사용할 때 보안 취약점이 발생한다는 점입니다. 보안 검사 프로그램은 한 종류의 동치 관계를 사용하고, 파일 시스템은 다른 종류를 사용하며, 공격자는 바로 이 불일치를 이용하여 보안 검사를 우회합니다.
Apple의 심층 방어 전략은 실용적인 타협안입니다. 역사적 결정(대소문자 비구분은 이미 macOS의 기본 동작임)을 바꿀 수 없으므로, 더 높은 계층과 더 낮은 계층에서 독립적인 보안 장벽을 구축한 것입니다.
- SSV는 암호화 해시를 통해 시스템 무결성을 보호합니다.
- SIP는 메타데이터 마킹을 통해 주요 파일을 보호합니다.
- 파일 서술자는 파일 이름을 우회하여 inode를 직접 사용합니다.
- TCC는 프로세스 신원 확인을 통해 사용자 데이터를 보호합니다.
이러한 메커니즘의 공통점은 파일 이름을 신뢰하지 않는다는 것입니다. 혼동될 수 있는 문자열에 의존하는 대신 암호화 해시, 메타데이터 마킹, 프로세스 신원, inode를 사용하여 신뢰를 구축합니다.
결론
토발즈의 비판은 보안 시스템이 복잡한 의미론적 해석에 의존해서는 안 된다는 기본 원칙을 상기시켜 줍니다.
단순한 모델은 비록 완벽하지 않더라도 복잡한 모델보다 더 신뢰할 수 있고 예측 가능할 때가 많습니다. Unix의 “파일 이름은 바이트 시퀀스다”라는 원칙은 바로 그러한 단순 모델입니다. 파일 이름을 ‘이해’하는 능력은 포기했지만, 그 대가로 예측 가능성과 보안성을 얻었습니다.
macOS의 역사는 복잡성의 대가를 보여줍니다. HFS+의 유니코드 정규화부터 APFS의 정규화 비구분, Git 취약점부터 TOCTOU 공격에 이르기까지 파일 이름의 의미론적 해석은 항상 보안 문제의 온상이었습니다.
하지만 Apple의 대응 전략은 공학적 지혜를 보여줍니다. 복잡성을 제거할 수 없을 때 심층 방어를 통해 그 영향을 제한할 수 있습니다. SSV, SIP, 파일 서술자, TCC 등 이 모든 메커니즘은 파일 이름의 의미론적 해석에 의존하지 않으며, 더 낮은 계층에서 독립적인 신뢰 기반을 구축했습니다.
개발자들에게 이 이야기가 주는 교훈은 명확합니다.
- 파일 이름이 고유하거나 불변이라고 절대 가정하지 마십시오.
- 파일 작업 시 경로 문자열 대신 파일 서술자를 사용하십시오.
- 보안 검사를 수행할 때 대소문자와 유니코드 정규화의 영향을 고려하십시오.
- 크로스 플랫폼 개발 시 대소문자 구분 및 비구분 환경 모두에서 테스트하십시오.
토발즈가 말했듯, 파일 이름은 단지 바이트의 연속이어야 합니다. 우리가 그것에 마법 같은 의미를 부여하기 시작하는 순간, 우리는 판도라의 상자를 여는 것입니다.
참고 문헌
Footnotes
-
Phoronix. “Linus Torvalds Expresses His Hatred For Case-Insensitive File-Systems.” 2025. https://www.phoronix.com/news/Linus-Torvalds-Anti-Case-Fold ↩
-
Bovet, D. P., & Cesati, M. “Understanding the Linux Kernel, Second Edition.” O’Reilly Media, 2002. ↩
-
Linux Kernel Documentation. “Overview of the Linux Virtual File System.” https://docs.kernel.org/filesystems/vfs.html ↩
-
I18n Guy. “Internationalization for Turkish: Dotted and Dotless Letter I.” http://www.i18nguy.com/unicode/turkish-i18n.html ↩
-
Atwood, J. “What’s Wrong With Turkey?” Coding Horror, 2008. https://blog.codinghorror.com/whats-wrong-with-turkey/ ↩
-
Unicode Consortium. “UAX #15: Unicode Normalization Forms.” https://unicode.org/reports/tr15/ ↩
-
Apple Developer. “Technical Q&A QA1235: Converting to Precomposed Unicode.” https://developer.apple.com/library/archive/qa/qa1235/_index.html ↩
-
Wikipedia. “HFS Plus.” https://en.wikipedia.org/wiki/HFS_Plus ↩
-
Eclectic Light. “Explainer: Unicode, normalization and APFS.” 2021. https://eclecticlight.co/2021/05/08/explainer-unicode-normalization-and-apfs/ ↩
-
InfoQ. “Analyzing Git Clone Vulnerability.” 2021. https://www.infoq.com/news/2021/03/git-clone-vulnerability/ ↩
-
Birch, J. “Host/Split: Exploitable Antipatterns in Unicode Normalization.” Black Hat USA 2019. https://i.blackhat.com/USA-19/Thursday/us-19-Birch-HostSplit-Exploitable-Antipatterns-In-Unicode-Normalization-wp.pdf ↩
-
CERT/CC. “VU#999008 - Compilers permit Unicode control and homoglyph characters.” 2021. https://www.kb.cert.org/vuls/id/999008 ↩
-
MITRE. “CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition.” https://cwe.mitre.org/data/definitions/367.html ↩
-
CERT SEI. “FIO45-C. Avoid TOCTOU race conditions while accessing files.” https://wiki.sei.cmu.edu/confluence/display/c/FIO45-C.+Avoid+TOCTOU+race+conditions+while+accessing+files ↩
-
Basu, A., et al. “Unsafe at Any Copy: Name Collisions from Mixing Case Sensitivity.” USENIX FAST’23. https://www.usenix.org/system/files/fast23-basu.pdf ↩
-
Apple Support. “Signed system volume security.” Apple Platform Security Guide. https://support.apple.com/guide/security/signed-system-volume-security-secd698747c9/web ↩
-
Wikipedia. “Merkle tree.” https://en.wikipedia.org/wiki/Merkle_tree ↩
-
Jamf Blog. “What’s New in macOS Big Sur Security.” 2020. https://www.jamf.com/blog/whats-new-in-macos-big-sur-security/ ↩
-
Wikipedia. “System Integrity Protection.” https://en.wikipedia.org/wiki/System_Integrity_Protection ↩
-
Apple Support. “System Integrity Protection.” Apple Platform Security Guide. https://support.apple.com/guide/security/system-integrity-protection-secb7ea06b49/web ↩
-
Apple Support. “Controlling app access to files in macOS.” Apple Platform Security Guide. https://support.apple.com/guide/security/controlling-app-access-to-files-secddd1d86a6/web ↩
-
Rainforest QA. “A deep dive into macOS TCC.db.” 2021. https://www.rainforestqa.com/blog/macos-tcc-db-deep-dive ↩
-
Huntress. “Full Transparency: Controlling Apple’s TCC.” 2024. https://www.huntress.com/blog/full-transparency-controlling-apples-tcc ↩