C.W.K.
Stream
Lesson 04 of 04 · published

검색은 편집이야

~11 min · handoff, security, capability, confused-deputy

Level 0Empty Shelf
0 XP0/35 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"hit 은 답이 아냐. hit 은 문이야. 답은 그 초에서, 네 앞에 열린 영상이고."

원을 닫으며

트랙 1 은 여기서 검색이 텍스트 조회가 아니라 편집 워크플로라는 주장으로 열었어. 이제 기계장치를 봤으니 — 증거, release, 타임스탬프 segment — 그 주장이 실제로 뭘 사는지 볼 수 있어. hit 은 단어에서 안 끝나. 결과 하나에서 그 정확한 segment 의 영상 상세를 열고, 기본 플레이어로 원본을 열고, 특정 플레이어로 열고, QuickTime 으로 열어 절대 hit 시각으로 seek 하고, Finder 에서 드러내 Final Cut Pro 로 끌어다 놓을 수 있어. 파이프라인 전체가 존재하는 이유는 질문 — '내가 그거 어디서 말했더라?' — 이 잘라낼 준비된 열린 클립으로 끝나게 하려고야.

seam: 브라우저는 절대 파일을 지목 안 해

이제 그 handoff 가 어떻게 지어졌나 봐, 보안 원리의 작은 마스터클래스니까. 뻔한 구현은 브라우저에서 파일 경로를 보내는 거야: '/path/to/video.mov 를 12:34 에 열어.' 돌아가는 코드로 가는 최단 경로고, 함정문이야. 브라우저가 경로를 지목할 수 있는 순간, 서버가 confused deputy — 진짜 파일시스템 권한을 가진 프로세스가, 훨씬 덜 신뢰받는 호출자가 시키는 대로 하는 것 — 가 돼. 그 endpoint 에 닿을 수 있는 누구든 이제 특권 프로세스한테 임의 파일을 열라고 할 수 있어.

그래서 Recall 의 브라우저는 딱 셋만 제출해: DB 소유 video id, 고정 enum 의 action(default / movist / quicktime / reveal), 그리고 타임스탬프. 경로 없음. 명령 없음. 인자 없음. 그다음 control plane 이 신뢰받는 작업을 스스로 해: 자기 DB 에서 미디어 경로를 해석하고, canonicalize 하고, allowlist 된 root 아래 앉는지 확인하고, 고정 인자 목록을 실행해. client 는 원하는 을 참조로 대고; 서버가 서버만 소유한 데이터에서 어떻게를 정해. 그게 capability-by-reference 고, path-traversal 이랑 injection 버그의 부류 전체를 그냥 필터되는 게 아니라 구조적으로 불가능하게 만들어.

일하는 엔지니어의 메모 둘

이 구석의 현실주의는 훔칠 가치가 있어. 첫째: 그 GUI 행위들은 경계 지어진 백그라운드 스레드에서 돌아, 차가운 네트워크 마운트나 응답 없는 앱이 안 그러면 HTTP 요청을 열어둔 채 붙잡을 수 있으니까. 트랙 6 의 죽일 수 있는 자식과 같은 본능 — 네가 지연을 통제 못 하는 게 호출자의 critical path 에 앉게 절대 두지 마. 예를 들어 QuickTime 은 먼저 열리고, 문서가 준비되는 동안 정확한 seek 이 몇 초간 재시도돼, '열림' 과 'seek 준비됨' 이 같은 순간이 아니니까.

둘째, 더 인간적인 거: 한 플레이어는 설치된 버전에 쓸 만한 스크립팅 인터페이스가 없어서, Recall 이 프로그램적으로 seek 을 못 해. 솔깃한 수는 척하는 거야 — 0 에서 열고 바라기. 대신 Recall 은 파일을 열고 사람이 수동으로 seek 하도록 목표 타임코드를 표시해. 그게 정직한 저하야: 기능이 자기가 못 하는 걸 정확히 인정하고 네가 스스로 끝낼 데 필요한 정보 한 조각을 건네. 자기 한계에 대해 진실을 말하는 도구가 조용히 틀린 걸 하는 것보다 값져.

Code

client 는 참조로 요청; 서버가 자기 권한으로 해석·typescript
// 브라우저가 보내도 되는 것. 그게 전부다.
type InspectRequest = {
  video_id: string;                                  // DB 소유 id
  action: "default" | "movist" | "quicktime" | "reveal";  // 고정 enum
  timestamp_ms: number;
};
// 경로 없음. 명령 없음. 인자 없음. client 가 지어낸 것 없음.

// 서버 쪽 (진짜 파일시스템 권한 보유):
//   1. video_id 로 자기 DB 에서 미디어 경로 해석
//   2. 경로 canonicalize
//   3. allowlist 된 root 아래 앉는지 확인   <- 아니면 거부
//   4. enum action 에 대한 고정 인자 목록 실행
//
// client 는 참조로 무엇을; 서버가 어떻게를 정한다.
// path traversal 과 command injection 이 표현 불가능해진다.

External links

Exercise

네 일에서 client 가 특권 프로세스한테 리소스에 행동하라고 요청하는 endpoint 를 찾아 — 파일 열기, URL 가져오기, 리포트 돌리기, record export. payload 를 봐: client 가 경로, URL, 쿼리 조각, 명령을 줘? client 가 불투명 id + 닫힌 enum 의 action 만 보내고, 서버가 자기 데이터에서 진짜 대상을 해석하고 allowlist 로 검증하게 다시 설계해. 어떤 버그 부류가 방금 불가능해졌는지 적어봐.
Hint
모든 요청 payload 에 던질 질문은: '적대적 호출자가 여기 뭘 댈 수 있어?' 야. 답에 파일시스템 경로, URL, 테이블 이름, 인자가 되는 뭐라도 있으면, 일어나길 기다리는 confused deputy 가 있는 거야. 호출자가 준 리소스를 호출자가 준 *참조*로 바꾸고, 해석 — 그리고 allowlist 확인 — 을 권한 쥔 쪽에 전부 둬.

Progress

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

댓글 0

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

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