Skip to content

Security hardening: prevent code injection and improve error handling#35

Merged
tomtom215 merged 7 commits into
mainfrom
claude/audit-production-codebase-gjrgQ
Apr 9, 2026
Merged

Security hardening: prevent code injection and improve error handling#35
tomtom215 merged 7 commits into
mainfrom
claude/audit-production-codebase-gjrgQ

Conversation

@tomtom215
Copy link
Copy Markdown
Owner

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 source commands 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 source commands for loading configuration files with safe key=value parsing that validates variable names and strips quotes

    • lyrebird-updater.sh: Safe parsing of service state marker files
    • lyrebird-alerts.sh: Safe loading of alert configuration with LYREBIRD_ prefix validation
    • lyrebird-diagnostics.sh: Fixed YAML validation to use argument passing instead of string interpolation
  • JSON Escaping: Added json_escape() function in lyrebird-alerts.sh to 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=strict
    • Added kernel and control group protection
    • Added memory limits (1G for audio service, 512M for MediaMTX)
    • Fixed log file paths to use consistent naming

Error Handling & Robustness

  • Arithmetic Operations: Added || true to all arithmetic increment operations (((var++))) to prevent failures in strict mode (set -e)

    • Applied across all scripts: updater, stream-manager, mic-check, orchestrator, diagnostics, metrics
  • Trap Management: Replaced unsafe eval of trap strings with direct trap re-installation in transaction_rollback() to prevent arbitrary code execution

  • Process Management:

    • Fixed wait command handling to properly capture exit codes without relying on implicit status
    • Added safe PID reading with validation in stream-manager
    • Improved HTTP code validation with regex check before arithmetic comparison
  • Temporary Files:

    • Added secure temp file creation with proper permissions (600) in lyrebird-alerts.sh
    • Added cleanup traps for temp files in generate_mediamtx_config()
  • Input Validation:

    • Added numeric validation for heartbeat timestamps to prevent arithmetic crashes on corrupted files
    • Fixed path validation to require trailing slash match preventing false positives
    • Added guards against division by zero in progress bar calculations

Code Quality

  • Fixed multiple instances of unsafe string interpolation in Python/Perl commands
  • Improved guard clause ordering in lyrebird-common.sh to prevent readonly variable errors on re-sourcing
  • Removed unnecessary disown call in spinner function
  • Fixed progress bar overflow when current exceeds total
  • Improved countdown timer to use arithmetic assignment instead of decrement operator

Implementation Details

  • All configuration parsing now uses explicit key validation with regex patterns (e.g., ^[A-Z_][A-Z_0-9]*$)
  • JSON escaping is centralized in a single function for consistency
  • Arithmetic operations are made safe for use with set -e without changing script behavior
  • Trap restoration uses explicit function calls instead of eval to prevent code injection
  • All temporary files are created with restrictive permissions and proper cleanup handlers

https://claude.ai/code/session_01VLuWBVjLP54eb8sJx5VSXv

claude added 7 commits April 6, 2026 15:19
- 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
@tomtom215 tomtom215 merged commit 564d269 into main Apr 9, 2026
7 checks passed
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.

2 participants