alinux2-rss-processor

Status: Live and fully caught up Source: Alibaba Cloud Linux 2 updateinfo feed Type: rss (in the naming convention’s sense; the document is really YUM updateinfo XML, not RSS/Atom — parse with encoding/xml) Source slug: alibaba-cloud Schedule: weekly, Fridays 07:00 UTC — cron(0 7 ? * FRI *), verified ENABLED; 256 CPU / 512 MB, expected_duration_minutes = 30

Overview

Alibaba Cloud Linux 2 is the default OS image on Alibaba Cloud ECS, and like Amazon Linux it backports fixes rather than tracking upstream versions — so an upstream fixed-version tells you nothing about whether an aliyun host is patched. This feed is the only authoritative answer, and this processor is the only thing in the tree that reads it.

The distribution reached EOL in December 2024 but the feed is still occasionally updated, which is why the schedule is weekly rather than daily.

It owns source='alibaba-cloud' outright. The feed contained 612 <update> elements when checked on 2026-08-06 and production holds exactly 612 rows for that source — 100% coverage, nothing behind. 559 are keyed ALINUX2-SA-YYYY:NNNN and the remaining 53 HOTFIX-BA-YYYY:NNNN, the kernel-hotfix advisory series carried in the same document. The newest advisory is issued 2026-05-26, so a corpus staleness report will show this source as ~70 days old; that is a quiet upstream, not a stalled processor. Weekly runs since then have correctly matched every resume hash and stored nothing.

Feed shape

One <update> per advisory. The parts that matter:

Element / attributeUsed for
<id>CVEMetadata.cveId verbatim (main.go:180) — an empty id skips the item
<title>, <description>title and one CVEDescription row
<issued date>datePublished (main.go:210)
<updated timestamp>dateUpdated, preferred over <updated date> (main.go:212-216). The attribute is sometimes a float (1551199784.0), which is why it is unmarshalled through the flexInt64 type at main.go:66-76
<severity>CVEMetric other row, otherType = "alinux2-severity"
<reference type="cve" id="CVE-…" cvss3="…">CVE alias edges and the CVSS3 metric — the vector arrives as 7.5/CVSS:3.1/AV:N/…, split at /CVSS: (main.go:527)
<reference type="ALINUX2-SA" href>sourceAdvisoryRef; falls back to a constructed …/alinux/cve/{id}.xml URL when absent (main.go:198-201)
<pkglist>…<package name arch>one CVEAffected row per unique package, preferring arch="src" names as canonical (parsePackageNames, main.go:465-497)

Records produced

TableOne row perNotes
CVEMetadataadvisorysource="alibaba-cloud", cveId = the advisory id, dataVersion="5.0", state="PUBLISHED" (main.go:316)
CVEMetadata.sourceFileHashadvisorySHA1(id | issued | updated | description) — the resume key (main.go:203, main.go:331)
CVEDescriptionadvisory with a non-empty descriptioncontainerType="cna", lang="en"
CVEMetadataReferencesadvisory + each referenced CVEthe detail XML (referenceSource="alinux2-sa") plus one cve.mitre.org URL per CVE
CVEAffectedunique package namevendor="Alibaba Cloud", collectionURL="Alibaba Cloud Linux 2.1903"
Dependency / registry rowseach affected packagedb.EnrichAffectedWithDependency runs inside the same transaction (main.go:388)
CVEMetricseverity + each CVSS3 referenceproduction holds 612 other, 1,312 cvssV3_1 and 680 cvssV3_0 rows for this source
CVEAlias(advisory, CVE)via db.InsertAliases, always called even with an empty CVE list so the same-cveId cross-source backfill runs (main.go:431-436) — 16,904 edges in production

CVEMetadata.vectorString is not set, even though a vector is available: the CVSS3 data goes to CVEMetric only. Any coverage metric that reads CVEMetadata.vectorString therefore reports 0% CVSS for this source while 1,992 vectors are in fact stored one table over.

Resume

Per-advisory, by content hash. db.LoadProcessedHashes(pool.Read, "alibaba-cloud") is loaded once before the item loop (main.go:161); an item whose SHA1(id|issued|updated|description) matches the stored sourceFileHash is skipped (main.go:206). --force bypasses it. Because the feed is a full document rather than a rolling window, a run with a working resume set stores nothing once caught up — which is exactly what the weekly runs do now.

Flags

FlagDefaultDescription
--forcefalseReprocess every advisory regardless of stored hash
--limit0Maximum advisories to process (0 = unlimited)

There is no --emit-crit: unlike alas-rss-processor, this processor stages no CRIT candidates.

Failure modes

  • Plaintext HTTP. feedURL (main.go:42) is http://, not https://, so the 4.8 MB advisory document — from which CVSS vectors, package lists and CVE linkage are derived — is fetched unauthenticated and unencrypted and is trivially tamperable in transit. https://mirrors.aliyun.com serves the same path.
  • A whole-feed parse failure is not quarantined. fetchFeed retries 3 times and then os.Exit(1) (main.go:151-156) without writing the body to the quarantine prefix, so a feed-format change leaves no artefact to inspect.
  • Soft deadline margin. main.go:129 reserves a hardcoded 10 minutes and main.go:175 stops 5 minutes earlier still, so 15 of the 30 budgeted minutes are unavailable. Not currently harmful (a caught-up run finishes in seconds), and the deadline is correctly skipped entirely when EXPECTED_DURATION_MINUTES is unset, so backfills do run to completion.
  • No ALINUX3 feed exists. alinux3.xml is a 404. If Alibaba publishes one, add a sibling processor rather than a second feed here — the source slug alibaba-cloud currently means “Alibaba Cloud Linux 2” and nothing else.

S3 Persistence

Compliant. The generator printed “Not used” here because this slug was missing from scripts/docs/s3-status.yaml; the entry has been added (cf. ORCH-09).

  • Archive path: alibaba-cloud/files/{sha256}/{advisoryId}.jsonuploader.ArchiveRecord(ctx, alinux2Source, payload) at main.go:234, success path only, guarded on a non-empty marshalled payload.
  • Quarantine path: failed-feeds/alinux2-rss-processor/{YYYY-MM-DD}/store-error/{advisoryId}.jsonmain.go:229.
  • Failure reasons emitted: store-error only. Whole-feed parse-error is not emitted — see Failure modes.

Skipped entirely when S3_BUCKET_NAME is unset — s3client.NewFromEnv returns a nil uploader and both methods are nil-receiver no-ops.