모든 페이지는 적대적입니다
<webview> 의 설정은 붙는 순간 메인 프로세스가 다시 씁니다. 렌더러가 무엇을 요청했든 게스트는 샌드박스에 격리됩니다. 렌더러도, 페이지도 믿지 않는다는 것이 security.js 의 첫 문장입니다.
ST Browser(앱 이름 Mars)는 Electron 으로 창틀부터 만든 데스크톱 브라우저입니다. 탭과 주소창, 새 탭, 비공개 탭 같은 셸 위에 광고·추적 차단, 권한 관문, 인증서 경고, 비밀번호 보관함, 확장 프로그램 서명 검증을 직접 얹었습니다. AI 가 페이지를 번호 매긴 목록으로 읽고 여러 동작을 한 번에 실행하도록 브라우저 도구 19개도 들어 있습니다.
처음에는 탭과 주소창을 직접 만드는 셸이었습니다. 지금은 JavaScript 의 47%가 보안·프라이버시 모듈 여덟 개입니다. 사용자 수요는 아직 검증하지 않았다고 설계 문서가 먼저 적어 둡니다.

security.js 는 브라우저가 설명해야 할 실패를 셋으로 봅니다. 틀린 인증서, 끊긴 네트워크, 막힌 주소. 인증서 화면의 값은 expired.badssl.com 의 실제 인증서입니다.
인증서가 틀리면 페이지 대신 경고를 띄우고, 누르기 쉬운 버튼은 “돌아가기” 하나만 둡니다. 호스트와 오류 문자열처럼 네트워크에서 온 값은 전부 textContent 로만 씁니다.
“그래도 계속”은 세부 정보를 펼쳐야 나타나고, 펼친 뒤 5초 동안 눌리지 않습니다. 근육 기억이나 가로챈 클릭으로 결정되지 않게 하려는 것입니다. 예외는 이 호스트와 이 인증서에만, Mars 를 끌 때까지만 적용되고 디스크에 남지 않습니다.
네트워크 오류는 번호가 아니라 Chromium 이 알려 주는 이름(ERR_NAME_NOT_RESOLVED 등)으로 골라 문장과 힌트를 붙입니다. 번호는 Chromium 버전 사이에 바뀐 적이 있기 때문입니다.
웹 페이지가 로컬 파일, 브라우저 내부 페이지, 다른 앱을 열려고 하면 거절하고, 리디렉트로 끼워 넣어도 다시 거절합니다. 이 설명 화면들은 IPC 통로가 없는 평범한 파일이라, 실패를 설명하는 페이지가 더 많은 권한을 갖지 않습니다.




