Skip to content

Add an automation-friendly command-line version (continues #394) - #670

Open
Alex123666tw wants to merge 6 commits into
morkt:masterfrom
Alex123666tw:cli
Open

Add an automation-friendly command-line version (continues #394)#670
Alex123666tw wants to merge 6 commits into
morkt:masterfrom
Alex123666tw:cli

Conversation

@Alex123666tw

Copy link
Copy Markdown

This continues @Bioruebe's #394 (a new command-line version of GARbro), rebased onto current master, with changes that make the CLI usable as a child process driven by other tools.

What's here

  • The CLI (i identify / f formats / l list / x extract) from Added new command line version #394 by @Bioruebe — both commits cherry-picked with their original authorship preserved.
  • Subprocess hardening on top:
    • Non-interactive file handling: add -y/-s/-r, and fall back to overwrite automatically when stdin is redirected. The previous code blocked on Console.ReadKey() with no way to answer from a script.
    • Real exit codes: PrintError now sets Environment.ExitCode, and extraction returns non-zero when files are skipped (it always exited 0 before).
    • Output hygiene: banner / progress / warnings / errors go to stderr so the i/l data on stdout is clean to parse; add -q.
    • Remove a leftover debug print of the first entry offset; fix an inverted filter check in the non-archive path.
  • Build fix: drop the legacy <Import ...\.nuget\NuGet.targets> + EnsureNuGetPackageBuildImports gate from GameRes / ArcFormats / GUI so the solution builds on modern MSBuild via nuget restore (the .nuget folder is not in the tree).

Verified

Built Console + GameRes + ArcFormats (Release) with VS Build Tools 2022. On a SoftPal PAC/AMUSE archive, the extracted SCRIPT.SRC / TEXT.DAT / POINT.DAT are byte-for-byte identical (SHA-256) to reference output.

Note

This is also maintained, with prebuilt Windows releases, at https://github.com/Alex123666tw/garbro-cli (MIT). Happy to split commits, narrow the scope, or drop the build/doc parts if you'd prefer a more minimal PR.

Bioruebe and others added 4 commits June 30, 2026 22:11
…Get.targets

The MSBuild-integrated package restore (Import of .nuget\NuGet.targets plus
the EnsureNuGetPackageBuildImports guard target) predates automatic restore
and breaks on modern toolchains because the .nuget folder is not committed.
Packages are restored with nuget restore (or Visual Studio), so drop the
gate from GameRes, ArcFormats and GARbro.GUI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This command-line build is meant to be driven as a child process, but a few
behaviours made that unreliable:

- The overwrite prompt blocked on Console.ReadKey() with no way to answer
  from a script. Add -y/--overwrite, -s/--skip and -r/--rename, and fall
  back to overwrite when stdin is redirected (no interactive console).
- The process always exited 0, even on failure. PrintError now sets
  Environment.ExitCode, and extraction returns non-zero when files are skipped.
- Banner, progress, warnings and errors went to stdout and polluted the
  machine-readable i/l output. Route them to stderr; add -q/--quiet.
- Remove a leftover debug print of the first entry offset.
- Fix an inverted filter check in the non-archive code path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Alex123666tw and others added 2 commits July 1, 2026 13:53
Archive entry names are attacker-controlled. CreateNewFile combined the
entry name into the output directory without containment, so an entry
named with ..\ segments or an absolute path could write outside the
chosen output directory (arbitrary file write).

Resolve the output root and the target path to full paths and reject any
target that does not sit under the output root (case-insensitive, with a
trailing separator to avoid sibling-prefix bypass). The thrown
UnauthorizedAccessException is caught by the per-entry catch (Exception)
in Archive_ExtractFiles, so a malicious entry is skipped and the process
exits non-zero rather than crashing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…k -if

(a) In the non-archive path, the "Converting <fmt> audio" progress line
    and the "All OK" success line were written to stdout, contaminating
    the clean-stdout contract that parent processes rely on. Route both
    to stderr (the archive path already does this).

(b) The -if switch read args[i] without checking for a missing value,
    throwing IndexOutOfRangeException. Add the same bounds check already
    used by -o and -f: PrintError + return when the value is absent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Alex123666tw

Copy link
Copy Markdown
Author

Pushed two follow-up commits to this branch:

  • fix(console): prevent path traversal in archive extractionCreateNewFile combined the archive entry name with the output directory with no containment check, so an archive whose entry names contain ..\..\ or an absolute path could write outside the -o directory (arbitrary file write). Added a guard that resolves the full path and rejects anything not under the output root, with a trailing-separator check to block outout-evil sibling-prefix bypass. Offending entries are skipped and the process exits non-zero rather than writing out of bounds.
  • fix(console): route non-archive extract status to stderr; bounds-check -if — keep x stdout clean by sending Converting… / All OK on the non-archive path to stderr (the archive path already did this), and add a missing-value bounds check for -if matching the existing -o / -f handling.

Verified with a byte-for-byte extraction regression (a real SoftPal data.pac → the extracted files are SHA-256-identical to a known-good baseline) and the traversal guard checked against normal / sub-dir / ..\..\ / absolute / sibling-prefix inputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants