Một công cụ tự động hóa được xây dựng trên Safari MCP đã đóng tab bảng điều khiển (dashboard) của nhà phát triển trong khi nó đang được đọc. Sự cố này đã làm lộ ra một lỗ hổng tiềm ẩn trong cơ chế bảo vệ (guard) vốn được thiết kế để ngăn chặn các tác nhân AI (AI-driven agents) chạm vào bất kỳ tab nào không thuộc quyền sở hữu của chúng, và nó cho thấy tại sao các danh mục "an toàn theo mặc định" (safe-by-default) có thể trở thành một rủi ro.
Cơ chế bảo vệ đã hoạt động—cho đến khi nó không còn như vậy nữa
Công cụ này gắn thẻ mọi tab mà nó tạo ra bằng một mã định danh nội bộ. Trước khi tác nhân thực hiện bất kỳ lệnh nào, cơ chế bảo vệ sẽ kiểm tra mã đánh dấu đó; nếu thiếu mã, cơ chế sẽ từ chối hành động. Trong thực tế, cơ chế bảo vệ đã ngăn tác nhân đọc một trang mà nó không mở—đúng như thiết kế ban đầu.
Trong khi đang điền một biểu mẫu, trang web đã chuyển hướng sang một tên miền khác. Việc chuyển hướng này đã làm mất mã đánh dấu, khiến tab không còn nhãn. Cơ chế bảo vệ nhận thấy mã đánh dấu bị thiếu và báo cáo: “Tôi không thể xác minh quyền sở hữu, vì vậy tôi sẽ không đọc tab này.” Tại thời điểm đó, bước kiểm tra an toàn đã hoạt động đúng như dự kiến.
Mã dọn dẹp đã vượt quá giới hạn
Tiếp theo là một quy trình dọn dẹp thủ công nhằm đóng các tab mồ côi (orphaned tabs)—những tab không có mã đánh dấu. Quy trình này yêu cầu công cụ “đóng một tab” mà không xác nhận quyền sở hữu trước đó. Vì cơ chế bảo vệ không thể chứng minh tab đó thuộc về nó, công cụ đã chuyển sang hành động mặc định: “đóng tab hiện tại”. Tab hiện tại chính là bảng điều khiển mà nhà phát triển đang đọc, chứ không phải là một tab mồ côi.
Kết quả là một thao tác mang tính hủy hoại đã được kích hoạt bởi một lộ trình an toàn lẽ ra phải là một ngõ cụt.
Ba lớp đã coi “không có quyền sở hữu” là sự cho phép
- Phân loại lệnh – Danh sách nhóm các lệnh đã đặt
close_tabvào một nhóm lớn gọi là “quản lý tab” (tab management). Nhà phát triển giả định rằng mọi thứ trong nhóm đó đều vô hại vì các lệnh khác (như “liệt kê các tab”) chỉ đọc thông tin. Không có ghi chú rõ ràng nào đánh dấuclose_tablà lệnh mang tính hủy hoại, vì vậy nó thừa hưởng mức độ an toàn cảm tính từ các lệnh lân cận. - Chính sách cấp tiện ích mở rộng – Tiện ích mở rộng Safari đóng vai trò trung gian cho tất cả các hành động của trình duyệt đã cho phép thực hiện bất kỳ thao tác nào khi phiên làm việc không sở hữu gì cả. Quy tắc đó hoạt động tốt đối với các hành động chỉ đọc, nhưng nó cũng mở cửa cho lệnh
close_tabthực thi mà không cần kiểm tra nguồn gốc (provenance check). - Sự không khớp về logic – Quy trình dọn dẹp đã kiểm tra cờ sở hữu trên một tab nhưng sau đó lại gọi hàm đóng trên tab mà trình duyệt báo cáo là “hiện tại”. Sự không khớp này đã khiến việc cơ chế bảo vệ không tìm thấy mã đánh dấu vô tình bỏ qua lệnh đóng và chuyển hướng nó đến sai mục tiêu.
Mỗi lớp đều giả định rằng “không ghi nhận quyền sở hữu” có nghĩa là “an toàn để hành động”, và cùng nhau, chúng đã tạo ra một lệnh đóng tab chạy mà không có bất kỳ bằng chứng hợp lệ nào.
Giải pháp: Bằng chứng sở hữu là bắt buộc đối với các hành động mang tính hủy hoại
Logic đã được sửa đổi để tách biệt các lộ trình chỉ đọc khỏi các lộ trình mang tính hủy hoại. Giờ đây, trước khi lệnh close_tab có thể thực thi, công cụ phải đưa ra một mã đánh dấu hợp lệ cho tab mục tiêu. Nếu thiếu mã đánh dấu, lệnh sẽ báo lỗi thay vì mặc định đóng tab hiện tại. Cơ chế bảo vệ không còn chuyển sang nhánh “làm gì đó” chung chung nữa.
Thay đổi này loại bỏ trạng thái mơ hồ khi một mã đánh dấu bị thiếu có thể được hiểu là “không có gì để làm” hoặc “cứ tiếp tục hành động”. Bằng cách buộc phải thất bại một cách rõ ràng, công cụ sẽ bảo vệ công việc của người dùng khỏi việc bị mất mát ngoài ý muốn.
Những điều nhà phát triển nên lưu ý
- Đừng để tên danh mục quyết định mức độ an toàn – Một nhãn như “quản lý tab” không nói lên điều gì về tác động của từng lệnh bên trong nó. Hãy ghi lại mức độ ảnh hưởng của mỗi thao tác (đọc so với hủy hoại) ngay cạnh chính lệnh đó.
- Các điều kiện bảo vệ phải tương xứng với mức độ nghiêm trọng của hành động – Một bước kiểm tra đủ cho yêu cầu đọc là không đủ cho một lệnh có thể xóa dữ liệu. Hãy xây dựng các quy trình xác thực riêng biệt cho từng loại mức độ ảnh hưởng.
- Tránh các phương án dự phòng ngầm định (implicit fallbacks) – Khi cơ chế bảo vệ không thể xác minh quyền sở hữu, phản ứng an toàn nhất là hủy bỏ, chứ không phải chọn một mục tiêu mặc định. Các hành động mặc định là nguồn gốc phổ biến của các lỗi leo thang đặc quyền (privilege-escalation bugs).
- Kiểm tra các giả định về sự liền kề – Hãy xem xét bất kỳ danh sách hoặc menu nào mà các lệnh nằm cạnh nhau. Một lệnh vô hại có thể thừa hưởng sự tin cậy dành cho các lệnh lân cận nếu mã nguồn không đánh giá lại mức độ an toàn một cách rõ ràng.
Bài học rút ra
Việc thiếu cơ chế bảo vệ quyền sở hữu không phải là một lỗi (bug); đó là một lỗ hổng trong thiết kế. Hãy coi mọi lệnh mang tính hủy hoại là một miền bảo mật riêng biệt đòi hỏi bằng chứng rõ ràng về thẩm quyền, và đừng bao giờ để trạng thái “không có mã đánh dấu” được diễn giải là “cứ tiếp tục”. Chỉ khi đó, các công cụ tự động hóa mới có thể bảo vệ chính những tab mà chúng được giao nhiệm vụ quản lý.