탭과 주소창은 시작이었습니다. 그 위에 새 탭과 비공개 탭, 테마, 그리고 AI 가 읽는 페이지가 올라갔습니다.
AI 보기페이지를 번호 매긴 목록으로 바꿔 AI 에게 건넵니다. 90개에서 자르면 자른 사실과 전체 수를 함께 알립니다. 이 Hacker News 첫 화면은 230개 중 90개였습니다.
행성을 고르면 테마가태양계 테마에서 천체를 누르면 그 천체가 강조색과 새 탭 로고가 됩니다. 지구를 고르면 워드마크도 Earth 로 바뀝니다.
비공개 탭메모리에만 있는 별도 세션을 씁니다. 기록에 남지 않고, 쿠키와 로그인이 분리되며, Mars 를 끄면 전부 사라집니다. 회사와 통신사는 여전히 볼 수 있다는 것도 적어 둡니다.
테마 다섯 · 검색 엔진 일곱시스템 · 다크 · 라이트 · 해커 · 태양계. 검색은 Google · Bing · DuckDuckGo · Naver · Daum · Yandex · YouTube 중에서 고르고, 새 탭 검색창이 지금 엔진을 이름으로 보여 줍니다.
기본 차단 엔진 하나가 목록 14개의 규칙 157,204개를 들고 있습니다. 빌드할 때 미리 직렬화해 두어, 첫 실행에도 목록을 받으러 나가지 않습니다.
<webview> 의 설정은 붙는 순간 메인 프로세스가 다시 씁니다. 렌더러가 무엇을 요청했든 게스트는 샌드박스에 격리됩니다. 렌더러도, 페이지도 믿지 않는다는 것이 security.js 의 첫 문장입니다.
카메라 · 마이크 · 위치 같은 요청은 사용자가 그 사이트에 허락한 적이 있거나 지금 허락할 때만 통과합니다. 시간 초과도, 창 닫힘도 거부입니다. iframe 이 요청하면 최상위 페이지가 아니라 그 iframe 의 출처로 기록합니다.
예전에는 파비콘을 Google 과 DuckDuckGo 서비스에 물어, 연 페이지의 호스트를 전부 넘기고 있었습니다. 지금은 사이트 자신에게서 그 탭의 세션으로 받아 64KB 이하 PNG 로 다시 그립니다. SVG 는 받지 않습니다.
CRX3 서명을 검증하고, 확장 ID 가 서명 키에서 나온 것인지 확인하고, 권한을 알린 뒤에야 설치합니다. 전에는 헤더를 떼고 그냥 풀었습니다. 테스트 17개가 변조된 패키지와 남의 ID 를 사칭한 패키지를 거절하는지 확인합니다.
AI 의 클릭이 합성 이벤트면 isTrusted 가 false 라, 사용자 동작을 요구하는 사이트는 아무 말 없이 무시합니다. 그래서 좌표를 구해 sendInputEvent 로 실제 입력을 보내고, 테스트가 isTrusted === true 를 확인합니다.
페이지 지도의 번호에는 세대 표시가 붙습니다. 페이지가 바뀐 뒤 옛 번호로 누르려 하면 엉뚱한 요소를 누르는 대신 stale_map 으로 거절합니다. 한 단계가 실패해도 나머지 단계는 계속 돕니다.
<webview>Electron 이 주는 것은 창 하나와 렌더링 엔진뿐입니다. 탭, 주소창, 북마크, 새 탭, 경고 화면까지 브라우저라고 부를 만한 것은 전부 직접 정해야 합니다. 엔진은 어디까지고 제품 결정은 어디부터인지 확인하고 싶었습니다. 해 보니 결정의 절반 가까이가 보안이었습니다.
하나는 분명합니다. Chrome 의 확장은 Manifest V3 규칙 상한에 묶이지만, Mars 의 차단 엔진은 규칙 157,204개를 그대로 듭니다. 반대로 콜드 스타트와 기본 메모리는 집니다. Widevine 이 없어 Netflix · Disney+ · Spotify 는 재생되지 않습니다. 설계 문서는 둘 다 적어 둡니다.
마우스를 쓰지 않습니다. page_map 이 페이지를 #7 button "Sign in" 같은 번호 목록으로 돌려주고, act 는 그 번호로 된 동작 배열을 한 번에 실행한 뒤 새 지도를 돌려줍니다. 스크린샷을 찍고 좌표를 고르는 왕복이 줄어듭니다. 지도는 90개, 한 번의 동작은 24단계에서 자르고, 자른 사실을 결과에 적습니다.
기본 경로는 사용자의 Claude Code, Codex 같은 CLI 에 일을 넘기는 방식이라, 모델 비용은 Mars 가 아니라 그 CLI 계정에서 나갑니다. Anthropic API 를 직접 쓰는 경로에는 프롬프트 캐싱과 출력 effort 제한을 넣었습니다. 설계 문서의 계산으로는 출력 토큰 단가가 입력의 다섯 배라, effort 가 가장 큰 비용 레버입니다.
macOS 에서 도는 로컬 빌드입니다. 설계 문서는 수요 증거가 없다는 사실을 첫머리에 적었습니다 — 유료 고객도, 무료 사용자도 아직 없습니다. 먼저 고칠 목록 13개 중 12개를 9월 9일에 반영했고, 캐시를 무효화할 수 있는 한 항목은 따로 측정하려고 보류했습니다.