Skip to content

security(ui): make streaming display redaction differential-safe #2990

Description

@M4n5ter
English

Problem

Streaming assistant and thinking text currently stays safe by re-running redactSecrets over the accumulated display text. PR #2975 briefly attempted to optimize this with bounded incremental state, but review found that the incremental path could diverge from whole-text redaction: some chunk boundaries exposed secret suffixes, while others redacted legitimate opaque text.

#2975 therefore keeps the existing whole-text security boundary. A future optimization needs a stronger contract than a collection of regex examples.

Required behavior

  • For every input prefix and every possible chunking, the visible result must be exactly equivalent to applying redactSecrets to that full prefix, subject only to the existing documented display truncation.
  • No intermediate, aborted, errored, or truncated state may reveal bytes that whole-text redaction classifies as secret.
  • Normal text must not be redacted solely because tokens happen to cross chunk boundaries.
  • The implementation must remain bounded in retained state and demonstrate a material improvement on realistic long streams before replacing the current path.

Validation

Add differential/property tests over arbitrary chunk boundaries, including:

  • API keys and authorization values containing separators such as /, ., =, _, and -;
  • JWT-like values and long opaque hexadecimal/alphanumeric strings;
  • legitimate hashes adjacent to paths or punctuation;
  • one-character chunks, long whitespace, truncation boundaries, stream completion, abort, and error;
  • randomized inputs comparing every streamed prefix with the whole-text oracle.

Keep a benchmark for a long response delivered in small deltas, but treat security equivalence as the hard constraint.

Related: #2975

中文

问题

Assistant 与 thinking 的流式文本目前通过对累计显示文本重复执行 redactSecrets 来保证安全。#2975 曾尝试用有界增量状态优化这条路径,但 review 发现增量结果可能偏离全量脱敏语义:部分切块会暴露 secret 后缀,另一些切块会误伤正常的 opaque text。

因此 #2975 保留现有的全量文本安全边界。后续优化需要先定义严格契约,而不是继续补充正则样例。

必须满足的行为

  • 对任意输入前缀和任意切块方式,可见结果都必须与对该完整前缀执行 redactSecrets 严格等价,唯一例外是已有且明确记录的显示截断。
  • 中间态、abort、error 和截断状态都不能暴露被全量脱敏判定为 secret 的内容。
  • 正常文本不能仅因为 token 跨越 chunk 边界而被误脱敏。
  • 实现必须保持有界状态;只有在真实长流基准中证明有显著收益后,才替换当前路径。

验证

增加覆盖任意切块边界的 differential/property tests,包括:

  • 包含 /.=_- 等分隔符的 API key 与 authorization value;
  • JWT 类值以及较长的十六进制/字母数字 opaque string;
  • 紧邻路径或标点的合法 hash;
  • 单字符 chunk、长空白、截断边界、stream completion、abort 与 error;
  • 随机输入,并在每个流式前缀上与全量 oracle 对比。

保留“小 delta 组成长回复”的性能基准,但安全等价性是硬约束。

关联:#2975

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions