3 điểm bởi GN⁺ 2024-11-22 | 1 bình luận | Chia sẻ qua WhatsApp
  • Cookie HTTP là cơ chế cơ bản để duy trì trạng thái trên web, nhưng trình duyệt·máy chủ·thư viện chuẩn khác nhau về ký tự được phép và cách xử lý lỗi, nên có thể dẫn tới sự cố thực tế
  • Họ RFC 6265 đặt ra điều kiện khác nhau giữa giá trị Set-Cookie do máy chủ gửi và giá trị mà trình duyệt chấp nhận, và các giá trị tạo bằng document.cookie có thể xung đột với giả định của bộ phân tích phía máy chủ
  • Firefox, Chromium và Safari khác nhau trong cách xử lý khoảng trắng, dấu ngoặc kép, dấu phẩy, dấu gạch chéo ngược và Unicode; Safari còn có hành vi chỉ lưu phần đầu thay vì bỏ toàn bộ cookie khi gặp ký tự bị cấm
  • Go có thể âm thầm bỏ qua cookie JSON mà trình duyệt chấp nhận, Python SimpleCookie có thể dừng tải các cookie phía sau một cookie mà nó không hiểu, còn PHP·Ruby·Rust cũng có phạm vi chấp nhận rất khác nhau
  • Chỉ một cookie Unicode cũng có thể gây lỗi 400/500 hoặc sự cố một phần trên các trang lớn như Facebook, Netflix, Okta, WhatsApp, AWS, Apple Support, nên đặc tả cookie và hành vi thư viện cần được căn chỉnh rõ ràng hơn

Cookie mà trình duyệt nhận nhưng Go không đọc được

  • Cookie là dữ liệu do JavaScript qua document.cookie hoặc máy chủ HTTP thiết lập, và sẽ tiếp tục được gửi kèm trong các yêu cầu HTTP phù hợp phạm vi cho đến khi hết hạn
  • Đoạn JavaScript ví dụ lưu nguyên chuỗi JSON làm giá trị cookie phiên
    • Giá trị có dạng {"ginger":"snap","peanutButter":"chocolate chip","snicker":"doodle"}
    • Khi đưa JSON vào cookie, nhiều nơi thường tuần tự hóa bằng base64, nhưng trình duyệt vẫn thiết lập giá trị này bình thường và gửi nó trong header Cookie
  • Vấn đề phát sinh khi cookie này được chuyển tới mã dùng thư viện chuẩn Go
    • Bộ phân tích của Go không thể diễn giải cookie đó
    • Sự thất bại lan truyền theo chuỗi lên các lớp cao hơn trong stack

Hai tiêu chuẩn trong RFC không khớp nhau

  • Cookie được định nghĩa qua RFC 2109, RFC 2965, RFC 6265, và hiện có bản dự thảo cập nhật
  • RFC xử lý giá trị cookie khác nhau ở hai khu vực
    • Section 4.1.1 loại trừ ký tự điều khiển, khoảng trắng, dấu ngoặc kép, dấu phẩy, dấu chấm phẩy, dấu gạch chéo ngược... khỏi giá trị mà máy chủ gửi bằng Set-Cookie
    • Section 5.6 lại cho phép trình duyệt chấp nhận rộng hơn nhiều khi phân tích chuỗi Set-Cookie, miễn là không có ký tự điều khiển
  • Xung đột cốt lõi là giá trị máy chủ được phép gửigiá trị trình duyệt phải chấp nhận không được căn chỉnh
    • Nếu trình duyệt chỉ nhận cookie do chính máy chủ thiết lập thì ảnh hưởng sẽ nhỏ, nhưng document.cookie cũng có thể tạo cookie
    • Tiêu chuẩn không nói rõ thư viện chuẩn xử lý header Cookie nên hào phóng như user agent hay nghiêm ngặt như máy chủ

