Skip to content

Severe audit: fix Backup API runtime failure and unsafe backup path containment #65

Description

@rolling-codes

Summary

Follow-up audit found severe Backup API issues that can either break backup/restore endpoints at runtime or allow backup restore/delete path checks to match unintended sibling directories.

Findings

1. Severe: Backup endpoints require JobQueue, but LocalApi does not register it

BackupEndpoints calls:

ctx.RequestServices.GetRequiredService<JobQueue>()

for backup create, restore, and job status. However LSPDFRManager.LocalApi/Program.cs builds the app without registering JobQueue in DI.

Impact: backup create/restore/status endpoints can fail at runtime with a missing service exception instead of creating or returning job state.

Expected fix: register JobQueue before builder.Build():

builder.Services.AddSingleton<JobQueue>();

Add endpoint tests that boot the Local API and call:

  • POST /api/v1/backups
  • POST /api/v1/backups/restore
  • GET /api/v1/jobs/{jobId}

2. Severe: Backup restore/delete containment check uses unsafe prefix matching

Backup restore/delete resolve a target path and check:

resolvedPath.StartsWith(resolvedRoot, StringComparison.OrdinalIgnoreCase)

without forcing resolvedRoot to end with a directory separator. A sibling path such as C:\Backups2\file.zip can match root C:\Backups by string prefix.

Impact: a crafted backup file name can pass containment logic for unintended sibling directories if routing/model binding provides the path segment in a compatible form.

Expected fix: use a robust containment helper, for example:

var root = Path.GetFullPath(backupPath)
    .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
    + Path.DirectorySeparatorChar;
var candidate = Path.GetFullPath(Path.Combine(root, request.FileName));
if (!candidate.StartsWith(root, StringComparison.OrdinalIgnoreCase))
    return Results.BadRequest("Invalid file name.");

Also reject rooted file names, path separators where only a file name is expected, and non-.zip extensions before file I/O.

Acceptance criteria

  • JobQueue is registered in LocalApi DI.
  • Backup create/restore/status endpoint tests pass without missing-service exceptions.
  • Restore/delete path containment cannot match sibling directories.
  • Rooted paths and traversal-like file names are rejected.
  • Tests cover sibling-prefix cases such as C:\Backups vs C:\Backups2.

Audit note

This issue intentionally tracks only severe bugs. Lower-severity diagnostics such as stale health version or misleading display messages should be handled separately if desired.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions