fix: fail closed when no safe export destination exists; polish salvage edges
- _profile_export_directory(): when the managed store, the home-sibling store, AND the temp dir all resolve inside Git checkouts, raise a clear ValueError instead of warning and proceeding — a stderr warning would not stop a scripted export from staging a secret-bearing archive in a source tree, which is the exact #92457 incident class. All three callers already surface ValueError cleanly (CLI/TUI print Error: + exit, API returns 400). - .dockerignore: drop the /default.tar.gz line made redundant by the global *.tar.gz pattern this PR adds. - hermes profile export -o help text: stop advertising the old <name>.tar.gz cwd default. - Tests: cwd-in-unrelated-checkout topology (the second production shape from the blocking review) and the fail-closed path. Mutation-checked: both fail on the pre-fix helper.
This commit is contained in:
@@ -2154,13 +2154,14 @@ def _profile_export_directory() -> Path:
|
||||
for candidate in candidates:
|
||||
if not _inside_git_checkout(candidate):
|
||||
return candidate
|
||||
logger.warning(
|
||||
"Every managed export destination resolves inside a Git checkout; "
|
||||
"falling back to %s. Pass an explicit output path to avoid staging "
|
||||
"profile archives in a source tree.",
|
||||
export_dir,
|
||||
# Fail closed: writing a secret-bearing archive into a source tree is the
|
||||
# incident this helper exists to prevent (#92457). A warning on stderr
|
||||
# would not stop a scripted export from recreating it.
|
||||
raise ValueError(
|
||||
"No safe automatic export destination: every candidate directory is "
|
||||
"inside a Git checkout. Pass an explicit output path outside the "
|
||||
"checkout (e.g. -o /path/outside/repo/profile.tar.gz)."
|
||||
)
|
||||
return export_dir
|
||||
|
||||
|
||||
def get_profile_export_path(name: str, *, timestamp: Optional[str] = None) -> Path:
|
||||
|
||||
Reference in New Issue
Block a user