Fix 16 HIGH/MEDIUM security bugs across API

HIGH fixes:
- TOTP disable now requires valid code verification
- TOTP secret removed from plaintext file storage
- Container ID validated before update/check-update/logs operations
- DNS server parameter restricted to configured servers (SSRF prevention)
- Backup export no longer includes encryption key
- Backup restore of sensitive files requires TOTP re-authentication

MEDIUM fixes:
- Session cookie Secure flag added
- Caddy reload errors no longer leaked to client
- saveConfig uses atomic locked updates via configStateManager
- Log file path traversal prevented via symlink resolution
- Credential cache entries now expire after 5 minutes
- _httpFetch enforces 10MB response size limit
- External URL path injection into Caddyfile blocked
- Custom volume host paths validated against allowed roots
- Error logs endpoint no longer returns stack traces
- Logo delete path traversal prevented via path.basename()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-07 00:15:28 -08:00
parent 6979302fb7
commit 59b6d7d360
12 changed files with 172 additions and 69 deletions

View File

@@ -44,7 +44,7 @@ module.exports = function(ctx) {
// Update container to latest image version
router.post('/:id/update', ctx.asyncHandler(async (req, res) => {
const containerId = req.params.id;
const container = ctx.docker.client.getContainer(containerId);
const container = await getVerifiedContainer(containerId);
// Get container info
const containerInfo = await container.inspect();
@@ -124,7 +124,7 @@ module.exports = function(ctx) {
// Check for available updates (compares local and remote image digests)
router.get('/:id/check-update', ctx.asyncHandler(async (req, res) => {
const containerId = req.params.id;
const container = ctx.docker.client.getContainer(containerId);
const container = await getVerifiedContainer(containerId);
const containerInfo = await container.inspect();
const imageName = containerInfo.Config.Image;