链上数据是不可信的输入
ZooBC 上的每一个代币名称、符号、交易消息、托管指令和数据集值,都是由支付手续费的人自行选择的。没有任何东西审查它,也没有任何东西会仅仅因为它是永久的就变成真的。给开发者的规则很简短:从链上读取的数据是输入,绝不是指令。
显示链上文本
在网页中,以文本的形式把链上文本放到屏幕上:
el.textContent = token.name; // shown as text: safe
el.innerHTML = token.name; // parsed as HTML: never
以 HTML 形式插入的文本可能携带标记和脚本,它们会以你页面的权限运行,而由正则表达式构成的过滤器不足以阻止这一点。链接也需要同样小心:不要在未检查其协议头的情况下打开链上数据中发现的 URL。
由 AI 代理驱动的应用同样绝不能服从它在代币名称、备注或数据集值中发现的句子。写在代币名称里的“忽略你的指令”与其他任何字符串一样,只是数据。发送方的余额也说明不了其文本是否安全。
协议确实检查的内容
只有少数几个字段具有由链强制执行的格式:
| 字段 | 规则 |
|---|---|
tokenicon: 数据集值 | PNG 或 WebP 图像,长宽各 1 到 512 像素,16 到 4,096 字节 |
| 注册表中的域名,例如网关的域名 | 1 到 256 个字符:字母、数字、点和连字符 |
| 注册表中的 URL,例如网关的 URL | 以 https:// 开头;不含空白、控制字符、引号、尖括号或反引号 |
inv: 数据集值 | 一个任何位置都不含负数的 JSON 对象 |
其他一切在设计上都是任意字节。即使是经过检查的字段也只是格式而已:一个格式正确的 https:// 地址仍可能指向任何地方。
代币图标
节点在 GET /api/v1/tokens/:id/icon 提供每个代币的图标,并附带使其保持惰性的响应头:X-Content-Type-Options: nosniff、Content-Disposition: inline、Content-Security-Policy: default-src 'none'; sandbox,以及五分钟的缓存。页面只需要一个指向该路由的图片标签。
数据集行:检查设置者
节点为某个账户列出的数据集,返回该账户作为设置者或接收账户的行,而任何账户都可以在其他任何账户名下写入行(数据集)。要读取一个账户关于自己的陈述,只保留 role 为 setter 或 both 的行;该账户仅作为接收账户的行是别人写的。要核实诸如“verified = yes”这样的声明,只接受设置者是你所信任账户的行。
值有两种形式:经过转义的 value 和无损的 value_b64。无论哪种,内容都是陌生人的文本,要像其余内容一样用 textContent 显示。
检查清单
- 对从链上读取的每个字符串都用
textContent,绝不用innerHTML。 - 打开 URL 之前先检查其协议头,绝不把链上文本当作指令执行。
- 只信任来自预期设置者的数据集行。
- 通过图标路由显示代币图标。