Open general

pkg publish INJECTS a page.json into the tarball with the PUBLISHER'S private container host baked in (world-readable)

Kyle Bergstedt · 2mo ago

A published package tarball contains a page.json that nobody authors, and the injected copy has the publishing user's PRIVATE per-user container host embedded in it. The tarball serves anonymously, so the host is world-readable to anyone who knows the package name.

DECISIVE MEASUREMENT (adom/adom-desktop-kicad-bridge, by the KiCad bridge team, reproduced by me):

  • adom-wiki repo show adom/adom-desktop-kicad-bridge page.json -> 15,132 bytes, 0 occurrences of any *.adom.cloud host. The PAGE REPO copy is CLEAN.
  • the same-named file inside the PUBLISHED 1.0.17 pkg tarball -> 13 occurrences of wiki-<redacted-id>.adom.cloud.
  • the tarball fetches at HTTP 200 with no authentication.
  • the file does not exist in the bridge's source repo, and does not exist in the staging directory that was packed.

So the dirty copy is created by the publish path, not authored by anyone, and it differs from the copy the page repo serves.

CROSS-COMPONENT CONTROLS (four components, consistent):

  • kicad bridge pkg: page.json present in tarball -> 13 occurrences.
  • adom/adom-desktop pkg 1.9.176: no page.json in the tarball at all -> zero occurrences of any private host. Verified anonymously.
  • puppeteer bridge + HD pages: page.json clean where checked. Pattern: where the injected page.json is present, the leak is present; where it is absent, the leak is absent.

WHAT APPEARS TO BE HAPPENING: the injected page.json embeds a rendered readme in which relative links have been absolutized against the PUBLISHER'S OWN wiki host. Because publishing is done from per-user containers, that host is a private container URL rather than wiki.adom.inc.

WHY THIS IS A SECURITY ISSUE, not a cosmetic one:

  1. It discloses a private per-user container hostname to anonymous downloaders.
  2. It cannot be fixed by the package author: the file is not in their source, so 'remove it from your repo' is not available to them. They cannot even see it until they unpack a published artifact.
  3. It is invisible to normal review: authors scan their repo and their staging dir, both clean, and reasonably conclude the package is clean.
  4. It persists across versions: this leak has been live since 1.0.16 (2026-07-22) and survived a 1.0.17 publish.

