Security hardening: prevent code injection and improve error handling#35
Merged
Conversation
- Fix division-by-zero crash in lyrebird_progress_bar when total=0 - Fix ((count++)) set -e crashes across all scripts (returns exit 1 when count is 0, killing the script under set -e) - Fix lost exit codes via `local exit_code=$?` pattern in orchestrator (local resets $? to 0) - Fix dead code: `if ! func; then code=$?` always captures 0, not the function's exit code (stream-manager monitor, updater service update) - Fix uninitialized COMMAND variable in stream-manager cleanup trap (crashes under set -u on early errors) - Fix command injection in diagnostics YAML validation via python3/perl -c with interpolated filenames - Fix unsafe `source` of marker file in updater (replaced with safe key=value parser to prevent code injection) - Fix pgrep -f self-match in diagnostics (could report wrong PID) - Fix spinner subprocess orphan leak (removed disown) - Fix temp file + config lock leak on write failure in stream-manager - Fix log path mismatch: service file pointed to /var/log/lyrebird/ but script defaults to /var/log/lyrebird-stream-manager.log - Enable systemd security hardening (NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp, memory limits) - Fix readonly before include guard in lyrebird-common.sh https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
The bare call to validate_mediamtx_config would cause the entire diagnostics script to silently exit under set -e when the config file has invalid YAML (a normal diagnostic finding, not a crash). https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
- Fix CRITICAL: Replace unsafe `source` of config file in alerts with safe key=value parser to prevent arbitrary code execution - Fix HIGH: Add json_escape() helper and escape all interpolated values in webhook payloads (generic, Discord, Slack) to prevent JSON injection - Fix HIGH: Pass filename as argv instead of interpolating into python3 -c string in install_mediamtx.sh parse_github_release - Fix HIGH: Require trailing slash in path prefix match in storage validate_safe_path to prevent /tmp-evil matching /tmp prefix - Fix MEDIUM: Use mktemp with chmod 600 in alerts interactive_setup instead of predictable /tmp/lyrebird-alerts.conf path https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
- Fix HIGH: systemctl daemon-reload piped through grep always reported failure on success (grep returns 1 on no output, pipefail propagates it), causing service updates to abort on every run - Fix: Replace eval of saved trap strings with direct trap re-install to eliminate fragile eval pattern in rollback path https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
- Fix HIGH: force_stop_mediamtx used raw cat instead of read_pid_safe to read PID file, bypassing numeric/range validation before SIGKILL - Fix MEDIUM: http_code from curl could be empty or non-numeric on timeout/connection failure, crashing under set -e on comparison https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
Corrupted or empty heartbeat file would cause bash arithmetic error and crash the metrics collection under set -e. https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv
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
This PR implements comprehensive security hardening across the LyreBird codebase, focusing on preventing code injection vulnerabilities and improving error handling robustness. The changes replace unsafe
sourcecommands with safe key=value parsing, add proper JSON escaping, fix arithmetic operations in strict mode, and enhance systemd service security configurations.Key Changes
Security Improvements
Code Injection Prevention: Replaced all
sourcecommands for loading configuration files with safe key=value parsing that validates variable names and strips quoteslyrebird-updater.sh: Safe parsing of service state marker fileslyrebird-alerts.sh: Safe loading of alert configuration with LYREBIRD_ prefix validationlyrebird-diagnostics.sh: Fixed YAML validation to use argument passing instead of string interpolationJSON Escaping: Added
json_escape()function inlyrebird-alerts.shto properly escape special characters (backslashes, quotes, newlines, tabs, carriage returns) in all webhook formatters (generic, Discord, Slack)Systemd Hardening: Enabled security features in service files:
NoNewPrivileges=yes,ProtectHome=yes,PrivateTmp=yes,ProtectSystem=strictError Handling & Robustness
Arithmetic Operations: Added
|| trueto all arithmetic increment operations (((var++))) to prevent failures in strict mode (set -e)Trap Management: Replaced unsafe
evalof trap strings with direct trap re-installation intransaction_rollback()to prevent arbitrary code executionProcess Management:
waitcommand handling to properly capture exit codes without relying on implicit statusTemporary Files:
lyrebird-alerts.shgenerate_mediamtx_config()Input Validation:
Code Quality
lyrebird-common.shto prevent readonly variable errors on re-sourcingdisowncall in spinner functionImplementation Details
^[A-Z_][A-Z_0-9]*$)set -ewithout changing script behaviorhttps://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv