Split out of #12, where CodeRabbit flagged the same class in a different step.
The exposure
Bump pin in pyproject.toml does:
python3 - <<EOF
from pathlib import Path
p = Path("pyproject.toml")
text = p.read_text()
text = text.replace(
'upstream-version = "${FROM}"',
'upstream-version = "${TO}"',
1,
)
...
EOF
The heredoc delimiter is unquoted (<<EOF, not <<'EOF'), so the shell expands ${FROM} and ${TO} into the Python source before python runs. They are not Python variables — they are textual substitution into a program.
to_version originates outside this repo: scripts/refresh-upstream.sh reads it from the upstream release feed. A version string containing a single quote terminates the Python string literal; one containing a newline plus arbitrary statements injects code that runs with the workflow's contents: write token.
Same root cause as the one fixed in #12 — an externally-sourced value pasted in as syntax rather than passed as a value — just a different substrate (Python source instead of a shell command line).
Why it was not fixed in #12
The remedy changes the bump logic itself (quote the heredoc, pass the values via os.environ), and the workflow is currently dead (#11), so that edit cannot be exercised end-to-end. Every other change in #12 is mutation-verified; adding an untestable edit to it would have weakened the whole PR. Filing instead of quietly absorbing.
Suggested fix
FROM="$FROM" TO="$TO" python3 - <<'PY'
import os, re
from pathlib import Path
frm, to = os.environ["FROM"], os.environ["TO"]
p = Path("pyproject.toml")
text = p.read_text()
text = text.replace(f'upstream-version = "{frm}"', f'upstream-version = "{to}"', 1)
text = text.replace(f'"latitudesh-python-sdk=={frm}"', f'"latitudesh-python-sdk=={to}"', 1)
p.write_text(text)
PY
Quoted delimiter (<<'PY') stops shell expansion entirely; os.environ keeps the values as data.
Worth pairing with
A sanity check on to_version right where it is produced, so nothing downstream has to be defensive — upstream versions should match something like ^[0-9]+(\.[0-9]+)*([a-z0-9.\-]*)$, and anything else should fail the run loudly rather than flow into a shell, a Python heredoc, and a git ref name.
Split out of #12, where CodeRabbit flagged the same class in a different step.
The exposure
Bump pin in pyproject.tomldoes:The heredoc delimiter is unquoted (
<<EOF, not<<'EOF'), so the shell expands${FROM}and${TO}into the Python source before python runs. They are not Python variables — they are textual substitution into a program.to_versionoriginates outside this repo:scripts/refresh-upstream.shreads it from the upstream release feed. A version string containing a single quote terminates the Python string literal; one containing a newline plus arbitrary statements injects code that runs with the workflow'scontents: writetoken.Same root cause as the one fixed in #12 — an externally-sourced value pasted in as syntax rather than passed as a value — just a different substrate (Python source instead of a shell command line).
Why it was not fixed in #12
The remedy changes the bump logic itself (quote the heredoc, pass the values via
os.environ), and the workflow is currently dead (#11), so that edit cannot be exercised end-to-end. Every other change in #12 is mutation-verified; adding an untestable edit to it would have weakened the whole PR. Filing instead of quietly absorbing.Suggested fix
Quoted delimiter (
<<'PY') stops shell expansion entirely;os.environkeeps the values as data.Worth pairing with
A sanity check on
to_versionright where it is produced, so nothing downstream has to be defensive — upstream versions should match something like^[0-9]+(\.[0-9]+)*([a-z0-9.\-]*)$, and anything else should fail the run loudly rather than flow into a shell, a Python heredoc, and a git ref name.