Summary
A package blocked during docker build is the most security-relevant event PMG produces, and it currently never reaches SafeDep Cloud under any configuration. The system install docs note the symptom ("a failed build uploads nothing"); this issue is about closing the gap.
Follow-up from #363.
Why no configuration can deliver it today
Verified on main:
- The ephemeral flow (what the shims invoke in a
RUN step) only buffers events to the local WAL (internal/flows/proxy_flow.go → audit.LogSessionComplete). There is no synchronous delivery in this path; the periodic sync + shutdown flush exist only in the long-running proxy daemon (internal/proxyserver/server.go), which is not what runs here.
- Delivery for ephemeral runs is a detached fire-and-forget
pmg cloud sync-background child spawned post-run (main.go → audit.MaybeSpawnBackgroundSync, internal/audit/background_sync.go). On a block, the parent exits non-zero, the RUN step fails, BuildKit tears down the build container, and the detached child dies before it can resolve credentials or complete a round trip.
- The WAL lives in the build container's filesystem, which is discarded with the failed build, so the event cannot be recovered afterwards either.
Consequences:
- The documented pattern (credentials mounted only on a final
pmg cloud sync step) cannot report blocks: that step never runs in a failed build.
- Mounting BuildKit secrets on the install
RUN steps does not help either, because of (2).
Net effect: Package Guard sees a build's successful installs, but never the one event that matters most — a malicious package caught in CI.
Summary
A package blocked during
docker buildis the most security-relevant event PMG produces, and it currently never reaches SafeDep Cloud under any configuration. The system install docs note the symptom ("a failed build uploads nothing"); this issue is about closing the gap.Follow-up from #363.
Why no configuration can deliver it today
Verified on
main:RUNstep) only buffers events to the local WAL (internal/flows/proxy_flow.go→audit.LogSessionComplete). There is no synchronous delivery in this path; the periodic sync + shutdown flush exist only in the long-running proxy daemon (internal/proxyserver/server.go), which is not what runs here.pmg cloud sync-backgroundchild spawned post-run (main.go→audit.MaybeSpawnBackgroundSync,internal/audit/background_sync.go). On a block, the parent exits non-zero, theRUNstep fails, BuildKit tears down the build container, and the detached child dies before it can resolve credentials or complete a round trip.Consequences:
pmg cloud syncstep) cannot report blocks: that step never runs in a failed build.RUNsteps does not help either, because of (2).Net effect: Package Guard sees a build's successful installs, but never the one event that matters most — a malicious package caught in CI.