Khác biệt giữa các trình duyệt về giá trị cookie được chấp nhận

  • Firefox

    • Kiểm tra giá trị cookie của Firefox cho phép một số ký tự mà RFC 6265 cấm
    • Các ký tự được cho phép dù RFC khuyến nghị loại trừ gồm:
      • 0x09 horizontal tab
      • 0x20 khoảng trắng
      • 0x22 dấu ngoặc kép
      • 0x2C dấu phẩy
      • 0x5C dấu gạch chéo ngược
    • Hành vi này được đưa vào trước đây để tương thích với Chrome và vẫn còn trong cả hai codebase
    • Thiết lập network.cookie.blockUnicode có thể từ chối các giá trị từ 0x80 trở lên, và công việc liên quan được theo dõi tại bug 1797231
    • Vấn đề cho phép 0x7F đã được sửa trong Firefox 108 tại bug 1797235
  • Chromium

    • Chromium chỉ từ chối ký tự điều khiển và dấu chấm phẩy trong giá trị cookie
    • Nó nghiêm hơn Firefox một chút vì không nhận 0x09 horizontal tab
    • Trái với RFC, nó vẫn chấp nhận và gửi lại khoảng trắng, dấu ngoặc kép, dấu phẩy, dấu gạch chéo ngược và ký tự Unicode
  • Safari / WebKit

    • Mã lưu cookie của Safari nằm trong CFNetwork mã nguồn đóng nên khó kiểm chứng trực tiếp
    • Khi thử thiết lập giá trị cookie từ 0x00 đến 0xFF bằng JavaScript, Safari cho phép các giá trị sau
      • 0x09 horizontal tab
      • 0x20 khoảng trắng
      • 0x22 dấu ngoặc kép
      • 0x5C dấu gạch chéo ngược
    • Safari không cho phép 0x7F delete và các ký tự high ASCII / Unicode 0x80-FF
    • RFC nói rằng khi gặp ký tự điều khiển thì phải bỏ qua toàn bộ cookie, nhưng Safari lại nhận phần giá trị trước điểm xuất hiện ký tự cấm
    • Cũng quan sát thấy lỗi Safari xóa khoảng trắng quanh dấu phẩy khi đặt giá trị -- , --

Khác biệt phân tích giữa ngôn ngữ và thư viện chuẩn

  • Go

    • Mã cookie của Go hoạt động khá gần với câu chữ RFC áp cho giá trị mà máy chủ gửi trong Set-Cookie
    • Nó cho phép khoảng trắng và dấu phẩy vốn khá phổ biến trong thực tế, nhưng không cho phép dấu ngoặc kép, dấu chấm phẩy và dấu gạch chéo ngược
    • Nếu header Cookie ví dụ chứa cookie JSON, kết quả request.Cookies() của Go chỉ còn cookie1=foocookie3=bar
    • cookie2 mà trình duyệt chấp nhận sẽ âm thầm biến mất mà không có ngoại lệ hay lỗi tường minh
  • PHP

    • PHP không có hàm phân tích cookie native nên khó khẳng định chính xác phạm vi cho phép, nhưng kết quả thử nghiệm cho thấy cách xử lý ký tự điều khiển không nhất quán
    • Các giá trị như 0x00-0x090x0D carriage return vẫn hoạt động
    • Nếu dùng 0x10 data link escape hoặc 0x7F delete thì PHP trả về lỗi 400 Bad Request
    • Cookie Unicode cũng xuất hiện trong đầu ra thử nghiệm
  • Python

    • http.cookies.SimpleCookie của Python khi gặp cookie JSON sẽ âm thầm dừng tải các cookie phía sau
    • Với đầu vào ví dụ, đầu ra chỉ còn cookie1=foo
    • Nếu một subdomain có thể đặt cookie lỗi cho domain gốc, chỉ một cookie như vậy cũng có thể làm hỏng toàn bộ xử lý cookie của site
    • Việc xử lý ký tự điều khiển cũng không đều
      • Một số ký tự điều khiển được tải với giá trị rỗng
      • Nếu thêm aa trước và sau giá trị thì cookie chứa ký tự điều khiển sẽ không được tải
  • Ruby

    • CGI::Cookie.parse của Ruby có vẻ cực kỳ hào phóng khi phân tích
    • Nó chấp nhận ký tự điều khiển, tab, dấu ngoặc kép, dấu phẩy, dấu gạch chéo ngược, 0x7F và ký tự Unicode, rồi áp dụng percent-encoding khi lấy ra từ cookie jar
    • Cách này có thể gần như tối ưu trong thế giới cookie, nhưng mã đặt cookie bằng document.cookie có thể không mong đợi giá trị phản chiếu đã được percent-encode
  • Rust

    • Rust không cung cấp xử lý cookie mặc định, nên việc kiểm tra dựa trên crate cookie phổ biến
    • cookie crate ở cấu hình mặc định có vẻ thuộc nhóm hào phóng nhất và dường như chấp nhận chuỗi UTF-8 được truyền vào

