Skip to content

Commit 331bb5d

Browse files
committed
chore(xport): adopt null-prototype merge maps from sdxgen canonical
Cascade sdxgen's prototype-pollution hardening in `mergeManifests`: use `Object.create(null)` for the upstream + site merge maps so untrusted manifest keys can't poison Object.prototype. All 6 repos ship byte-identical xport.mts.
1 parent 8c8141b commit 331bb5d

1 file changed

Lines changed: 11 additions & 4 deletions

File tree

scripts/xport.mts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,20 @@ function loadManifestTree(rootManifestPath: string): {
186186
areas.push({ area, manifest: sub })
187187
}
188188

189-
const mergedUpstreams: Record<string, Upstream> = {}
190-
const mergedSites: Record<string, Site> = {}
189+
// Null-prototype objects prevent prototype-pollution via untrusted
190+
// manifest keys. Object.create(null) + a plain-object cast works
191+
// under both relaxed and strict (exactOptionalPropertyTypes) tsconfigs.
192+
const mergedUpstreams = Object.create(null) as Record<string, Upstream>
193+
const mergedSites = Object.create(null) as Record<string, Site>
191194
const mergedRows: Row[] = []
192195
// Include order, root last so it wins on duplicate keys.
193196
for (const { manifest } of [...areas.slice(1), ...areas.slice(0, 1)]) {
194-
Object.assign(mergedUpstreams, manifest.upstreams ?? {})
195-
Object.assign(mergedSites, manifest.sites ?? {})
197+
for (const [k, v] of Object.entries(manifest.upstreams ?? {})) {
198+
mergedUpstreams[k] = v
199+
}
200+
for (const [k, v] of Object.entries(manifest.sites ?? {})) {
201+
mergedSites[k] = v
202+
}
196203
}
197204
for (const { manifest } of areas) {
198205
mergedRows.push(...manifest.rows)

0 commit comments

Comments
 (0)