Skip to content

fix: pass values to Python as arguments and keep temporary files private - #173

Merged
CybotTM merged 14 commits into
mainfrom
fix/secfix-hardening
Oct 7, 2026
Merged

CybotTM merged 14 commits into
mainfrom
fix/secfix-hardening

Conversation

@CybotTM

@CybotTM CybotTM commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Merging this changes how the shell helpers hand values to Python, which endoflife.date cycles the collector accepts, where installers and the rollback generator keep temporary files, and how the Docker and Claude Code installer scripts are downloaded (curl held to HTTPS on every redirect). One behaviour changes for users: without curl, install_claude.sh no longer downloads the native installer with wget. install then falls through to Homebrew or npm; upgrade of an existing native installation fails without changing it, and upgrade of an npm installation keeps it and reports that curl is required. Everything else behaves as before for valid input.

Summary

  • scripts/lib/config.sh (config_get_auto_update, config_get_global_auto_upgrade), scripts/auto_update.sh (check_manager_outdated) and scripts/set_auto_update.sh run a fixed Python program from a quoted heredoc and pass the tool name, project root, config path, value and snapshot path as arguments.
  • cli_audit/collectors.py: collect_endoflife keeps a cycle only when the whole string has the shape of a release number (3.13, 24, 1.23), for the API response, the file cache and the offline cache. All cycles endoflife.date publishes today for go, nodejs, php, python and ruby have that shape.
  • github_release_binary.sh, docker_plugin.sh, install_docker.sh and install_claude.sh download into a directory that mktemp -d creates for the run (mode 0700, under $TMPDIR) and remove it afterwards. Installer markers for make upgrade default to ${XDG_CACHE_HOME:-~/.cache}/cli-audit/markers; CLI_AUDIT_MARKER_DIR still overrides it. The convenience-script downloads in install_docker.sh and install_claude.sh run curl with --proto '=https' --proto-redir '=https', so every redirect stays on HTTPS; install_claude.sh no longer falls back to wget for the native installer (wget cannot restrict redirects) and without curl moves on to the Homebrew and npm methods.
  • cli_audit/bulk.py: generate_rollback_script writes into a directory from tempfile.mkdtemp, creates the script with O_EXCL/O_NOFOLLOW and mode 0700, and quotes tool names with shlex.quote.
  • Tests: test_bulk.py and integration/test_e2e_install.py point tempfile at each test's tmp_path, so generated rollback scripts no longer stay in the system temp directory. The installer run in test_guide_multi_install.sh writes its marker into the suite's own directory.
  • CHANGELOG.md: a "Security" section under Unreleased.

Linked issues / PRs

Builds on #169.

Type of change

  • Bug fix (fix:)

Test plan

New tests. The ones marked (red) fail on the code before this change and pass here; the others pin behaviour that was already correct and must stay so:

  • tests/test_config_sh.py: a tool name with quotes and parentheses is looked up as a name (red); set_auto_update.sh stores such a key as written (red); per-cycle keys and the global preference are read, and a key written by set_auto_update.sh is found by the reader.
  • tests/test_endoflife_cycles.py: other shapes, a trailing newline included, are dropped from the API response and from the file cache (red); release-number cycles pass.
  • tests/test_github_release_binary.py: the download lands in a 0700 directory under $TMPDIR that is removed afterwards; the already-current marker is written under ~/.cache/cli-audit/markers (both red).
  • tests/test_installer_workdirs.py: the same for docker_plugin.sh, install_docker.sh (WSL path) and install_claude.sh (red); install_claude.sh upgrade without curl keeps an npm installation (red against the previous head of this branch, which removed it).
  • tests/test_bulk.py: the rollback script and its directory are owner-only, each call gets its own directory, tool names are single shell words (red).

Gates on the pushed head:

  • uv run pytest tests/ (1085 passed, 2 skipped)
  • uv run python -m flake8 cli_audit tests, black --check, isort --check-only, mypy cli_audit
  • bash tests/test_guide_multi_install.sh (52 passed), bash tests/test_reconcile_dryrun.sh (7 passed)
  • ./scripts/test_smoke.sh
  • shellcheck -x --severity=warning on every changed script

Checklist

  • Conventional Commits (type(scope): description)
  • Commits signed (git commit -S --signoff)
  • CHANGELOG.md updated for user-visible changes
  • Relevant AGENTS.md files updated if structure / commands changed (none)
  • No secrets, credentials, or PII committed

Assisted by claude-code:claude-opus-5-5 — Session

@CybotTM
CybotTM marked this pull request as ready for review October 7, 2026 07:26
Copilot AI balanced review requested due to automatic review settings October 7, 2026 07:26
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 3 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: aba9c877-c9f7-4d3c-906d-cc129e7c3aef
📥 Commits

Reviewing files that changed from the base of the PR and between 1083ab8 and 668c17b.

📒 Files selected for processing (19)
  • CHANGELOG.md
  • cli_audit/bulk.py
  • cli_audit/collectors.py
  • scripts/auto_update.sh
  • scripts/guide.sh
  • scripts/install_claude.sh
  • scripts/install_docker.sh
  • scripts/installers/docker_plugin.sh
  • scripts/installers/github_release_binary.sh
  • scripts/installers/package_manager.sh
  • scripts/lib/config.sh
  • scripts/set_auto_update.sh
  • tests/integration/test_e2e_install.py
  • tests/test_bulk.py
  • tests/test_config_sh.py
  • tests/test_endoflife_cycles.py
  • tests/test_github_release_binary.py
  • tests/test_guide_multi_install.sh
  • tests/test_installer_workdirs.py
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

