security: harden against local attack vectors#35
Merged
graykode merged 6 commits intograykode:mainfrom Apr 18, 2026
Merged
Conversation
- Verify PID command before kill to prevent TOCTOU race - Abort kill if ps check fails (fail-closed) - Skip symlinks in session, transcript, and subagent file reads - Symlink check defaults to true on error (fail-closed) - Add visited set to all process tree walkers to prevent infinite loops - Cap token_history and JSONL line buffer to prevent OOM - Validate CLAUDE_CONFIG_DIR as existing directory - Atomic write for summary cache (temp + rename) - Harden statusline hook setup (exact match, 0o700) - Download update installer to file before executing - Validate cwd as directory before git operations - Sanitize --once output to strip terminal escape sequences - Redact common secret patterns in tool arg display - Truncate deserialized session fields at char boundaries
Follow-up to 4cd51e2 - three issues a paranoid re-read of the hardening commit turned up. - Download update installer via tempfile::NamedTempFile instead of a predictable /tmp/abtop-installer.sh path. Prevents a local attacker from pre-planting a symlink at the fixed path and redirecting the curl -o write (symlink clobber + post-download swap). Promotes the tempfile crate from [dev-dependencies] to [dependencies]. - Cap read_line allocation with take(MAX_LINE_BYTES + 1) instead of checking line length after the fact. The previous check fired only after read_line had already grown the buffer unbounded, so a single 10GB-no-newline transcript line would OOM the process before the cap engaged. On cap hit, skip to end-of-file for this tick; the file_identity reset picks it up if the transcript is later replaced. - Extend sanitize_output to strip Unicode bidi overrides (U+202A-U+202E, U+2066-U+2069, U+200E, U+200F) in addition to control characters. Closes a Trojan Source (CVE-2021-42574) vector where an LLM-generated task description or session cwd containing RTLO could visually reorder text in --once output.
Pre-existing code flagged by newer Rust toolchain in CI. Collapses the if-guard into the match arm pattern as clippy suggests.
…-attack-surface # Conflicts: # src/collector/codex.rs
- run_update: shasum (macOS default) first, fall back to sha256sum (coreutils). Previously sha256sum alone silently failed on macOS, so the "Show checksum so the user can verify" line was never printed on the primary target OS. - sanitize_output: remove `|| *c == ' '` dead branch. Space is not a control character, so the OR never fired; expression simplifies to `!c.is_control()`.
The original PR hardened Claude's transcript parser but left Codex exposed to the same local attack vectors. Bring Codex to parity: - Extract redact_secrets into collector/mod.rs and expand coverage: add sk-proj-, sk-or-, ghs_, ghr_, ghu_, github_pat_, xoxa-, xoxs-, rk_live_, rk_test_, ASIA, and "Bearer " prefixes. - Cap codex JSONL line reads at 10 MB via take(MAX+1) + read_line, matching the Claude transcript parser. Prevents OOM from a malformed or hostile rollout file. - Cap codex token_history at 10,000 entries. - Redact secrets in codex function_call args and user_message prompts before they reach the TUI.
graykode
approved these changes
Apr 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Hardens abtop against local attack vectors. While abtop reads only local files with no network activity, the files it reads (session transcripts, JSONL logs, config) are writable by other processes on the same machine. A compromised or malicious Claude Code session could craft payloads targeting abtop's parsing.
Threat model
Local attacker with write access to
~/.claude/(e.g. malicious MCP server, compromised subagent, rogue extension) attempting: symlink exploitation, PID reuse for kill misdirection, OOM via crafted transcripts, terminal injection via bidi overrides, credential exfiltration via tool arg display, or installer supply chain hijack.Changes
Commit 1 - core hardening:
token_history(10K entries) and JSONL line buffer (10MB) to prevent OOMCLAUDE_CONFIG_DIRas existing directory before use0o700permissionscurl | sh)--onceoutput: strip terminal escape sequencessk-ant-,ghp_,gho_,glpat-,xoxb-,AKIA, ...) in tool arg displayCommit 2 - follow-up tightening:
/tmp/abtop-installer.shwithtempfile::NamedTempFile(O_EXCL + random suffix) to prevent symlink plantingread_linevia.take(MAX+1)instead of post-read check (the previous check fired after the buffer had already grown unbounded)sanitize_outputto strip Unicode bidi overrides (U+202A-U+202E, U+2066-U+2069, U+200E, U+200F) - closes CVE-2021-42574 Trojan Source vectorTesting
cargo clippy -- -D warnings- cleancargo test- 31/31 passcargo build --release- compiles, binary functionalabtop --oncewith active sessions, verified sanitized output