Não desserializar dado não confiável; se precisar, assinar e verificar antes, usar formato só de dados e lista de permissão.
A defesa não é um truque, é uma ordem de prioridades.
Não desserialize dado não confiável com formatos que carregam tipos ou classes. Prefira um formato só de dados (JSON puro), que no máximo vira um registro, nunca uma classe escolhida pelo dado.
Se o dado precisa ir e voltar pelo cliente, assine e verifique ANTES de usar. Calcule um HMAC com chave secreta forte, compare em tempo constante, e se falhar, pare sem ler nenhum campo. Verificar depois de usar não adianta.
Trate o dado como dado. Ignore campos de tipo embutido (_type, __class__); aceite só uma lista de permissão de campos; escolha variantes por uma lista fixa no servidor, nunca indexando por valor do cliente.
Tire a decisão do dado. Papel e permissão vêm de um armazenamento no servidor, buscado por um identificador verificado, não de um campo do token.
A ordem que sustenta tudo é verificar antes de confiar: autenticar os bytes antes que eles virem um objeto em que você age. Em Python: nunca pickle.loads em dado externo; use json.loads e hmac.compare_digest antes de ler os campos.
Fluxo do conserto: verificar a assinatura primeiro, parar se falhar, e só então ler apenas os campos permitidos, com a decisão vindo do servidor.