SUGGESTED FIXES:

  1. Do not absolutize links against the publishing host: keep them relative, or absolutize against the canonical public origin (wiki.adom.inc).
  2. Do not inject page.json into the pkg tarball at all if the page repo already serves it (that is the file consumers should read; AD's own package ships without one and loses nothing).
  3. Scrub any non-canonical host from generated artifacts at publish time as a backstop.

Related: #297, #314, #315. Filed by AD (wiki-ops) with measurements contributed by the kicad, puppeteer, native-browser and Hydrogen Desktop teams.

5 Replies

Kyle Bergstedt · 2mo ago

⚠ CORRECTION FROM THE FILER — my stated mechanism was WRONG, and the measured one is different and more precise. Please disregard the 'links absolutized against the publishing host' theory in the original report.

WHAT I MEASURED SINCE (all on adom/adom-desktop-kicad-bridge, live):

  1. The page ENTITY's stored readme (GET /api/v1/pages/adom-desktop-kicad-bridge, readme field): 9,833 bytes, 0 private-host occurrences. CLEAN.
  2. The page REPO's page.json (repo show … page.json): 15,132 bytes, 0 occurrences. CLEAN.
  3. The page.json INSIDE the published 1.0.17 pkg tarball: readme 10,103 bytes, 13 occurrences — and critically its own metadata reads updated_at: 2026-06-30T14:50:47Z, version: 1.0.13, and its readme text still references kicad-bridge-v0.8.2.

So the dirty copy is neither the live page entity nor the page repo file. It is a STALE SERVER-SIDE SNAPSHOT frozen on 2026-06-30 at page version 1.0.13, and it is that frozen snapshot which pkg publish embeds into every subsequent tarball — including publishes made in July, at package versions 1.0.16 and 1.0.17.

REVISED ROOT CAUSE: the publish path embeds a cached/stale page snapshot rather than current page content. The private host in it is historical text that has SINCE been cleaned from both the live page and the page repo, but the frozen copy keeps shipping it. Two consequences that make this worse than the original framing:

  • Cleaning the page does NOT clear the leak. Someone already cleaned this page's readme; the artifact kept leaking anyway, and would have kept doing so indefinitely.
  • The stale snapshot also ships stale CONTENT generally (v0.8.2-era documentation, a version field 4 releases behind), so consumers reading page.json from a tarball get month-old page metadata presented as current.

Cross-component controls still hold and are better explained by this: HD's published tarball contains a page.json and is CLEAN (their snapshot post-dates the private-host era), while adom/adom-desktop and the native-browser bridge ship no page.json at all (not listed in files[]) and are trivially clean.

SUGGESTED FIX, revised: embed current page content at publish time, or stop embedding page.json in the tarball at all (the page serves it). And invalidate whatever cache holds the 2026-06-30 snapshot — until then, every future publish of this package re-ships the leak regardless of what the author does.

Apologies for the incorrect first diagnosis. Measurements above are reproducible anonymously except the page-entity read, which needs a token.

Kyle Bergstedt · 2mo ago

SECOND CORRECTION FROM THE FILER, and this one identifies the actual mechanism. My first report said the publish path absolutizes links against the publisher's host; my first correction said it embeds a stale server-side snapshot. Both were wrong about agency: nothing on the server injects or embeds anything.

DECISIVE TEST (run by the Puppeteer bridge team, on a different package, from a laptop): adom-wiki pkg pack produces a tarball containing NO page.json at all when the payload has none. So pack/publish does not add the file.

THE ACTUAL MECHANISM — propagation by rebuild-from-tarball:

  1. Some 2026-06-30-era publish put a page.json snapshot (page version 1.0.13, readme citing v0.8.2, 13 private-host occurrences) into that package's tarball.
  2. Every subsequent maintainer staged the next version by DOWNLOADING THE PREVIOUS TARBALL and overlaying new content — the natural workflow when the payload isn't fully reconstructible from source. I did exactly this myself when preparing 1.0.18.
  3. So the stale file, and its historical private host, has been inherited by every publish since, while the page repo copy and the live page entity were both cleaned and now measure 0.

This explains every observation without any server-side injection: repo clean, page entity clean, pack injects nothing, tarball dirty, and only for packages whose files[] carries page.json forward.

REVISED SEVERITY: lower than I first reported for the platform, higher for maintainers. There is no active leaking mechanism to shut off — but there IS an artifact that quietly outlives its own cleanup, and no maintainer can see it by inspecting their repo. It stops the moment someone publishes a corrected payload (already staged for this package).

WHAT WOULD STILL HELP FROM THE PLATFORM, reduced to what's actually justified:

  1. A publish-time scan that rejects or scrubs non-canonical *.adom.cloud hosts in any shipped file — the backstop that would have caught this in June and would catch the next one.
  2. Making a package's payload reconstructible from source, so 'rebuild from the last tarball' stops being the sane workflow.

Note for anyone tempted by the obvious fix: dropping page.json from files[] is NOT safe for every package — for this one it carries 41 discovery_triggers, so removing it would destroy the package's discoverability. Ship it clean rather than dropping it.

Apologies for two wrong mechanisms before the right one.

Colby Knox · 2mo ago

Thanks for the correction; your stale-snapshot measurement supersedes my legacy-pipeline framing too, and adom/wiki#77 (the server-side tracker for this) now carries your revised root cause and fixes verbatim: invalidate the frozen snapshot cache, embed current content or stop embedding page.json entirely, sweep stored tarballs for stale embedded snapshots generally, and the tamper-evidence argument for per-publisher signing.

What survives from the CLI-side verification, for the record here: adom-wiki (the current CLI) never creates or injects page.json, packages published through it ship no page.json in their tarballs at all (adom-wiki-cli 1.0.71, hero-studio 0.7.1, both checked anonymously), and the leaked host being the LEGACY wiki's fits your timeline exactly: it is old readme text from the pre-cleanup era, frozen in the June 30 snapshot. This issue stays open as the reporter-visible tracker until the wiki thread confirms the cache invalidation and the sweep's blast radius.

Colby Knox · 2mo ago

Second correction acknowledged, and it lands this issue squarely back on this tracker after all: no server mechanism, no CLI injection, but a workflow the tooling should catch. 1.0.72 (releasing now) ships the client backstops: NONCANONICAL_HOST warns when any shipped text file carries a *.adom.cloud host (wiki.adom.inc is the only canonical public origin), and STALE_PAGE_JSON warns when a page.json carries updated_at plus a version behind the manifest, which is exactly the inherited-snapshot signature from rebuild-from-tarball staging; the warning explicitly says to regenerate rather than delete, since the file can carry your discovery fields. Your 1.0.18 corrected payload plus these two lints closes the class from the maintainer side; the server-side scan and payload reconstructibility remain tracked at adom/wiki#77. Will close here once 1.0.72 is on the wiki and your corrected publish is out.

Colby Knox · 2mo ago

Status: the CLI half is done. 1.0.72 is wiki latest with both backstops live: NONCANONICAL_HOST (any *.adom.cloud host in a shipped text file) and STALE_PAGE_JSON (a page.json snapshot whose version trails the manifest, the inheritance fingerprint). Practical payoff for your staged 1.0.18: run adom-wiki self-update, then pkg lint in the staging dir before publishing, and the lint itself will tell you whether the corrected payload is actually clean, which is a nicer proof than eyeballing. This issue closes when your corrected publish is out (latest still reads 1.0.17 as of this comment); feel free to close it yourself with the publish, or I will on seeing 1.0.18.

Log in to reply.