Segurança em qub

Data de entrada em vigor: 23 de setembro de 2026 Versão: 1.1 — revisão da precisão da implementação


Para investigadores — referência rápida:

Todos os detalhes estão no §12 (Divulgação Coordenada).


Quem somos

qub.social é operado por VSPRY AUSTRALIA PTY LIMITED (ABN 41 631 026 330), Level 38, 71 Eagle Street, Brisbane QLD 4000, Australia. As referências a "qub", "nós", "nos" e "nosso" referem-se a essa entidade.

Contacto de segurança: support@qub.social com o prefixo de assunto [SECURITY].


1. Nossa abordagem

qub é infraestrutura de confiança. O produto não vale nada se não for seguro, então segurança não é um recurso — é o substrato. Esta página descreve, em termos concretos, como protegemos nossa stack, seus dados e a integridade do conteúdo selado.

O valor de um compromisso temporal verificável aumenta à medida que mais da internet se torna gerada por máquinas. Uma transação de armazenamento verificada ou um âncora de registo de transparência pode estabelecer que o texto cifrado existia não mais tarde do que o seu tempo de bloco; o artefacto selado prova separadamente a integridade do conteúdo, a ligação à ronda do drand e quaisquer assinaturas de autoria. Manter essas alegações distintas é o padrão ao qual esta página se mantém.

Não pedimos que você confie em nós. Projetamos para que a confiança exigida de nós seja a menor possível e, onde a confiança é exigida, explicamos exatamente o que está a ser confiado e por quê.

Três princípios orientam cada decisão de design:


2. Modelo de ameaças

2.1 Contra o que protegemos

2.2 Contra o que não podemos proteger

Somos honestos sobre nossos limites. qub não pode defender contra:


3. Criptografia do lado do cliente

No fluxo de mensagens do navegador padrão, a encriptação do conteúdo ocorre antes do pedido de upload. Dois caminhos explícitos diferem: Builder /api/v1/seal envia deliberadamente texto simples e K gerado pelo chamador ao Trabalhador para selagem em memória, e o encenamento/assinatura do pacto envia o pacto estruturado assinado ao serviço para que este possa finalizar o artefacto bilateral. Nenhuma das exceções deve ser confundida com encriptação de ponta a ponta pelo caminho do navegador.

3.1 Cifragem timelock

qub usa tlock — cifragem baseada em identidade indexada a um round drand futuro. A cifragem ocorre no seu navegador usando a chave pública da rede drand; a chave de decifragem é liberada publicamente pela rede drand somente quando o round alvo é alcançado. Ninguém, incluindo nós, pode reconstruir a chave de decifragem antecipadamente.

Visamos a cadeia quicknet:

A chave pública e o tempo de gênese da cadeia quicknet são compilados no cliente. Não obtemos parâmetros da cadeia em tempo de execução, então um nó malicioso não pode substituir uma cadeia que controlamos.

3.2 Cifragem simétrica

O esquema tlock envolve uma chave de conteúdo AES-256-GCM. AES-GCM fornece cifragem autenticada: um único bit invertido no ciphertext faz a decifragem falhar, em vez de produzir texto plano silenciosamente corrompido.

3.3 Serialização canónica

As estruturas de protocolo são serializadas utilizando CBOR determinístico (RFC 8949 §4.2 codificação determinística principal). Duas implementações que codificam a mesma estrutura lógica produzem CBOR idêntico. Os conteúdos selados completos são não determinístico: tlock e encriptação de outer-wrapper usam aleatoriedade nova. O hash do corpo é calculado sobre os bytes crus do corpo, enquanto a codificação canónica torna as estruturas circundantes assinadas/de rede inequívocas.

Escrevemos o codificador CBOR à mão para nossas implementações de cliente e servidor em vez de depender de uma biblioteca de serialização genérica — o requisito é exatidão, não ergonomia, e testes de propriedade rodam em ambas as implementações para verificar que concordam.

Um teste de regressão afirma que o formato de transmissão canónico não contém nenhuma sequência de bytes da marca qub além da chave de campo qub_id primitiva do protocolo. O formato de transmissão é intencionalmente agnóstico de marca — qualquer leitor conforme (o nosso ou de terceiros) pode renderizar qualquer qub do armazenamento permanente, independentemente de qual deployment o selou. O teste é uma armadilha que evita que uma mudança futura incorpore acidentalmente uma referência de marca em bytes que, uma vez no armazenamento permanente, não podem ser reescritos.

