{
  "synthetic": true,
  "execution": "Teaching record only; no live integration tested",
  "slug": "enquiry-log-allowlist-redaction-contract",
  "group": "portal-delivery",
  "title": [
    "An enquiry failure log should not copy the whole form",
    "询盘失败日志，不应复制整张表单"
  ],
  "intro": [
    "When an enquiry fails, a supplier may log the entire request to make debugging easier. That can copy messages, attachments and credentials into a second system. Commission a small operational event with approved fields, and test what is excluded as carefully as what is retained.",
    "询盘失败时，供应商可能为排错记录完整请求，导致留言、附件及凭证进入第二套系统。应验收字段获准、尽量小的操作事件；排除什么与保留什么同样重要。"
  ],
  "facts": [
    [
      "OWASP’s logging guidance identifies data such as access tokens, authentication secrets and sensitive personal information for exclusion or protected handling, and calls for sanitising event data against log injection.",
      "OWASP日志指南列出访问令牌、认证秘密及敏感个人信息等应排除或保护处理的数据，并要求防范日志注入。",
      "https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude"
    ]
  ],
  "example": [
    [
      [
        "Synthetic failed event has requestID R18, codeMAIL_TIMEOUT, elapsed850ms",
        "Approved operational allowlist",
        "Retain R18, MAIL_TIMEOUT,850; no message body"
      ],
      [
        "合成失败事件含R18、MAIL_TIMEOUT、850毫秒",
        "批准操作字段白名单",
        "保留R18、错误码及850，不留留言正文"
      ]
    ],
    [
      [
        "Request also contains Authorization and email",
        "Not in approved event schema",
        "Drop from log event; never hash a token and call it harmless"
      ],
      [
        "请求还含Authorization及邮箱",
        "不在批准事件schema",
        "不写入事件，不能把令牌hash后就称无害"
      ]
    ],
    [
      [
        "User text includes a newline and fake SUCCESS record",
        "Raw interpolation into a text log",
        "Reject raw interpolation; use reviewed structured encoding"
      ],
      [
        "文字含换行及假SUCCESS记录",
        "直接拼入文本日志",
        "拒绝拼接，使用审核后的结构化编码"
      ]
    ],
    [
      [
        "Log write fails but enquiry outcome is unknown",
        "Separate diagnostic and business states",
        "Record logging failure safely; do not invent enquiry success"
      ],
      [
        "日志写入失败，询盘结果未知",
        "诊断与业务状态分开",
        "安全处理日志失败，不能编造询盘成功"
      ]
    ]
  ],
  "steps": [
    [
      "Have the owner approve event fields, purpose, access and retention. Use an opaque request ID rather than copying contact details to identify the event.",
      "由负责人批准字段、目的、访问及保留期，以不含个人信息的请求ID关联事件，不复制联系方式。"
    ],
    [
      "Build the synthetic request with both allowed and deliberately excluded fields. Inspect the final emitted event and all configured sinks, not only the first console line.",
      "构造同时含保留与排除字段的合成请求，检查最终事件及全部日志目的地，不只看第一行console。"
    ],
    [
      "Exercise newline content and a failed log sink in isolation. Verify credentials/message text remain absent and enquiry receipt, mail delivery and diagnosis remain distinct.",
      "隔离演练换行及日志目标失败，确认凭证留言未泄露，并把询盘接收、邮件送达及诊断分开。"
    ]
  ],
  "result": [
    "The retained event is useful for tracing a timeout without duplicating the form. A field allowlist also gives a concrete negative test: adding a new form field must not automatically add it to logs. Redaction is a maintained data-flow decision, not a promise made by an error-code label.",
    "保留事件能追超时而不复制表单。白名单还有明确反例：新增表单字段不能自动进入日志。脱敏是持续维护的数据流决定，不是错误码名称的保证。"
  ],
  "accept": [
    "Require only approved fields in every observed sink and a tested failure path. Unauthorised sink access remains outside the test; record it as unverified.",
    "每个已观察目的地仅含获准字段，并测试失败路径；无权限访问的目的地保持未验证。"
  ],
  "limit": [
    "Synthetic request only; no real enquiry, logs, customer information, mail or third-party telemetry is accessed or sent. Retention and legal basis need separate owner decisions.",
    "仅合成请求，未访问或发送真实询盘、日志、客户信息、邮件或第三方遥测；保留期及法律依据由负责人另定。"
  ],
  "oldLinks": []
}
