mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-16 08:59:26 +00:00
Step 1's own bash and PowerShell fragments both built a command whose
literal text was the resolved scan path, substituted verbatim by the
agent following the instructions before that line ever ran. The bash
form, echo dollar paren cd INPUT_PATH and pwd close paren, still
expands a command substitution even inside the outer double quotes,
and the cd itself was entirely unquoted; the PowerShell form passed
INPUT_PATH as a bare unquoted argument to Resolve Path, exposed to the
same class of problem through a stray semicolon or pipe. A path drawn
from an untrusted source, a malicious readme's suggested command, a
copied value from an untrusted page, executed as code the moment this
line ran, before any Python was ever reached.
Both now capture INPUT_PATH through a construct their own interpreter
guarantees performs no expansion at all: a quoted bash heredoc for the
posix form, a single quoted PowerShell here string for the windows
form. The raw text reaches Python (respectively Resolve Path) only as
inert data on standard input, never as source the shell itself
parses. Verified for the posix form by actually executing the
extracted Step 1 block with a malicious substituted value and
confirming no injected command runs; the PowerShell form could not be
executed in this environment (no interpreter available to install
without an interactive credential prompt), so it was written using
well established, unambiguous here string syntax and reviewed
carefully rather than run.
As a side effect of no longer building the path through an unquoted
cd, a legitimate path containing a space is now handled correctly
too, and a nonexistent path now fails the whole step loudly instead
of silently continuing past a swallowed cd error.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
(cherry picked from commit 9a7e5d0a51)
3.2 KiB
3.2 KiB
# Detect Python with graphify — uv/pipx-aware (fixes #831)
New-Item -ItemType Directory -Force -Path graphify-out | Out-Null
$GRAPHIFY_PYTHON = $null
function Find-GraphifyPython {
# 1. uv tool install — 'uv tool dir' is authoritative, respects UV_TOOL_DIR automatically
if (Get-Command uv -ErrorAction SilentlyContinue) {
$uvDir = (uv tool dir 2>$null).Trim()
if ($uvDir) {
$py = Join-Path $uvDir "graphifyy\Scripts\python.exe"
if (Test-Path $py) {
& $py -c "import graphify" 2>$null
if ($LASTEXITCODE -eq 0) { return $py }
}
}
}
# 2. pipx install — 'pipx environment' respects PIPX_HOME automatically
if (Get-Command pipx -ErrorAction SilentlyContinue) {
$venvs = (pipx environment --value PIPX_LOCAL_VENVS 2>$null).Trim()
if ($venvs) {
$py = Join-Path $venvs "graphifyy\Scripts\python.exe"
if (Test-Path $py) {
& $py -c "import graphify" 2>$null
if ($LASTEXITCODE -eq 0) { return $py }
}
}
}
# 3. Active venv / conda / pip-into-current-env
$pyCmd = Get-Command python -ErrorAction SilentlyContinue
if ($pyCmd) {
& $pyCmd.Source -c "import graphify" 2>$null
if ($LASTEXITCODE -eq 0) {
return (& $pyCmd.Source -c "import sys; print(sys.executable)").Trim()
}
}
return $null
}
# Try to find the right Python (uv → pipx → active env)
$GRAPHIFY_PYTHON = Find-GraphifyPython
# Not found — install then re-detect
if (-not $GRAPHIFY_PYTHON) {
if (Get-Command uv -ErrorAction SilentlyContinue) {
uv tool install --upgrade graphifyy -q 2>&1 | Select-Object -Last 3
} else {
pip install graphifyy -q 2>&1 | Select-Object -Last 3
}
$GRAPHIFY_PYTHON = Find-GraphifyPython
}
# Save interpreter path — all subsequent steps read this.
# `Out-File -Encoding utf8` always writes a BOM on Windows PowerShell 5.1 (utf8NoBOM
# only exists from PowerShell 6), and that BOM rides into the saved path, so the hook
# rebuild fails with WinError 123 (#3028). WriteAllText with an explicit BOM-less
# encoding writes the bytes POSIX writes, and adds no trailing newline.
$Utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText((Join-Path $PWD 'graphify-out\.graphify_python'), [string]$GRAPHIFY_PYTHON, $Utf8NoBom)
# Save scan root so `graphify update` (no args) knows where to look next time.
# INPUT_PATH is captured through a single-quoted (literal) here-string, never
# substituted directly into the command line: an unquoted bareword argument
# substituted here would let a malicious path (a stray `;`, `|`, or `$(...)`)
# execute as script code the moment this line runs.
$InputPathRaw = @'
INPUT_PATH
'@
[System.IO.File]::WriteAllText((Join-Path $PWD 'graphify-out\.graphify_root'), (Resolve-Path $InputPathRaw.Trim()).Path, $Utf8NoBom)
If the import succeeds, print nothing and move straight to Step 2.
In every subsequent block, run Python through the saved interpreter — & (Get-Content graphify-out\.graphify_python) in place of a bare python3 — so every step uses the interpreter that actually has graphify.