Ảnh hưởng bộc lộ trên các website thực tế

  • Vấn đề này được phát hiện khi kiểm chứng thủ công việc cập nhật thư viện bên thứ ba trên một site thử nghiệm
    • Đây là kiểu thay đổi khó bị bắt bởi kiểm thử tự động
    • Nếu được triển khai nguyên trạng, khách truy cập sau đó có thể nhận cookie hỏng và bị mắc kẹt với lỗi không rõ nguyên nhân cho tới khi rollback bản cập nhật và xóa cookie
  • Vấn đề này không chỉ giới hạn ở site nhỏ hay framework cụ thể nào
  • Nếu đặt cookie Unicode cho domain từ console trình duyệt như sau, nhiều site lớn có thể bị hỏng
    • document.cookie="unicodeCookie=🍪; domain=.grayduck.mn; Path=/; SameSite=Lax"
  • Các trường hợp được quan sát gồm
    • Facebook: hiện trang lỗi và hình ảnh cũng bị vỡ
    • Instagram và Threads: phát sinh lỗi 500 đơn giản
    • Netflix: trả về lỗi NSES-500 và cả trang trợ giúp cũng bị hỏng
    • Okta: mọi trang đăng nhập đều trả về lỗi 400
    • WhatsApp: hiển thị “whatsapp error”
    • Amazon: phần lớn vẫn hoạt động nhưng một số tính năng hỏng ngẫu nhiên
    • AWS: console đăng nhập trả về lỗi 400 và ngừng hoạt động
    • Apple Support: không thể tải danh sách thiết bị
    • Best Buy: điều hướng hoạt động nhưng tìm kiếm không chạy
    • eBay: phần lớn đã được sửa nhưng một số chỗ vẫn trả lỗi 400
    • Home Depot: dự kiến sẽ sửa
    • Intuit: site duy nhất xác định được nguyên nhân lỗi
    • Outlook: xuất hiện thêm một trường hợp lỗi 400

Khó khăn khi sửa giữa tiêu chuẩn và tính tương thích

  • Việc sửa một vấn đề trong đặc tả nền tảng đã 30 năm tuổi là cực kỳ khó, và có thể không tồn tại lời giải tốt cho vấn đề này
  • Cả Mozilla và Google đều đã xem xét và làm việc theo hướng chặn các cookie kiểu này ở phía trình duyệt
  • Việc chặn một chiều rất phức tạp vì vấn đề tương thích
    • Cookie không phải ASCII chiếm dưới 0.01% tổng số cookie nên không phổ biến
    • Telemetry cho thấy chúng xuất hiện thường xuyên hơn nhiều ở các nước như Argentina, Mexico và Finland
    • Mozilla đã triển khai thiết lập network.cookie.blockUnicode có thể bật nhanh, nhưng chưa kích hoạt vì vấn đề tương thích hành vi với Chromium
  • Sửa ở phía máy chủ cũng có thể khả thi, nhưng phạm vi trải dài qua hàng triệu website cùng lỗi xử lý nội bộ của nhiều ngôn ngữ và framework
    • Những nơi như Facebook hay Netflix có thể giảm thiểu được, nhưng người vận hành một site trung bình khó có đủ thời gian hoặc năng lực để xử lý
  • Giải pháp gốc rễ là IETF HTTP Working Group phải căn chỉnh lại đặc tả cookie từ bên trong và quy định chặt chẽ cách hệ thống xử lý cookie phải hoạt động
    • Việc cho phép hay không cho phép ký tự không phải ASCII phải giống nhau giữa phía máy chủ và user agent
    • Các bước mà trình duyệt, ngôn ngữ và framework xử lý cookie cũng phải được mô tả tường minh như các tiêu chuẩn W3C hiện đại như Content Security Policy
    • Việc chỉ một cookie lỗi có thể khiến xử lý các cookie khác cũng dừng theo là hành vi khó chấp nhận vì dễ dẫn tới nhiều sự cố bất ngờ

Quy trình xử lý cookie được đề xuất

  • Bắt đầu từ field-value, tách theo ;, để tạo danh sách raw-cookie-pair, nhưng không coi dấu phẩy là từ đồng nghĩa của dấu chấm phẩy
  • Mỗi raw-cookie-pair được xử lý theo thứ tự sau
    • Nếu không có = thì chuyển sang pair tiếp theo
    • Xóa khoảng trắng ở đầu và cuối
    • Phần trước dấu = đầu tiên được xem là cookie-name-octets, phần sau là cookie-value-octets
    • Nếu giá trị bắt đầu bằng dấu ngoặc kép thì bỏ một dấu ngoặc kép mở đầu, và nếu có dấu ngoặc kép kết thúc thì bỏ một dấu đó
    • Nếu tên hoặc giá trị ở dạng máy chủ không thể chấp nhận thì bỏ qua pair đó
    • Bộ đôi [cookie-name-octets, cookie-value-octets] còn lại được xử lý theo cách do máy chủ định nghĩa
  • Đề xuất thêm là máy chủ từ chối các bộ đôi có tên cookie không phải token, và từ chối giá trị cookie nếu chứa octet không nằm trong cookie-octet

