tencent-cloud-fetch-processor — Design (IMPLEMENTABLE)
1. Overview
- Tier: Tier-2 IaaS (Phase 4)
- Verdict: IMPLEMENTABLE — first-party CVE-bearing advisories reachable via paginated server-rendered HTML, no anti-bot
- Source:
https://cloud.tencent.com/announcelisting →https://cloud.tencent.com/announce/detail/{id}per advisory - Owner: Tencent Cloud
- Licence: Public, no auth
- Schedule cadence:
cron(0 15 * * ? *)— daily 15:00 UTC. Tencent posts【安全通告】(security advisories) at irregular cadence; daily check is sufficient given the monotonic ID enables incremental crawl. - ECS resources: cpu_units=256, memory_mb=512, expected_duration_minutes=15
- Reads: External HTML, BulkDataDumpTracker (last-seen ID), LoadProcessedHashes (resume)
- Writes: CVEMetadata, CVEMetadataReferences, CVEAlias, BulkDataDumpTracker, S3 archive, optional CRIT staging
- Extended dictionary:
internal/critutil/dictionaries/extended/tencent.json(§15.2)
2. Source contract (Phase 0 recon — 2026-05-08)
Recon-protocol grid:
| Step | Check | Finding |
|---|---|---|
| 1 | First-party CSAF | None |
| 2 | First-party CVRF | None |
| 3 | First-party RSS / Atom | None |
| 4 | First-party JSON API | None |
| 5 | First-party HTML listing | Yes. cloud.tencent.com/announce paginated 1..~216, server-rendered HTML, monotonic integer detail IDs /announce/detail/{N} |
| 6 | GitHub Security Advisories | N/A |
| 7 | CVE alias presence | Confirmed. Title prefix 【安全通告】 filters security from operational announces; titles + bodies carry CVE-YYYY-NNNN+ identifiers extractable by regex |
| 8 | Anti-bot | None observed; plain HTML, no JS gating, no WAF challenge to identifying-UA fetches |
Source contract table:
| Property | Finding |
|---|---|
| Cadence | Irregular; ~50 security advisories per year |
| Volume | 216+ pages of mixed announces; security subset is the 【安全通告】-prefixed entries |
| Identifier | Tencent advisory ID = integer in URL path; CVE refs as aliases |
| Backfillability | Full history reachable via paginated index; integer IDs are monotonic so resume-from-max-seen is trivial |
| Anti-bot / auth | None |
| Pagination | ?page=N query param; ~10 entries per page |
| Freshness signal | Per-row publication date (YYYY-MM-DD); detail page repeats it; tracker uses max-seen ID |
CVE presence verified:
$ curl -sS https://cloud.tencent.com/announce/detail/2277 | grep -oE 'CVE-[0-9]{4}-[0-9]+' | sort -u
CVE-2026-31431
Sample fixture: https://cloud.tencent.com/announce/detail/2277 —
Linux Kernel “Copy Fail” CVE-2026-31431, dated 2026-04-30.
Language note: Content is Chinese-only. CVE refs (CVE-YYYY-NNNN),
advisory IDs (numeric), URLs in references section, and dates
(YYYY-MM-DD) are language-neutral and extractable by regex without
NLP. The title prefix 【安全通告】 is a stable ASCII-bracketed
sentinel for filtering security advisories from operational ones.
Description text stored verbatim; downstream translation out of scope.
3. Architecture diagram
[Listing pages 1..N] ── HTTP fetch ──> regex filter `【安全通告】`
│
▼
[advisory IDs] ── enumerate, skip seen
│
▼
[GET /announce/detail/{id}]
│
▼
tencent.ParseDetail ── extract:
- title (zh-CN), date, advisory_id
- CVE aliases (regex)
- severity (CVSS extracted from body)
- references (URLs in body)
│
▼
tencent.MapToSourceData ── osv.CVESourceData
│
▼
processor.StoreCVESourceData
│
▼
(tx) UpsertCVEMetadata + InsertAliases +
CVEDescription + CVEReference +
BulkDataDumpTracker
│
▼
optional CRIT staging per matched service
│
▼
S3 archive (re-serialised JSON)
4. Source → DB field mapping
| OSV / CVEMetadata field | Tencent source |
|---|---|
cveId | First CVE alias if present; else TC-YYYY-NNNN minted (mirrors elastic ESA pattern) |
source | "tencent-cloud" |
title | Tencent title (zh-CN, kept verbatim) |
description | Body text (zh-CN), stripped of HTML, kept verbatim |
datePublished | YYYY-MM-DD parsed to seconds (int) |
dateUpdated | Same |
aliases | Tencent advisory ID tencent-{id} + every CVE-YYYY-NNNN regex hit |
references | URLs in body (NVD, vendor, PoC) |
severityCvss | If body includes CVSS vector string, parse and store; otherwise null |
affectedVendor / affectedProduct | Best-effort extraction from 【安全通告】 title (e.g. “Linux Kernel” / “MongoDB”) |
sourceFileHash | SHA1 of detail-page raw HTML |
5. Identifier policy
- Primary cveId: First CVE alias by canonical sort. If no CVE
alias exists, mint
TC-{YYYY}-{NNNN}viadb.LoadMaxGcveSequence(mirrors elastic ESA-YYYY-NN pattern from §15.6). - Aliases written via
db.InsertAliases— never raw INSERT (per AGENTS.md alias contract): the Tencent advisory ID prefixtencent-{integer}plus everyCVE-YYYY-NNNNextracted from title + body. source="tencent-cloud"on every CVEMetadata + CVEAlias row.- Bundle suppression: when title carries multiple CVEs (rare —
most Tencent advisories are 1:1),
db.InsertAliaseshandles the CVE-prefix bundle suppression automatically.
6. CRIT / VEX
Single-envelope CRIT per advisory keyed to title-inferred service (mirrors zoom-fetch-processor §15.6 pattern):
| Title keyword | provider/service/resource_type |
|---|---|
| 云数据库 / cdb / mysql / postgresql | tencent / cdb / db_instance |
| 云服务器 / cvm | tencent / cvm / instance |
| 容器服务 / tke | tencent / tke / cluster |
| 对象存储 / cos | tencent / cos / bucket |
| 云函数 / scf | tencent / scf / function |
| (default fallback) | tencent / cvm / instance |
VEX semantics:
vex_status="fixed"when title/body says “已修复” or includes a patched-version noteshared_responsibility:provider_onlyfor managed services (CDB, COS, TKE control-plane, SCF);customer_action_requiredfor CVM (customer reboots)fix_propagation:automaticfor managed services;version_updatefor CVM
The §15.2 extended dict carries 5 service entries; cover-rate test asserts each title keyword routes to a dict-resolvable service.
7. S3 layout
Per AGENTS.md:
- Archive:
tencent-cloud/files/{sha256}/{advisory-id}.htmlwhereadvisory-id = "TC-{integer}" - Quarantine:
failed-feeds/tencent-cloud-fetch-processor/{date}/{reason}/{filename}
Reuse s3client.Uploader.Archive / Quarantine.
8. Error handling
Listing pages occasionally redirect to a localised landing page when
served from non-CN IPs; if <div class="announce-list"> is empty,
re-fetch with Accept-Language: zh-CN,en;q=0.5 once before
quarantining. Per-detail parse failures are quarantined as
parse-error. Detail pages that match 【安全通告】 but contain no
CVE alias get minted a TC- ID and proceed (so we don’t lose
Tencent-internal-only advisories).
9. Performance
CPU 256, memory 512 MB. Expected duration <15 minutes per scheduled run. Per-run cap: 100 new advisories (incremental beyond the last-seen integer ID). Backfill (full 216-page sweep) takes ~30 minutes at 200ms per page + ~2s per detail-page fetch.
10. Backfill
go-tencent-cloud-fetch-backfill TARGET="local" FORCE="false" \
LIMIT="0" EMIT_CRIT="false"
Recipe pattern matches go-zoom-fetch-backfill (§15.6). unset EXPECTED_DURATION_MINUTES. Pass LIMIT=0 for full history;
LIMIT=N for N-most-recent.
11. Implementation order
internal/tencent/{types,client,parse,parse_test}.gowithtestdata/listing-page-1.html+testdata/detail-2277.htmlcaptured fixturescmd/tencent-cloud-fetch-processor/{main,crit_mapper,crit_mapper_test}.go- Containerfile final stage, terraform module, task-manager.toml, dashboard targets.go, post-push-ecr.sh hook, justfile recipe
- Live test against
.envlocal DB --emit-crit=trueon schedule (spot-check freeze ended 2026-05-09 per §15.13; new producers ship at true and rely on post-deploy CloudWatch monitoring + per-source revert on >5% stage-failure)
S3 Persistence
Not used. This processor does not currently archive payloads or quarantine failures to S3. Per the S3 Persistence Contract this is non-compliant — see the compliance matrix for the implementation roadmap.
⚠ Not in the compliance matrix — status needs verification.
Expected paths when implemented:
- Archive:
tencent-cloud/files/{sha256}/{filename} - Quarantine:
failed-feeds/tencent-cloud-fetch-processor/{YYYY-MM-DD}/{reason}/{filename} - Likely reasons: (none documented)