33장. Navigation과 Bridge를 allowlist로 잠근다
local bundle의 origin만 native bridge를 사용할 수 있게 하고 외부 HTTP(S) 링크는 시스템 browser로 연다. window.open, redirect, iframe, intent/custom scheme을 각각 처리한다. 사용자 입력 URL을 그대로 WebView에 load하지 않는다. TLS 오류, hostname mismatch, mixed content는 fail-closed다. 개발 live reload host는 debug build와 local network에만 존재해야 한다.
bridge command는 {version, requestId, method, payload} schema를 검증한다. method allowlist, payload 크기·field, foreground와 user gesture, 로그인·업무 권한을 확인한다. native 응답은 필요한 값만 반환하고 file path, access token, raw device identifier를 주지 않는다.
const CaptureCommand = z.object({
version: z.literal(1), requestId: z.string().uuid(),
inspectionId: z.string().regex(/^FM-[0-9]{4}$/),
maxWidth: z.number().int().min(320).max(2048),
}).strict()
실패 실습은 외부 origin, unknown method, 5MB payload, background invocation, 다른 site inspection id다. native와 server 양쪽이 거부하고 민감 값이 log에 없는지 확인한다.