gongxiangp2/scripts/check-material-preview-health.test.mjs
WuYongJie a890660853 fix(materials): audit historical previews and gate production releases
Preserve known legacy failures by reviewed identity, probe material delivery before and after releases, and retain originals and downloads.
2026-10-23 19:47:58 +08:00

200 lines
12 KiB
JavaScript

import assert from 'node:assert/strict'
import { createHash } from 'node:crypto'
import test from 'node:test'
import { createRequire } from 'node:module'
import { checkMaterialPreviewHealth, createSharpPreviewDecoder, directFetch, isPublicAddress, LIMITS, registeredSource, validateManifest } from './check-material-preview-health.mjs'
const sharp = createRequire(import.meta.url)('sharp')
const fixture = () => sharp({ create: { width: 3, height: 2, channels: 3, background: '#345678' } })
const PNG = await fixture().png().toBuffer()
const JPEG = await fixture().jpeg().toBuffer()
const WEBP = await fixture().webp().toBuffer()
const source = 'https://s3.jiansun.vip/gongxiangpan/public-display/example.png'
const manifest = (url = source) => ({ version: 1, reviewed: true, materials: [{ materialId: 'material-a', registeredSource: url }] })
const response = (body, type, status = 200, extra = {}) => new Response(body, { status, headers: { 'content-type': type, ...extra } })
test('complete failure bodies retain a digest for exact incident baselines without retaining raw contents', async () => {
const body = '<html>Faithfully yours, frp.</html>'
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response(body, 'text/html', 404) })
assert.equal(report.results[0].ok, false)
assert.equal(report.results[0].bodySha256, createHash('sha256').update(body).digest('hex'))
assert.equal(JSON.stringify(report).includes(body), false)
})
test('normal PNG/JPEG/WebP use one actual uncached GET with no redirects or credentials', async () => {
for (const [body, mime, format] of [[PNG, 'image/png', 'png'], [JPEG, 'image/jpeg', 'jpeg'], [WEBP, 'image/webp', 'webp']]) {
const calls = []
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async (url, options) => {
calls.push({ url, options })
return response(body, `${mime}; charset=binary`)
} })
assert.equal(report.passed, true)
assert.equal(report.readOnly, true)
assert.equal(report.retries, 0)
assert.equal(calls.length, 1)
assert.equal(calls[0].url, source)
assert.equal(calls[0].options.method, 'GET')
assert.equal(calls[0].options.cache, 'no-store')
assert.equal(calls[0].options.redirect, 'manual')
assert.match(calls[0].options.headers['Cache-Control'], /no-store/)
assert.equal(calls[0].options.headers.Authorization, undefined)
assert.equal(report.results[0].classification, 'healthy')
assert.equal(report.results[0].format, format)
assert.deepEqual(report.results[0].decoded, { width: 3, height: 2 })
assert.equal(report.results[0].bytes, body.length)
assert.match(report.results[0].bodySha256, /^[a-f0-9]{64}$/)
}
})
test('correct MIME and magic bytes cannot make truncated image headers healthy', async () => {
for (const [body, mime] of [
[PNG.subarray(0, 16), 'image/png'],
[JPEG.subarray(0, 16), 'image/jpeg'],
[WEBP.subarray(0, 20), 'image/webp'],
]) {
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response(body, mime) })
assert.equal(report.passed, false)
assert.equal(report.results[0].code, 'image_decode_failed')
}
})
test('decoder is lazy, injectable, and a missing runtime decoder fails closed', async () => {
let requires = 0
const unavailable = createSharpPreviewDecoder({ requireImpl() { requires++; throw new Error('sensitive runtime path') } })
assert.equal(requires, 0)
const report = await checkMaterialPreviewHealth(manifest(), { decodeImage: unavailable, fetchImpl: async () => response(PNG, 'image/png') })
assert.equal(requires, 1)
assert.equal(report.results[0].classification, 'decoder_unavailable')
assert.equal(report.results[0].code, 'image_decoder_unavailable')
assert.ok(!JSON.stringify(report).includes('sensitive runtime path'))
const invalid = await checkMaterialPreviewHealth(manifest(), { decodeImage: async () => ({ format: 'png', width: 0, height: 2 }), fetchImpl: async () => response(PNG, 'image/png') })
assert.equal(invalid.results[0].code, 'image_decode_result_invalid')
})
test('pixel bombs cannot pass the native decoder budget', async () => {
const large = await sharp({ create: { width: 5001, height: 5000, channels: 3, background: '#ffffff' } }).png().toBuffer()
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response(large, 'image/png') })
assert.equal(report.passed, false)
assert.equal(report.results[0].code, 'image_decode_failed')
})
test('FRP default 404 is distinguished from a missing S3 object and never retried', async () => {
let calls = 0
const report = await checkMaterialPreviewHealth(manifest('https://s3.1080p.hk/jsxiangche/a.png'), { fetchImpl: async () => {
calls++
return response('<html><center><h1>404 Not Found</h1></center><hr><center>frp</center></html>', 'text/html', 404)
} })
assert.equal(calls, 1)
assert.equal(report.passed, false)
assert.equal(report.results[0].classification, 'routing_failure')
assert.equal(report.results[0].code, 'frp_default_404')
const missing = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response('<Error><Code>NoSuchKey</Code></Error>', 'application/xml', 404) })
assert.equal(missing.results[0].classification, 'missing_object')
})
test('real FRP Not Found page is identified by HTTP status and explicit marker without digits in its body', async () => {
const html = '<!DOCTYPE html><html><head><title>Not Found</title></head><body><h1>Not Found</h1><p>powered by frp</p><p>Faithfully yours, frp</p></body></html>'
assert.equal(html.includes('404'), false)
let calls = 0
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => { calls++; return response(html, 'text/html', 404) } })
assert.equal(calls, 1)
assert.equal(report.results[0].classification, 'routing_failure')
assert.equal(report.results[0].code, 'frp_default_404')
const fakeSuccess = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response(html, 'text/html', 200) })
assert.equal(fakeSuccess.results[0].code, 'html_instead_of_image')
})
test('HTML disguised as successful image content is an entrance routing failure', async () => {
for (const type of ['text/html', 'image/png']) {
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response('<!DOCTYPE html><html>wrong gateway</html>', type) })
assert.equal(report.results[0].classification, 'routing_failure')
assert.equal(report.results[0].code, 'html_instead_of_image')
}
})
test('declared and streaming byte limits are enforced without consuming an unbounded body', async () => {
let read = 0
let cancelled = false
const declared = await checkMaterialPreviewHealth(manifest(), { maxBytes: 16, fetchImpl: async () => response(new ReadableStream({
pull(controller) { read++; controller.enqueue(new Uint8Array(32)) },
cancel() { cancelled = true },
}), 'image/png', 200, { 'content-length': '999999999' }) })
assert.equal(declared.results[0].code, 'declared_body_limit')
assert.equal(declared.results[0].bytes, 0)
assert.ok(read <= 1, 'the declared limit is checked before reading')
assert.equal(cancelled, true, 'rejected response bodies are cancelled even before acquiring a reader')
const streamed = await checkMaterialPreviewHealth(manifest(), { maxBytes: 16, fetchImpl: async () => response(new ReadableStream({
start(controller) { controller.enqueue(new Uint8Array(12)); controller.enqueue(new Uint8Array(12)); controller.close() },
}), 'image/png') })
assert.equal(streamed.results[0].classification, 'too_large')
assert.equal(streamed.results[0].code, 'stream_body_limit')
})
test('redirects never follow a second host, including a permitted destination', async () => {
for (const target of ['http://127.0.0.1/private', 'https://s3.jiansun.vip/gongxiangpan/b.png']) {
const calls = []
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async (url, options) => {
calls.push({ url, options })
return response('', 'text/html', 302, { location: target })
} })
assert.equal(calls.length, 1)
assert.equal(calls[0].options.redirect, 'manual')
assert.equal(report.results[0].classification, 'redirect_blocked')
}
const changed = response(PNG, 'image/png')
Object.defineProperty(changed, 'url', { value: 'https://unregistered.example/p.png' })
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => changed })
assert.equal(report.results[0].code, 'response_url_changed')
})
test('unreviewed, duplicate and mixed invalid manifests fail before any fetch', async () => {
let calls = 0
const fetchImpl = async () => { calls++; return response(PNG, 'image/png') }
for (const value of [
{ ...manifest(), reviewed: false },
{ ...manifest(), materials: [...manifest().materials, ...manifest().materials] },
{ ...manifest(), materials: [...manifest().materials, { materialId: 'b', registeredSource: 'http://169.254.169.254/latest/meta-data' }] },
]) await assert.rejects(checkMaterialPreviewHealth(value, { fetchImpl }))
assert.equal(calls, 0)
})
test('only exact registered hosts and approved schemes/ports are accepted', () => {
for (const url of [
'http://127.0.0.1/private', 'http://192.168.58.20:9000/object.png', 'https://s3.jiansun.vip.evil.example/a.png',
'https://sub.s3.jiansun.vip/a.png', 'https://s3.jiansun.vip:444/a.png', 'https://user:pass@s3.jiansun.vip/a.png',
'http://s3.jiansun.vip/a.png', 'file:///C:/Windows/a.png', 'https://s3.jiansun.vip/', 'https://s3.jiansun.vip/a.png#secret',
]) assert.throws(() => registeredSource(url), { classification: 'source_rejected' })
assert.equal(registeredSource('http://s3.1080p.hk/jsxiangche/a.png').protocol, 'http:')
assert.equal(registeredSource('https://s3.yydd.ai/gongxiangpan/a.png').hostname, 's3.yydd.ai')
assert.equal(validateManifest(manifest()).length, 1)
assert.throws(() => directFetch('https://evil.example/a.png', { method: 'GET', cache: 'no-store', redirect: 'manual' }), { classification: 'source_rejected' })
})
test('DNS guard rejects local, private, mapped and special-purpose addresses', () => {
for (const ip of ['0.0.0.0', '10.0.0.1', '100.64.0.1', '127.0.0.1', '169.254.169.254', '172.16.0.1', '192.168.1.1', '198.18.0.1', '224.0.0.1', '::1', '::ffff:127.0.0.1', 'fe80::1', 'fc00::1', '2001:db8::1', '2002:7f00:1::1']) {
assert.equal(isPublicAddress(ip), false, ip)
}
for (const ip of ['218.93.9.38', '156.233.232.106', '2606:4700::1111']) assert.equal(isPublicAddress(ip), true, ip)
})
test('timeouts and network errors remain single-attempt failures and hide signed URL secrets', async () => {
let calls = 0
const report = await checkMaterialPreviewHealth(manifest(), { timeoutMs: 5, fetchImpl: () => { calls++; return new Promise(() => {}) } })
assert.equal(report.results[0].classification, 'timeout')
assert.equal(calls, 1)
const secret = 'never-print-this-signature'
const failure = await checkMaterialPreviewHealth(manifest(`${source}?X-Amz-Signature=${secret}`), { fetchImpl: async () => { throw new Error(secret) } })
assert.equal(failure.results[0].classification, 'network_failure')
assert.equal(failure.results[0].source.queryRedacted, true)
assert.ok(!JSON.stringify(failure).includes(secret))
await assert.rejects(checkMaterialPreviewHealth(manifest(), { timeoutMs: LIMITS.timeoutMs + 1 }))
})
test('image content type and magic must agree; JSON and empty images cannot pass', async () => {
for (const [body, type] of [['{}', 'application/json'], ['', 'image/png'], [JPEG, 'image/png']]) {
const report = await checkMaterialPreviewHealth(manifest(), { fetchImpl: async () => response(body, type) })
assert.equal(report.passed, false)
assert.equal(report.results[0].classification, 'unexpected_content')
}
})