3.4 Hashing do body e integridade pré-revelação

Cada carga útil selada transporta um hash SHA3-256 dos seus bytes de corpo brutos. O hash está vinculado a qub_id e, quando a assinatura de autoria está ativada, na entrada da assinatura V2. Um visualizador recalcúla-a após a descriptação e rejeita uma discrepância.

O identificador de conteúdo de 32 bytes qub_id é derivado de uma pré-imagem de 108 bytes cobrindo a versão do protocolo, tipo de conteúdo, timestamps de criação e desbloqueio, timestamp de resultado opcional (ou o seu sentinela zero), ronda drand alvo, hash do corpo, e SHA3-256 do título opcional normalizado em NFC. Um gateway ou CDN não pode alterar qualquer campo vinculado de forma consistente e ainda assim passar na re-derivação. Os títulos são limitados a 100 pontos de código NFC e rejeitados para a classe partilhada de pontos de código hostis/de controlo (incluindo sobreposições bidi, caracteres de largura zero, o bloco de tags, BOM, C0, C1 e DEL).

3.5 Assinatura (ML-DSA-65)

A assinatura de autoria usa ML-DSA-65 (FIPS 204), um esquema de assinatura pós-quântico padronizado pelo NIST. Escolhemos deliberadamente uma primitiva pós-quântica para assinatura porque o conteúdo selado é permanente: uma assinatura que verifica hoje deve ainda verificar décadas a partir de agora, incluindo após computadores quânticos em larga escala se tornarem práticos.

As chaves de assinatura são geradas no navegador. O segredo local é encapsulado sob uma chave WebCrypto não extraível antes de ser armazenado no IndexedDB. Se a funcionalidade de recuperação entre dispositivos com escopo de conta for utilizada, um blob de chave portátil encriptado com AEAD é armazenado no servidor; o seu texto cifrado da chave secreta está associado ao ID de conta imutável, e o serviço valida o envelope público, mas não consegue decifrar o material secreto. Os bytes da chave privada bruta não são enviados para o servidor. As chaves públicas e os registos de atestação são armazenados para verificação e exibição de identidade.

A mesma decifragem tlock no navegador aplica-se dentro do embed do qub: quando um qub selado é renderizado através de <qub-embed> numa página de terceiros, a decifragem ainda acontece no iframe do embed no navegador do leitor. O embed não muda o modelo de confiança — texto plano nunca é decifrado num servidor do qub.

3.6 Atribuição pública — Opcional

Os qubs selados não carregam nenhum ponteiro on-chain ao seu criador a menos que o criador escolha explicitamente anexar um. Quando você sela um qub, o app de referência emite uma tag de armazenamento Author (um fingerprint hex de 64 caracteres da sua chave pública de assinatura) somente quando "Atribuição pública" está ativada no passo do seletor de data. Com o toggle desativado — a predefinição — nenhuma tag Author é gravada e o qub fica não atribuído no armazenamento permanente: nada no armazenamento vincula o upload ao seu handle, ao seu e-mail ou aos seus outros qubs. Com o toggle ativado, o fingerprint resolve para o seu @handle via a cadeia de atestação em §6.3 / §10 e a contagem decrescente do leitor mostra "Selado por @{handle}" antes da revelação.

Esta é uma proteção deliberada contra o risco de enumeração que uma tag Author sempre ativa criaria: um terceiro que aprende o fingerprint de um criador poderia, de outra forma, varrer o armazenamento permanente pela tag e reconstruir a saída histórica completa daquele criador. A atribuição opcional fecha esse canal — apenas os qubs que o criador escolhe explicitamente atribuir aparecem sob um fingerprint no armazenamento permanente.

A página de perfil /u/{handle} é um cartão de identidade verificada — handle, nome para exibição opcional + URL, pílula de "e-mail verificado" (sem endereço), e a forma curta do fingerprint criptográfico. Não lista os qubs de um criador. Visitantes que querem ver um qub específico de um criador seguem a URL de entrega daquele qub diretamente.

