본문 바로가기
C.W.K.
Stream
Lesson 04 of 05 · published

들어가길 거부하는 방들

~11 min · secure-field, denylist, refusal, privacy

Level 0불씨 없음
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"제일 중요한 기능은, 앱이 자기가 할 수 있는 걸 보고도 사양하는 그거야."

거부가 곧 기능

Firekeeper 는 접근성을 쥐고 있어. 네 비밀번호 관리자에서 포커스된 요소를 읽을 있다는 뜻이야. OS 는 그걸 막아 주지 않아. '할 수 있다' 와 '한다' 사이에 서 있는 건 앱이 안 하기로 고르는 것 하나뿐이고. 그리고 그 선택은 마음속 의도로 남으면 안 돼. 코드에 단단한 거부로 적혀 있어야지. 보안 텍스트 필드가 제일 분명한 경우야. 포커스된 요소가 보안 필드면 Firekeeper 는 맥락을 안 읽고, 클립보드를 안 건드리고, 삽입을 아예 거부해.

거부의 두 계층

계층 1 — 보안 필드 감지 (OS 가 알려줌):
    맥락 안 읽음, 클립보드 안 건드림, 삽입 안 함. 완전 정지.

계층 2 — 앱 거부목록 (네가 정함):
    비밀번호 관리자, 뱅킹 앱, 유저가 사적이라 표시한 뭐든.
    받아쓰기가 거기선 그냥 작동 안 함.

계층 1 은 기계적이야. macOS 가 보안 필드를 표시해 주고, 넌 그 표시를 존중하면 돼. 계층 2 는 판단이고. 어떤 앱은 필드 하나가 아니라 통째로 민감하고, 유저가 '여긴 절대' 라고 말할 수 있어야 하니까. 둘 다 거부야. 그리고 둘 다 삽입 직전에 예의 바르게 확인하는 게 아니라 제일 이른 지점에서 강제해야 해. 맥락을 읽기 전, 타깃 캡처 단계에서. 금고 앞을 지키는 것보다 문 앞을 지키는 게 나아.

왜 격하가 아니라 거부인가

넘어가기 쉬운 중간 지대가 있어. '보안 필드에서도 받아쓰긴 하되 맥락 읽기만 건너뛰자.' 버텨. 민감한 맥락에서 절반만 작동한다는 건 앱이 여전히 거기서 살아 있고, 여전히 타깃을 쥐고 있고, 건드리면 안 되는 걸 건드리기까지 버그 하나 거리라는 뜻이야. 완전히 거부하는 쪽이 따져 보기도 단순하고, 검증하기도 단순하고, 유저한테 설명하기도 단순해. 비밀번호 필드에선 작동 안 해. 아예, 설계상. 어떤 방에서 절대 안 쓰는 능력은 그 방에서 오용될 수가 없어.

거부는 마지막이 아니라 제일 이른 경계에서 강제해. 규칙이 '보안 필드는 절대 안 읽음' 이면, 그 확인은 타깃 캡처에 속해. 맥락을 모으기 전에. 읽기 자체의 조건이 아니라. 늦게 확인하는 거부는 민감한 게 이미 건드려진 창을 남겨 둬. 문에서 거부하면 위험한 코드는 아예 돌지도 않고.
거부 없는 능력은 아직 안 쓴 신뢰일 뿐이야. 접근성 권한을 가진 앱은 전부 키로거가 될 수 있어. 도구랑 스파이웨어를 가르는 건 오직 적어 두고 강제하는 거부뿐이고. 네 앱이 침해적인 권한을 쥐고 있는데 그걸로 뭘 안 하겠다는 명시적인 목록이 없으면, 유저는 네 아키텍처가 아니라 네 의도를 믿고 있는 거야. 그리고 의도는 리팩터를 못 견뎌.

Code

민감한 게 건드려지기 전, 캡처 시점에 거부·swift
func snapshot() -> TargetSnapshot? {
    guard let front = NSWorkspace.shared.frontmostApplication else { return nil }

    // 계층 2 — 유저/앱 거부목록: 여기선 아예 작동 안 함.
    if denylist.contains(front.bundleIdentifier ?? "") { return nil }

    let element = focusedElement()

    // 계층 1 — 보안 필드: 맥락을 읽기 전에 거부.
    if isSecureTextField(element) {
        return TargetSnapshot(secure: true)   // 거부를 하류로 전달
    }

    // 이제야 — 비-보안, 비-거부목록 타깃에서 — 맥락을 읽음.
    return TargetSnapshot(app: front, element: element,
                          selection: selectedText(element), secure: false)
}
// 삽입, 클립보드 처리, 맥락 수집 전부 `secure` 를 존중함.

External links

Exercise

침해적인 권한을 쥐고 지을 앱을 하나 정하고, 거부 목록을 써봐. 할 수 있는데도 절대 안 할 구체적인 것들 말이야. 그다음 거부마다 어디서 강제할지 정하고, 민감한 데이터를 이미 읽은 뒤에 강제되는 게 없는지 확인해.
Hint
좋은 거부 목록은 구체적이고 확인할 수 있어. '보안 필드는 절대 안 읽음', '거부목록에 든 앱에선 절대 작동 안 함' 처럼. '프라이버시를 존중합니다' 같은 모호한 건 아니고. 그리고 그걸 진짜로 만드는 건 강제하는 지점이야. 데이터가 메모리에 들어온 다음에 확인하는 거부는 그다음에 버려도 이미 실패한 거거든. 거부는 전부 위험한 경로를 통째로 건너뛸 수 있는 제일 이른 경계로 밀어.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.