1 bình luận

 
GN⁺ 2024-11-22
Ý kiến trên Hacker News
  • Cookie đầy những cái bẫy kỳ quặc và hành vi bất tiện, nhưng 99,95% thời gian thì vẫn chạy ổn. Bãi mìn cookie mà tôi thích nhất là cookie shadowing, khi bạn đặt cookie cùng tên nhưng chỉ khác các thuộc tính chính như domain, path, thì nhiều cookie gần như giống nhau sẽ tồn tại đồng thời, và backend hay JS không có cách nào phân biệt cái nào là cái nào
    Hãy vào https://example.com/somepath rồi nhập các dòng dưới đây trong console của trình duyệt
    document.cookie = "foo=a";
    document.cookie = "foo=b; domain=.example.com";
    document.cookie = "foo=c; path=/somepath";
    document.cookie
    Trong trường hợp của tôi, kết quả là 'foo=c; foo=a; foo=b'

    • Không biết ở công ty ai đã thiết kế như vậy, nhưng họ đặt môi trường staging và development trên cùng một domain, và cả một công ty khổng lồ đang đi theo mẫu này
      Đúng là một sai lầm cực lớn
    • Tôi nghĩ khá nhiều hành vi kỳ lạ xảy ra khi dùng nhiều tài khoản trên một website trong cùng một trình duyệt có thể được giải thích bằng chuyện này
    • Nếu đang ở /somepath, việc nhận C, giá trị cụ thể nhất trong ba giá trị, trông khá hợp lý. Vì mọi giá trị đều được trả về theo thứ tự, bạn có thể biết cả giá trị theo từng path lẫn giá trị toàn cục, nên cảm giác đây là thỏa hiệp tốt nhất
      Dù vậy, tôi không thích setter document.cookie đầy tính ma thuật đó, nhưng nó đã gần 30 năm tuổi rồi nên cũng đành chịu
    • Nhân tiện, về mặt kỹ thuật dấu chấm ở đầu domain không được phép và sẽ bị bỏ qua: https://www.rfc-editor.org/rfc/rfc6265#section-4.1.2.3
      Vấn đề này gần đây lại nổi lên khi jshttp/cookie siết chặt kiểm tra hợp lệ: https://github.com/jshttp/cookie/pull/167
      Sau PR đó, phần kiểm tra hợp lệ lại được nới lỏng đôi chút, tương tự đoạn mã trình duyệt được nhắc trong bài
      Thay đổi ban đầu bắt nguồn từ việc chúng tôi tìm thấy một lỗi trong mã của mình: tạo header cookie bằng cách nối chuỗi mà không mã hóa. Thỉnh thoảng giá trị có khoảng trắng làm hỏng request, và để tránh chuyện này, chúng tôi định khuyên các developer dùng serialize() của jshttp/cookie, nhưng rồi nhận ra phần kiểm tra hợp lệ của hàm đó không đủ để bắt lỗi mà chúng tôi đã thấy
      Khi đề xuất bản sửa, một người khác phát hiện phần kiểm tra quá lỏng, đến mức có thể nhét JS vào trường tên của cookie, rồi khiến nơi khác diễn giải nó như giá trị. Nó trở thành một đường chèn mã khá đặc biệt
    • Đúng vậy, thật sự có rất nhiều yếu tố nguy hiểm. https://www.usenix.org/conference/usenixsecurity15/technical-sessions/presentation/zheng trình bày chi tiết vấn đề này và các rắc rối liên quan
  • Bài viết có nhắc đến cách tiếp cận của Rust, nhưng khác với các ngôn ngữ khác, thư viện chuẩn của Rust không có chức năng xử lý cookie. Thực ra là đang nhìn vào hành vi của crate cookie bên thứ ba, và nó cũng có tùy chọn percent-encoding giống Ruby: https://docs.rs/cookie/0.18.1/cookie/

    • Đây là kiểu chiếm được một cái tên đẹp từ sớm rồi trở thành chuẩn trên thực tế
  • Trong giao thức HTTP dường như thực chất có khoảng mười nghìn giao thức khác nhau nhét bên trong. Trình duyệt và web server đã gắn thêm đủ loại tính năng, mỗi thứ lại có đặc tả và cả đặc tả trên thực tế, và tất cả gần như đều được truyền dưới chiếc ô chung gọi là HTTP
    Client không thể chỉ định mình tương thích với phiên bản nào trong số mười nghìn thứ phi-đặc-tả đó, server cũng vậy. Lý do không thể nâng cấp đặc tả là các client còn lại sẽ không hiểu, và cũng không có tương thích ngược
    Vì thế thứ còn lại là một mớ hỗn độn ngẫu nhiên mà không ai đồng thuận được và cũng không sửa được. Không có kế hoạch loại bỏ dần, nên ta phải tiếp tục mang theo những quyết định tệ hại trong quá khứ

    • Một nguyên nhân nữa là các thiết bị middleware tệ hại chặn luôn những giao thức mà chúng không hiểu. Kiểu như “mặc định chặn cho thất bại thì an toàn hơn”, nên từ giờ đến mãi mãi mọi lưu lượng ứng dụng mới muốn hoạt động trên Internet thực tế đều phải tunnel qua HTTP
    • Thành thật mà nói, giờ tôi đã làm hòa với thế giới như vậy rồi, và cũng không chắc tôi thích một thế giới có kế hoạch loại bỏ dần hơn
    • Nếu không muốn một công ty độc quyền đặt ra đặc tả gọn gàng rồi tùy tiện cưỡng ép khai tử, thì cái giá phải trả là chấp nhận tình trạng vô chính phủ
  • Trong một dự án khoảng 10 năm trước, tôi triển khai session dựa trên cookie, và đã thật sự khổ sở khi debug vì sao xác thực chạy trên Safari nhưng không chạy trên Chrome. Tôi không nhớ chính xác là bên nào, nhưng một trình duyệt sẽ không đặt cookie nếu định dạng không đúng
    Tôi cũng không làm gì đặc biệt kỳ lạ; theo trí nhớ thì hình như là khác biệt giữa -_

    • Tôi nhớ là giữa Safari và Chrome có khác biệt về phân biệt hoa thường. Có lẽ là ở header Set-Cookie
      Trước đây vì vấn đề này mà tôi từng không thể dùng camelCase cho key cookie
      Tìm kiếm cũng không thấy chính xác issue đó
  • Có vẻ từ ngay sau khi cookie được đưa vào, cách dùng hợp lý đã được coi là chỉ đặt token mờ để server nhận ra lần sau đây là cùng client, còn mọi thứ khác thì lưu hết phía server
    Tôi không hiểu vì sao việc client về nguyên tắc có thể xử lý những giá trị mà server tuyệt đối không bao giờ gửi lại là một vấn đề. Chỉ cần đừng gửi những giá trị như vậy, và không cần lo các câu đố kiểu “nếu gửi cái đó thì chuyện gì sẽ xảy ra?”

    • Cookie là công nghệ lâu đời. Nó là một trong những thứ được đưa vào sớm nhất trong thập niên 90 khi web còn non trẻ, và vài ý tưởng tệ đã được lặp lại qua nhiều lần
      Dù vậy, vì đây là nơi duy nhất để lưu token mờ nên vẫn phải dùng cho xác thực
  • Phân tích cú pháp header cookie là một mớ hỗn độn. “Tiêu chuẩn” không phản ánh được những hành vi tồn tại ngoài thực tế; mỗi backend server, thư viện, framework lại chấp nhận các định dạng khác nhau, còn trình duyệt thì làm một kiểu khác nữa.
    Nếu bạn kiểm soát hoàn toàn cả frontend lẫn backend thì không phải vấn đề lớn, nhưng ngay khi phải tích hợp các thứ khác nhau, tình hình sẽ rất nhanh trở nên ngớ ngẩn.

  • Cookie trông như một mớ hỗn độn lớn và phức tạp, đồng thời gần như không thể thay đổi vì tương thích ngược. Trong trường hợp này, có lẽ nên tạo một cơ chế mới hoàn toàn tách biệt.
    Ví dụ có thể đặc tả một cơ chế mới kiểu NewCookie và thiết kế lại từ đầu để nó hoạt động nhất quán. Có thể tích hợp sẵn các biện pháp bảo mật hiện đại, đặc tả chặt chẽ hơn và hỗ trợ Unicode đúng cách.

    • Việc nhắc đến NewCookie khá thú vị, vì trên thực tế đã từng có header Set-Cookie2 nhưng đã bị loại bỏ: https://stackoverflow.com/q/9462180/3474615
    • NewCookie đại khái tương ứng với Local Storage của trình duyệt.
      Ít nhất là trong một số use case, và tất nhiên nó không tích hợp trực tiếp với header.
    • Vấn đề cốt lõi có vẻ là cookie gắn quá sâu với theo dõi. Nếu bây giờ cố tạo ra cookie tốt hơn, rất có thể sẽ bị các nhà vận động quyền riêng tư, những người không muốn chính khái niệm đó tồn tại, chặn lại.
      Vì cookie đã tồn tại nên chúng ta bị ràng buộc với cookie.
    • Nơi an toàn nhất để lưu trạng thái phía client là DOM và URL. Không bao phủ được mọi use case, nhưng có thể xử lý những vùng như liên kết phê duyệt trước trong email.
      Tôi đã mất trọn một tháng để truy tìm vấn đề iOS Safari tùy tiện nuốt cookie trên các domain do khách hàng kiểm soát. Tôi chưa từng thấy trạng thái phiên biến mất kiểu này trên các domain như Google, Twitter hay Facebook.
    • Cái tên nên hay hơn NewCookie. Có thể đề xuất các tên như SuperCookie, UltraCookie, BetterCookie.
      Nói nghiêm túc hơn một chút, tốt nhất nên tránh từ cookie và đặt hẳn một cái tên khác. Từ cookie mang theo quá nhiều gánh nặng.
  • Bài viết bắt đầu từ việc tác giả đưa kết quả JSON.stringify vào cookie, nhưng điều đáng ngạc nhiên là không phải vì ai đó đã đưa dấu chấm phẩy vào JSON được stringify.
    Hầu hết rắc rối quanh cookie dường như phát sinh khi cố đưa input tùy ý của người dùng vào cookie. Không nên làm vậy. Nếu chỉ dùng chuỗi ASCII chữ-số có độ dài cố định như khi dùng cho token xác thực thì ổn.

  • Đồng ý rằng đây đúng là một bãi mìn.
    Với tư cách lập trình viên, cách đi đường vòng là mã hóa giá trị bằng Base64 an toàn cho URL. Khi đó bạn nhận được giá trị byte thô và có thể dùng biểu diễn nội bộ tùy ý. Tuy nhiên, như bài viết cũng nói, bạn không thể kiểm soát 100%. Vì đó là user agent, và cũng nên như vậy.
    Mong rằng nhiều user agent hơn sẽ chọn tuân thủ tiêu chuẩn thay vì “byte trên dây và cầu nguyện”. Các phản hồi 400 trong ảnh chụp màn hình là phản hồi đúng theo đặc tả. Có lẽ sẽ tốt hơn nếu header ngay từ đầu đã là UTF-8, hoặc ban đầu là ASCII rồi sau đó cho phép UTF-8. Tuy nhiên trường hợp đầu khó về mặt nhân quả, còn trường hợp sau vẫn có thể gây vấn đề vì biến những giá trị vốn bất hợp pháp thành hợp pháp.

    • Khi nói Base64 an toàn cho URL, nhất thiết phải nói rõ chính xác là gì. Mã hóa base64url không tương thích với base64 cộng thêm URL encoding trong khoảng 3% trường hợp; lúc phát triển rất dễ bỏ sót, nhưng lên production chắc chắn sẽ nổ.
    • Giá trị cookie có thể chứa các ký tự =, /, +, nên cũng có thể dùng mã hóa Base64 tiêu chuẩn :)
  • Bài viết chế giễu định luật Postel, nhưng nếu bên đặt cookie đã bảo thủ khi gửi thì ngay từ đầu đã không cần bài viết này.

    • Đáng bị chế giễu. Định luật Postel là một ý tưởng khủng khiếp và đã tạo ra bãi mìn ở khắp nơi.
      Đôi khi quả mìn đó không chỉ là bug đơn giản mà còn trở thành lỗ hổng bảo mật lớn.
      Nếu client gửi dữ liệu không đúng đặc tả thì đó là bug và cần được sửa. Việc server đoán ý định rồi chấp nhận tuyệt đối không nên trở thành điều hiển nhiên.
    • Vấn đề của định luật Postel chính là bên gửi tuyệt đối không bao giờ bảo thủ. Những hành vi chi tiết mà đa số bên nhận chấp nhận cuối cùng sẽ được bên gửi tận dụng.