Comment thread scripts/install_claude.sh Fixed
Comment thread scripts/install_claude.sh Fixed
Comment thread scripts/install_docker.sh Fixed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@CybotTM
CybotTM force-pushed the fix/secfix-hardening branch from 5df835b to 8b093cd Compare October 7, 2026 07:44
CybotTM added 11 commits October 7, 2026 09:49
config_get_auto_update, config_get_global_auto_upgrade and
check_manager_outdated built their Python program by pasting shell
values into the program text. They now run a fixed program from a quoted
heredoc and read the tool name, the project root and the snapshot path
from sys.argv, so any value is looked up as a plain string.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
collect_endoflife now keeps a cycle only when it has the shape of a
release number (3.13, 24, 1.23), for the API response as well as the
file cache and the offline cache. The cycle ends up in tool keys, binary
names and installer environment values.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
github_release_binary.sh, docker_plugin.sh, install_docker.sh and
install_claude.sh now download into a directory that mktemp -d creates
for the run (mode 0700, under $TMPDIR) and remove it when they finish.
Before, they used fixed or PID-derived names directly in /tmp.

The markers that installers leave for guide.sh (<tool>.already-current,
<tool>.held-back) now default to ${XDG_CACHE_HOME:-~/.cache}/cli-audit/markers
instead of /tmp/.cli-audit; CLI_AUDIT_MARKER_DIR still overrides it.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
generate_rollback_script now creates a directory of its own with
tempfile.mkdtemp (mode 0700) and creates the script there with
O_CREAT | O_EXCL | O_NOFOLLOW and mode 0700, instead of opening a
timestamp-named file directly in the temp directory and making it
world-readable. Tool names are written as single shell words
(shlex.quote), and as repr() in comments.

The rollback tests remove only a directory that generate_rollback_script
created.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
bulk_install generates a rollback script whenever a test enables it, and
those scripts stayed in the system temp directory after the run. An
autouse fixture points tempfile at the test's tmp_path.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
set_auto_update.sh, which guide.sh runs when the user presses 'a', built
its Python program from an unquoted heredoc. It now reads the config
path, the tool key and the value from sys.argv under a quoted heredoc,
like the readers in scripts/lib/config.sh.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
re.match with ^...$ accepts a final newline; fullmatch does not.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
The end-to-end case ran install_tool.sh without CLI_AUDIT_MARKER_DIR,
so its marker went to the user's cache and the check looked in a
directory the suite had already removed. The installer now writes into
the suite's directory, which is removed after that case.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
The convenience-script downloads in install_docker.sh and
install_claude.sh now pass --proto '=https' --proto-redir '=https' to
curl and --https-only to wget, as github_release_binary.sh already does.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@CybotTM
CybotTM force-pushed the fix/secfix-hardening branch from 8b093cd to 1b3688a Compare October 7, 2026 07:51
Comment thread scripts/install_claude.sh Fixed
install_claude.sh drops its wget fallback for the native installer: the
URL redirects, and only curl can restrict every redirect hop to HTTPS
(--proto-redir). Without curl the script reports it and moves on to the
Homebrew and npm methods, as it did when neither tool was present.
The non-WSL path of install_docker.sh now passes
--proto '=https' --proto-redir '=https' like the WSL path.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
upgrade_claude migrates an npm installation to the native installer by
removing the npm packages first. migrate_npm_to_native now checks for
curl, which the native installer needs, before it removes anything, and
otherwise keeps the npm installation and reports why.

Assisted-by: claude-code:claude-opus-5-5
Agent-Session: https://claude.ai/code/session_018YeAfZRDbYWzRMVUPmZDXj
Agent-Host: 0493f0
Signed-off-by: Sebastian Mendel <info@sebastianmendel.de>
@sonarqubecloud

sonarqubecloud Bot commented Oct 7, 2026

Copy link
Copy Markdown

@CybotTM

CybotTM commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Review note for head 668c17b: CodeRabbit is rate-limited on this head and Copilot is out of review quota, so the review was done by six independent reviewer passes, each with a bounded finding criterion (false claims, reproducible defects, repository rules, unfixed weaknesses).

  • Round 1 (5df835b): 4 findings: one more script pasting values into Python (set_auto_update.sh), a PR-body claim about red tests, the shell suite's installer marker, a trailing newline accepted in cycles. Fixed in the next commits.
  • Round 2 (8b093cd): 0 findings; three SonarCloud S6506 alerts on the installer downloads. Fixed by holding curl to HTTPS on redirects.
  • Round 3 (1b3688a): 2 findings: wget --https-only does not restrict redirects, and a commit message overstated a change. The wget fallback was removed.
  • Round 4 (f967333): 1 finding in the PR body (behaviour change not stated). Body corrected.
  • Round 5 (f967333): 2 findings: the body's upgrade description, and an npm install removed before a failing native install without curl. Fixed in 668c17b with a test.
  • Round 6 (668c17b): 0 findings. Re-ran the upgrade paths with and without curl, the full suite (1085 passed, 2 skipped), the red/green claims and the endoflife.date cycles.

All checks pass, 0 unresolved threads, 0 open code-scanning alerts.

Assisted by claude-code:claude-opus-5-5 — Session

@CybotTM

CybotTM commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Self-review: 668c17b

The bot review this pull request demands is unsatisfiable (Copilot quota wall or repeated bot failures on this head). The diff on this head was reviewed by the PR author; this comment is the on-the-record attestation the merge gate reads back. It stops matching on the next push.

@CybotTM
CybotTM merged commit d61b555 into main Oct 7, 2026
25 checks passed
@CybotTM
CybotTM deleted the fix/secfix-hardening branch October 7, 2026 08:13
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.

3 participants