3.7 Invólucro externo de cifragem

Mesmo depois de a descodificação com bloqueio temporal ser matematicamente possível — uma vez que a assinatura drand para a ronda vinculada tenha sido publicada — a camada canónica de bloqueio temporal sozinha permitiria a um indexador descodificar em massa os qubs descobráveis. A entrega privada fecha esse canal com uma camada simétrica adicional em torno dos bytes codificados com bloqueio temporal (Protocolo §13). A entrega pública omite intencionalmente o invólucro para que a notificação, incorporação e os links de descoberta possam funcionar sem um fragmento secreto.

O invólucro usa AES-256-GCM, uma cifra autenticada padronizada pelo NIST, com uma chave K nova de 256 bits gerada por qub pelo CSPRNG do seu navegador. K está vinculado ao qub_id do qub como dado adicional autenticado, então uma chave de um qub não pode ser reutilizada para decifrar um qub diferente.

K nunca chega aos nossos servidores no fluxo de navegador privado padrão. Está codificado no fragmento de URL do link de partilha (https://qub.social/c/<tx_id>#<base64url(K)>). Os navegadores não transmitem fragmentos de URL para os servidores—o RFC 3986 coloca o fragmento fora do pedido—portanto, qub.social, gateways de armazenamento, CDNs e monitorização de pedidos não conseguem ver K nesse fluxo. O armazenado OuterWrapper é CBOR estruturado reconhecível, mas o seu campo de texto cifrado autenticado esconde o interior SealedQub estrutura e não pode ser aberta sem K.

Consequências líquidas:

O endpoint do lado do servidor /api/v1/seal do Worker (usado por agentes de IA e outros chamadores de API) exige que o chamador gere K com um CSPRNG, a retenha localmente e a forneça como wrapper_key_b64url. O Worker vê necessariamente tanto o texto plano como K em memória neste caminho explicitamente confiável, mas não persiste nenhum dos dois. Um Idempotency-Key obrigatório impede que uma resposta perdida crie um segundo qub faturado, enquanto o K retido pelo chamador pode ser combinado com a URL sem fragmento repetida. Isto difere do caminho de navegador padrão, em que K nunca chega ao Worker a menos que o criador ative explicitamente a recuperação.


4. Transporte e edge

4.1 TLS

O tráfego do navegador para o qub é servido via HTTPS na interface da Cloudflare. As respostas definem o HTTP Strict Transport Security (max-age=63072000; includeSubDomains; preload). A versão exacta de TLS negociada e o conjunto de cifras são governados pela configuração activa da borda, em vez de serem definidos pelo código da aplicação. Não expomos um servidor de origem acessível separadamente.

4.2 Segurança de conteúdo

O cliente compilado é servido com cabeçalhos estritos de content-type e cache. O shell do SPA é uma origem única. Não embutimos scripts de terceiros para analytics ou publicidade. Os dois pontos de contacto com terceiros no produto são ambos estritamente delimitados: o fluxo de compra deixa o SPA inteiramente com um redirecionamento de página inteira para o checkout alojado pelo Stripe (https://checkout.stripe.com/…) — a UI do Stripe nunca executa na nossa origem e nunca vemos dados de cartão — e o fluxo de selo carrega o widget Turnstile do Cloudflare, uma alternativa de CAPTCHA respeitosa com a privacidade que o Cloudflare renderiza dentro do seu próprio iframe sandboxed. Nenhuma das partes pode ler o resto da página.

O qub inserir iframe (servido a partir de qub.social/embed/{tx_id} e carregado em sites de terceiros por embed.js) possui a sua própria Política de Segurança de Conteúdo. A sua connect-src lista de permissões é 'self', https://qub.social, https://arweave.net, https://ar-io.dev, https://permagate.io, https://api.drand.sh, e https://drand.cloudflare.com. O iframe funciona com sandbox="allow-scripts allow-top-navigation-by-user-activation" (não allow-same-origin): a página anfitriã não pode ler o seu DOM, e não pode navegar pela anfitriã exceto após uma ação do utilizador.

4.3 CORS e âmbito de fetch

O cliente do navegador faz pedidos fetch apenas para:

Os destinos do embed são aplicados pelo seu CSP. Os destinos pretendidos da SPA principal estão fixos no código e na configuração e são verificados pelo navegador e pelos testes de integração; a Integridade de Subrecursos não é um controlo de destino de rede.

O embed busca bytes armazenados através das origens qub/storage na lista de permissões, desembrulha cargas úteis privadas no navegador usando K a partir do fragmento da sua URL, e busca assinaturas de rondas em tempo de revelação das duas origens drand na lista de permissões. O SPA principal usa o conjunto de fallback de quatro endpoints definido em config/drand-endpoints.json (drand.cloudflare.com, api.drand.sh, api2.drand.sh, e api3.drand.sh) para que uma falha de um endpoint não bloqueie a revelação. O CSP incorporado nega conexões fora da sua lista explícita.


5. Infraestrutura do lado do servidor

5.1 Edge serverless

Nossa API roda inteiramente num runtime serverless gerido no edge. Não há VMs, nem containers, nem processos de servidor persistentes que administremos. Isto reduz drasticamente a superfície de ataque pela qual somos responsáveis: não rodamos um SO, um servidor web, ou um runtime de aplicação que devamos atualizar.

Aplica-se um middleware público-CORS separado Access-Control-Allow-Origin: * para o seguinte conjunto de caminhos implementados: /embed.js, /embed/v1.js, tudo abaixo /embed/; /api/v1/telemetry; /api/v1/openapi.json; tudo abaixo /api/v1/qub/ (incluindo bytes, metadados, prova, envolvimento, notificação e subrotas de envio); tudo debaixo de /api/v1/log/; pesquisas de identificadores públicos sob /api/v1/handle/; e o avatar público lê por baixo /api/v1/identity/avatar/. As suas autorizações de pré-voo GET, POST, e OPTIONS com o Content-Type cabeçalho de pedido. Esta superfície baseada em prefixo é mais ampla do que apenas as chamadas que a incorporação faz atualmente, por isso cada manipulador abaixo desses prefixos deve continuar a aplicar a sua própria validação, autenticação, limites de taxa e controlos de abuso. Outros caminhos de API mantêm a política CORS qub.social-restricted.

5.2 Armazenamento

O fluxo de mensagens do navegador por defeito não mantém texto simples na infraestrutura qub. Construtor /api/v1/seal manipula texto simples e K na memória, mas não persiste nenhum dos dois. O staging do Pact armazena necessariamente o pact estruturado assinado até que seja co-assinado, retirado ou expirado. A recuperação opcional armazena uma capacidade de entrega (o link completo com fragmento) para que possa ser recuperada mais tarde. Portanto, não descrevemos todo o nível de armazenamento como “apenas metadados.”

5.3 Segredos

Segredos (carteiras de assinatura, tokens de fornecedor e chaves HMAC) são fornecidos através de ligações de segredos/ambiente da plataforma em vez de controlo de código-fonte. Os componentes em execução recebem apenas as ligações de que precisam. Os procedimentos de rotação e sobreposição são específicos de cada componente; não afirmamos a existência de um único mecanismo universal de rotação automática ou auditada.

5.4 Logging e telemetria

Logs JSON estruturados são gravados em cada pedido da API com um ID de correlação exposto no cabeçalho de resposta X-Request-Id. A telemetria do cliente é anónima — sem identificador de dispositivo, sem endereço IP, sem prévia de conteúdo. Os eventos são bufferizados em memória e despejados na base de melhor esforço; um despejo falhado é descartado, não tentado novamente. A telemetria é projetada para ser desativável na camada de rede sem afetar o produto.


6. Autenticação

6.1 Login por magic-link

O início de sessão utiliza um token de uso único, assinado com HMAC, enviado para a sua caixa de correio eletrónico. O link é válido durante 15 minutos e o resgate é reclamado de forma atómica, de modo que o uso em simultâneo ou repetido falha de forma segura. Em caso de sucesso, o navegador recebe um opaco __Host-qub_session biscoito com Secure, HttpOnly, SameSite=Strict, e Path=/ atributos.

As sessões têm um limite de inatividade de 30 dias e um limite absoluto de 90 dias, rotacionam após 24 horas e aceitam apenas a geração imediatamente anterior durante um período de tolerância de 120 segundos para respostas perdidas. As alterações sensíveis da conta requerem autenticação nos 10 minutos precedentes. O segredo de assinatura HMAC é uma ligação à plataforma; uma leitura apenas de metadados não cria por si só um token válido.

6.2 Chaves de API (plano Developer)

As chaves de API do desenvolvedor usam o prefixo qub_sk_ para fácil reconhecimento e grepabilidade. Cada chave:

Os endpoints de gestão de chaves admin estão protegidos atrás de uma credencial admin separada.

6.3 Atestação de e-mail (assinatura de autoria)

Vincular um endereço de e-mail a uma chave de assinatura exige:

  1. Posse da chave de assinatura privada (você assina um desafio)
  2. Posse da caixa de entrada de e-mail (você insere um código de 6 dígitos entregue por e-mail)

Qualquer um sozinho é insuficiente. A revogação é um registo assinado na sua própria conta e tem efeito imediato; os leitores que consultam a atestação veem o estado revogado e exibem em conformidade.


7. Pagamentos

A introdução e o processamento de cartões são realizados no checkout hospedado pela Stripe. Nunca recebemos números de cartão, datas de validade ou CVCs. Armazenamos, no entanto, identificadores de clientes e subscrições da Stripe, estado da subscrição e dados de período em registos de direitos/chave API para que o acesso, renovações, medição, cancelamento e reembolsos possam ser conciliados. As declarações de privacidade e segurança da Stripe regem a forma como ela trata os dados de pagamento.

O endpoint de selo verifica de forma cruzada o registo de direitos contra o identificador de dispositivo e, para utilizadores autenticados, contra a identidade vinculada. Um direito não pode ser reutilizado entre dispositivos sem o utilizador explicitamente restaurá-lo via login por magic-link.


8. Resistência a abuso

8.1 Deteção de bots

O fluxo de selo é protegido por uma alternativa de CAPTCHA respeitosa com a privacidade que não usa cookies para rastreamento e não faz fingerprint para publicidade. Um desafio falhado é rejeitado pelo nosso edge Worker antes que qualquer processamento do lado do selo aconteça.

8.2 Rate limiting

Os rate limits são aplicados em várias camadas:

Contadores e reivindicações atómicas são distribuídos pelo KV, Objetos Duráveis e ligações de limitação de taxa da plataforma de acordo com os requisitos de consistência do endpoint. As requisições com limite de taxa devolvem 429; os endpoints que podem calcular uma janela de nova tentativa incluem Retry-After.

8.3 Moderação de conteúdo

A rota de upload do navegador por defeito não consegue analisar o corpo: recebe apenas o artefacto selado pelo cliente. O Construtor /api/v1/seal o percurso vê o texto simples de forma transitória, e a preparação do pacto mantém os termos estruturados até à finalização, mas essas exceções de confiança não transformam o caminho de carregamento geralmente cego a bytes num scanner de conteúdo. A moderação operacional é uma lista de negação no nível do visualizador: um qub na lista de negações é recusado pelo nosso visualizador independentemente de o payload armazenado continuar acessível. Colocar na lista de negações não retira bytes duráveis, entradas no registo de transparência ou dados de rede permanentes já publicados.

As denúncias de abuso têm rate limit usando um hash unidirecional do IP do denunciante; não armazenamos IPs em claro para esse propósito.


9. Cadeia de suprimentos e integridade do build

9.1 Pinagem do toolchain

As versões do compilador e do tempo de execução estão fixadas na configuração do repositório e as dependências são resolvidas através de ficheiros de bloqueio comprometidos. O CI verifica a atualidade dos ficheiros gerados e invariantes sensíveis à reprodutibilidade. Não fazemos a afirmação mais forte de que cada compilação limpa seja bit a bit idêntica em todas as máquinas suportadas.

9.2 Lints e análise estática

O workspace ativa os nossos grupos de lint mais estritos no nível deny. CI trata cada warning — incluindo warnings de doc-link — como uma falha de build. Isto é deliberado: usamos a estrita lintagem como uma armadilha para regressões sutis.

9.3 Gates de CI

O fluxo de trabalho de CI cobre formatação e lints rigorosos; testes de Rust, WASM/browser, Worker, embed e API; verificação de tipos; cobertura de código; verificação de mutações/invariantes; análise estática de dependências e fluxo de trabalho; verificação de chaves i18n, cobertura, desvio e pontos de código hostis; frescura de documentação gerada/API/base de conhecimento; inventário de documentos e verificação de links internos; orçamentos de folhas de estilo e pacotes; e validação OpenAPI. Alguns trabalhos de mutação dispendiosos são agendados em vez de serem executados em cada push.

Um único necessário ci O roll-up permanece vermelho se algum trabalho necessário falhar. Os fluxos de trabalho de branch protegida e de deploy consomem esse resultado em vez de duplicar uma verificação de segurança menor.

9.4 Teste de mutação

Um job semanal roda teste de mutação contra os módulos puros críticos para a segurança: hashing, CBOR canónico, seal, unlock, os newtypes do formato de transmissão, os validadores de tipo de protocolo, e o namespace de handle. O teste de mutação responde "nossa suíte de testes captura código sutilmente errado?" — se uma implementação mutada ainda passar em todos os testes, sabemos que temos uma lacuna de cobertura de teste e a abordamos.

9.5 Git hooks

Hooks locais (pre-commit, pre-push) espelham os gates de CI para que regressões sejam capturadas antes de saírem da máquina do desenvolvedor. Os hooks são instalados via um script do repositório; não são contornados em nosso fluxo de trabalho e o CI é o gate autoritativo se forem ignorados.


10. Testes

O código crítico para a segurança carrega três tipos de testes:


11. Higiene de branches e releases

Ramos de funcionalidades avançam staging apenas através de um pedido de pull do Gate 1: obrigatório ci verde, sem pedidos de alteração por resolver, sem conflitos de fusão e uma árvore limpa e revista; a fusão é do tipo 'squash-and-delete'. main avança apenas através do Portão 2 staging → main pull request e preserva a ancestralidade com um commit de merge. Os pushs diretos para a branch não são o fluxo de trabalho de release.

As implementações de staging e produção são acionadas a partir do correspondente protegido staging e main os ramos de estados após a CI. O código do pull request e as credenciais do fork não recebem segredos de deploy.

Os segredos usados em workflows de deploy são limitados ao ambiente de deploy pela nossa plataforma de CI. Eles não estão disponíveis para workflows de pull-request de forks.


12. Divulgação coordenada

Se você acredita que encontrou uma vulnerabilidade de segurança no qub, queremos saber rapidamente e nos comprometemos a tratar o relatório profissionalmente.

Acusamos recebimento em até três dias úteis e o mantemos informado à medida que investigamos. Com seu consentimento, creditamos os relatores nas notas de release.

12.1 Safe Harbor

Se sua pesquisa segue as regras acima (investigação de boa-fé, sem dano a outros utilizadores ou ao serviço, janela razoável de divulgação), não tomaremos ação legal contra você, e não pediremos que a aplicação da lei o faça. Tratamos seu trabalho como teste autorizado e preferimos que você encontre o bug a alguém mais.

Este Safe Harbor aplica-se a:

Não se aplica à engenharia social de membros da equipa qub, testes de negação de serviço, ou acesso a dados de outros utilizadores além do necessário para demonstrar o problema. Se você não tem certeza se algo cai dentro do Safe Harbor, pergunte primeiro usando o mesmo prefixo de assunto [SECURITY].


13. Limitações honestas

A segurança é uma prática, não um estado. Algumas limitações merecem ser nomeadas diretamente:


14. Mudanças nesta página

Mudanças materiais são notadas atualizando a data de entrada em vigor no topo. Quando uma mudança reflete uma melhoria concreta de segurança, descrevemo-la brevemente no changelog público. Quando uma mudança reflete uma clarificação de política, descrevemos o que mudou e por quê.

Para perguntas sobre qualquer coisa nesta página, envie um e-mail para support@qub.social com o prefixo de assunto [SECURITY].


15. Registo de mudanças

Versão Data de vigência Resumo
1.1 23 de setembro de 2026 Conciliou reivindicações criptográficas, modos de entrega, armazenamento, CSP, sessões, chaves de API, pagamentos, CI e fluxo de trabalho de lançamento com o sistema implementado.
1,0 2 de maio de 2026 Publicação inicial.