Repository navigation
fix: accurate prune sizes, shared-image and revert tracking, and security hardening - #103
Merged
Merged
Conversation
…rity hardening Prune reported each leftover image's WHOLE size (Docker's `Size` includes base layers still used by current images), so the preview and the "Freed X" message were wildly inflated. Now: - preview shows what each image really frees (Size minus layers shared with other images; SharedSize taken from the unfiltered list, since Docker only computes it among the images in the same response) - "Freed X" is measured (image-layer disk usage before/after) - untagged images still used by a container are no longer offered - prune-all counts images, not untag/layer entries - revert points whose image was pruned are dropped (and Revert refuses cleanly with 410 if its image is gone), and the Settings badge refreshes Found by running the app against a real Docker daemon: - containers on a tag that moved (sibling updated first) or that were reverted reported "up to date" forever; reverted standalone containers couldn't be updated (pull of a bare image ID) - revert copied Compose's image label, so a later compose update was a silent no-op; also added a force-recreate safety net - no revert point / blank history versions when the old image's digest was unknown (tracked by image ID now; versions stored on history rows) - loopback registries (localhost:5000) are spoken to over http, like Docker Security: - CSRF: state-changing API calls require an X-DockPull header (SameSite=Lax doesn't cover other apps on the same host) - container names validated before reaching the Docker API - session cookie bound to ADMIN_PASSWORD (changing it signs everyone out) - registry credentials only sent to https token servers Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KiL5R3bRpvGk6QP3E21eHF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Prune was over-reporting (the "15 GB")
Docker's image
Sizeis the whole image, including base layers still used by your current images. The preview and the "Freed X" message summed those, so they were wildly inflated. In a reproduction on real Docker, three leftovers showed 1.26 GB when they actually freed 60 MB.SharedSizeamong images in the same response, so it's taken from the unfiltered list.410) if its image is gone.Bugs found by running the app against a real Docker daemon
docker pull sha256:….com.docker.compose.imagelabel, so a later compose update silently did nothing. That label is fixed now, and there's a force-recreate safety net aftercompose up.localhost:5000) are now queried over http, as Docker does.Security
X-DockPull: 1header.SameSite=Laxdoesn't protect against other apps on the same host on a different port.ADMIN_PASSWORD, so changing the password signs everyone out. Existing sessions need to log in once after upgrading.Testing
docker system df🤖 Generated with Claude Code
https://claude.ai/code/session_01KiL5R3bRpvGk6QP3E21eHF
Generated by Claude Code