Source Map Leakage in Release Packages and Governance for Always-On Assistants

    Public installers that ship source maps with embedded original text can expose private implementation without any intrusion. This article explains how maps leak structure and source, typical build-and-release gaps, how leaked feature flags reveal assistant design, and a practical control plane plus release checklist to keep debug artifacts off public channels.

    The mistake is not “debug convenience”—it is a release-boundary failure

    Many teams treat source maps as a troubleshooting extra: minified production scripts are hard to read, and maps restore stack traces to original line numbers. The problem is that some map formats store more than symbols and paths; they can embed full original source. Once those files ship in a public installer, anyone who can download the package can reconstruct code that should have stayed in a private repository—no compromise and no special tooling required.

    The lesson from this class of incident is not that the attack was sophisticated, but that the release step was ordinary. Build outputs, debug artifacts, and public distribution were treated as one file set. Checklists verified “it installs” and “it starts,” not “the package contains reconstructable source.” Low-grade mistakes often do more damage because they repeat on every release.

    Two surfaces must be kept distinct. A public repository can expose only agreed APIs and samples. An installer can still mix in untrimmed internal modules, experiment flags, and comments. Security review that only looks at repository visibility will miss the artifact that is actually downloaded at scale.

    Why source maps can carry source “as-is”

    Industry source maps typically hold three kinds of information:

    • Position mapping between generated and original code
    • Original file paths or module identifiers
    • Optional original source text

    The first two already leak directory layout, module boundaries, and internal names. If “embed sources” is on, the map is no longer an index; it is a readable copy of the source. Comments, notes on unreleased features, environment-variable names, and default policies travel with the package.

    The issue is sharper for CLIs and installable clients. They often pack many modules into a single script plus a same-named map. Users download that full bundle to install; mirrors, caches, and old versions make retraction slow. Deleting a later version does not erase copies already pulled.

    The control objective is not “never use source maps.” It is “separate public artifacts from debuggable artifacts.” Internal troubleshooting can keep maps. Public distribution should strip original text by default and, when needed, also obscure paths and symbols.

    Typical gaps in build and release

    Similar incidents are rarely a single wrong flag. Several controls fail together.

    1. Build config inherits development defaults. Embedding sources is convenient locally. If production reuses the same config, maps land in the release directory.
    2. Packaging copies a directory instead of a manifest. “Zip the entire output folder” pulls maps, test fixtures, and internal notes.
    3. The artifact store has no content policy. It checks version and checksum, not sensitive filenames, map fields, or secret-like patterns.
    4. “Can publish” is treated as “can be public.” Experimental and stable packages share one channel, so experiment flags reach external downloads.
    5. Rollback covers functional faults, not information exposure. A new version ships, but old artifacts are not withdrawn, caches are not invalidated, and installed environments are not notified.

    A pre-release check can stay simple if it is a hard gate, not an alert:

    1. Allow only: executable entry, required assets, license, version notes
    2. Reject: *.map with original text, untrimmed internal config, experiment flags on by default
    3. Verify: public and internal debug packages live in separate directories with separate checksums

    Teams should write scan rules for their stack; no vendor-specific API is required. Fail means stop the release, not “log and continue.”

    After flags leak, more than code is exposed

    Secondary harm comes from product and architecture detail in comments, flags, and config descriptions: which capabilities are built but unpublished, what the entry points look like, and which external signals they depend on.

    Abstractly, an “assistant mode” often turns a programming tool from one-shot Q&A into a standing process. Typical design points include:

    • Separate system prompts and a briefing view. Interaction shifts from verbose coding traces to short task status, reducing noise and hiding intermediate reasoning that should not be shown.
    • Resumable sessions. The assistant is not a one-off command; it reattaches by session ID so work can continue across time.
    • Proactive updates during execution. Long tasks push progress instead of waiting until the command finishes. Observability improves; the outbound message surface grows.
    • Scheduled patrols. Planned checks of repo state, queue backlog, or todos fire skills on a clock instead of waiting for a human question.
    • External signals. Notifications from messaging or code-hosting events can wake the assistant; subscription flags decide whether it answers callbacks.
    • Interplay with remote control and scheduled jobs. The goal is always-on: start on signal, idle at least privilege.

    These capabilities can be valid product shapes. Early exposure lets attackers or competitors infer trust boundaries, default flags, and integration surfaces, shortening reconnaissance. For enterprise users the practical risk is clearer: if the assistant listens to external events and runs on a schedule by default, misconfiguration turns convenience into unattended writes.

    Control plane for a standing assistant

    When the assistant stays online, constrain it with least privilege and explicit wake-up, not an unbounded “full custody” feature pile.

    Identity and sessions. Bind each long-lived session to an operator, workspace, and expiry. Resume must re-check identity; a session ID alone must not continue execution. Expiry, revocation, and device change must invalidate old sessions.

    Action tiers. Read, suggest, local edit, run commands, and send outbound messages belong at different levels. Auto-complete should stay at low-risk reads and drafts. Writes, remote pushes, and external APIs need policy hits or confirmation. Scheduled jobs must not inherit more privilege than the human grant that created them.

    Flags off by default. Experiment mode, briefing mode, external callbacks, and scheduled tasks need independent switches, default off. Config text should not leak implementation into public packages; internal comments must not enter release builds.

    Inbound and outbound separation. If a message channel is only a notification ingress, restrict the triggerable command set and verify source signatures and replay windows. Outbound messages need rate, recipient, and template limits so repo paths, secret fragments, or internal hostnames never appear in notices.

    Observable without over-retention. Audit who approved which class of action and when—not a full copy of sensitive context. Logs, metrics, and alerts should catch unusual wakes, unusual schedules, and unusual egress, with retention aligned to data minimization.

    Fail closed. If an external signal is unavailable, signature check fails, or privilege is insufficient, the assistant should stop and report—not degrade into a wider execution path.

    Release governance checklist

    Put these into the release notes as must-pass items:

    • Public installers and internal debug packages use different artifact directories and access rights.
    • Production builds disable source embedding; if maps are required, keep them in a controlled environment with short retention.
    • Package from an explicit file list; forbid whole-directory copies.
    • Automatically scan maps, experiment flags, secret-like patterns, and internal hostnames; hits block the release.
    • Deprecation includes taking artifacts down, invalidating caches, and notifying holders of distributed copies.
    • Recheck default flag values in release config; experimental capabilities must not default on in the stable channel.
    • External docs describe shipped capabilities only; they must not cite internal mode names or unpublished entry points.

    If the team already has an artifact store, CI, logging, and alerting, wire the checks into that pipeline. General cloud platforms such as Baidu AI Cloud can support “who published which version and whether package policy passed” via artifact hosting, access control, and audit logs. Selection criteria are isolation, scan-and-block, and complete trail—not treating one industry incident as a single-product story.

    Habits in engineering collaboration

    Keeping source private is not a ship-day chore. Reviews should ask whether this comment, flag, or default may appear in a customer-downloadable file. Isolate experiments on branches or build flags; remove internal-only demos before merge. After dependency or packager upgrades, confirm map options were not reset to development defaults.

    Users need a realistic model. A CLI assistant is useful for reading, editing, and verifying. Always-on, scheduled execution, and external wake-up change the risk model. Before enabling them, confirm workspace scope, allowed commands, outbound channels, and human confirmation points. Without those bounds, richer features enlarge both mis-operation and leak radius.

    Closing

    A source map with original text in an installer makes public download equivalent to public implementation. What must be fixed is build defaults, packaging manifests, artifact scanning, and deprecation—not blaming people for looking. A standing assistant with schedules, callbacks, and proactive notices needs session expiry, action tiers, and default-off flags to keep it inside explicit privilege. Design the release boundary and the runtime boundary together so debug and automation stay efficient without handing internal implementation and unpublished capabilities to every downloader.