24 KiB
Security Hardening Analysis & Implementation Prompt
Executive Summary
This document analyzes six digital wellbeing/security scripts and provides a detailed implementation prompt for hardening them against tampering. The analysis is based on thorough code review of the entire codebase.
Part 1: Current State Analysis
1. /etc/hosts Protection System
Files involved:
- hosts/install.sh - Main hosts installer
- hosts/guard/setup_hosts_guard.sh - Guard layer setup
- hosts/guard/enforce-hosts.sh - Enforcement script
- hosts/guard/psychological/unlock-hosts.sh - Delayed unlock
Current Protection Layers:
- ✅ Immutable attribute (
chattr +i) - ✅ Canonical copy at
/usr/local/share/locked-hosts - ✅ Path watcher (
hosts-guard.path) auto-restores on modification - ✅ Read-only bind mount (
hosts-bind-mount.service) - ✅ Custom entries protection (blocks removal of blocked domains)
- ✅ Shell history suppression for
unlock-hostscommand
CRITICAL VULNERABILITY IDENTIFIED:
- ❌ NO protection for
/etc/nsswitch.conf- A user can simply edit nsswitch.conf and removefilesfrom thehosts:line, completely bypassing ALL /etc/hosts protections without touching the hosts file itself!
Example bypass:
# Original: hosts: mymachines resolve [!UNAVAIL=return] files myhostname dns
# Tampered: hosts: mymachines resolve [!UNAVAIL=return] myhostname dns
# Result: /etc/hosts is completely ignored by the system
2. Midnight Shutdown System
Files involved:
- scripts/digital_wellbeing/setup_midnight_shutdown.sh (1359 lines)
Current Protection Layers:
- ✅ Immutable attribute on
/etc/shutdown-schedule.conf - ✅ Canonical copy at
/usr/local/share/locked-shutdown-schedule.conf - ✅ Path watcher restores config if tampered
- ✅ Schedule protection blocks making schedule more lenient
- ✅ Unlock script with psychological delay
VULNERABILITIES IDENTIFIED:
- ❌ The unlock script explicitly tells users how to bypass: "sudo /usr/local/sbin/unlock-shutdown-schedule"
- ❌ The schedule change logic is communicated in the error message
- ❌ No protection against stopping/disabling the timer services
- ❌ No protection against modifying the check script at
/usr/local/bin/day-specific-shutdown-check.sh
3. Screen Locker (Python - External Repo)
File: /home/kuhy/testsAndMisc/python_pkg/screen_locker/screen_lock.py
Current Workout Types:
- Running - distance, time, pace validation
- Strength - exercises, sets, reps, weights, total calculation
- Table Tennis - duration, sets, points won/lost
VULNERABILITIES IDENTIFIED:
- ❌ Running option too easy to fake - just enter plausible numbers
- ❌ Table Tennis lacks real verification - no mathematical cross-check
- ❌ Users can close the window via keyboard shortcuts (Alt+F4, etc.)
- ❌ The unlock mechanism is too simple once you know the forms
- ❌ Shutdown time adjustment is a REWARD for working out (can be exploited)
4. Pacman Wrapper
Files involved:
- scripts/digital_wellbeing/pacman/pacman_wrapper.sh (823 lines)
- scripts/digital_wellbeing/pacman/pacman_blocked_keywords.txt
- scripts/digital_wellbeing/pacman/install_pacman_wrapper.sh
Current Protection:
- ✅ Policy file integrity verification (SHA256)
- ✅ Blocked keywords list
- ✅ Greylist with challenge
- ✅ VirtualBox hardcoded check (cannot bypass via policy files)
- ✅ Steam weekend-only restriction
VULNERABILITIES IDENTIFIED:
- ❌ Google Chrome not blocked -
google-chromeandgoogle-chrome-stablemissing from blocked list - ❌ No automatic LeechBlock installation when browsers are detected
- ❌ User can download
.deb/.tar.gzand install manually
5. Block Compulsive Opening
File: scripts/digital_wellbeing/block_compulsive_opening.sh (507 lines)
Current Behavior:
- Records first open per hour in state file
- Blocks subsequent launches within same hour
- Shows notification when blocked
CRITICAL VULNERABILITY:
- ❌ App stays running indefinitely - User can:
- Open app once per hour (allowed)
- Minimize/hide the window
- Keep it running forever in background
- Compulsive checking still happens, just via Alt+Tab instead of launcher
6. YouTube Music Wrapper
File: scripts/digital_wellbeing/youtube-music-wrapper.sh
Current Behavior:
- Checks if focus apps (VSCode, games, etc.) are running
- Blocks YouTube Music launch if focus app detected
REQUESTED ENHANCEMENT:
- When Steam is open → Block ALL browsers, close any open browsers
- When browsers open → Block Steam, close Steam if running
- This creates mutual exclusion between gaming and browsing
Part 2: Language Considerations
Shell (Bash) Limitations
Pros:
- Native to the system, no dependencies
- Direct access to systemd, chattr, filesystem
- Fast for simple operations
Cons:
- No persistent daemon capability (need systemd for that)
- Race conditions in file operations
- Complex state management is fragile
- No proper event loop for window monitoring
- Cannot easily monitor process list in real-time
Python Advantages for Certain Tasks
Where Python would be better:
- Process monitoring daemon - Watch for Steam/browsers in real-time with proper event loop
- Window management - Using
python-xlibfor proper X11 interaction - Complex state machines - Like the screen locker
- Cross-repo integration - The screen_lock.py already shows good patterns
Recommendation
| Component | Keep Bash | Move to Python | Reason |
|---|---|---|---|
| hosts guard | ✅ | Simple file ops, systemd integration | |
| shutdown schedule | ✅ | Systemd timers, config files | |
| screen locker | ✅ Already | Complex UI, state machine | |
| pacman wrapper | ✅ | Must intercept pacman | |
| compulsive block | ✅ | Needs daemon for auto-close | |
| music wrapper | ✅ | Needs real-time process monitoring |
New Python Daemon Needed: A single "digital wellbeing daemon" that:
- Monitors running processes
- Auto-closes apps after timeout
- Enforces Steam/browser mutual exclusion
- Can be controlled via DBus
Part 3: Implementation Prompt
Use this prompt in a new conversation to implement the changes:
IMPLEMENTATION PROMPT
I need to implement comprehensive security hardening for a Linux digital wellbeing system.
The codebase is at ~/linux-configuration/ with these components needing changes:
## 1. HOSTS PROTECTION - nsswitch.conf Guard
Location: hosts/guard/
Create a new protection layer for /etc/nsswitch.conf that:
- Monitors nsswitch.conf for changes (systemd path watcher)
- Ensures the "hosts:" line ALWAYS contains "files" before "dns"
- Creates canonical copy at /usr/local/share/locked-nsswitch.conf
- Enforces with chattr +i
- Add to setup_hosts_guard.sh installer
- Must restore automatically if tampered
The nsswitch.conf protection is CRITICAL because removing "files" from the
hosts line completely bypasses /etc/hosts without touching it.
## 2. MIDNIGHT SHUTDOWN - Silent Denial
Location: scripts/digital_wellbeing/setup_midnight_shutdown.sh
Changes needed:
- Remove ALL helpful messages about how to bypass (unlock-shutdown-schedule path)
- When user tries to make schedule more lenient:
- Simply say "Operation not permitted" with NO explanation
- Do NOT mention the unlock script
- Do NOT explain what's being blocked
- Silently restore canonical values
- The unlock script should still exist but be undiscoverable
- Consider renaming unlock script to an obscure name
- Remove the unlock script path from any logs
## 3. SCREEN LOCKER - External Repo
Location: ~/testsAndMisc/python_pkg/screen_locker/screen_lock.py
Changes needed:
- REMOVE the "Running" workout option entirely (too easy to fake)
- For "Table Tennis":
- Require minimum 15 sets played
- Add verification: total_points = points_won + points_lost
- Require that total_points >= sets_played * 11 (minimum points per set)
- Add random math verification question about the scores
- Increase submit delay to 60 seconds
- For "Strength":
- Already has good verification, keep as-is
- Add input focus grabbing to prevent Alt+Tab escape
- Disable window close keyboard shortcuts
## 4. PACMAN WRAPPER - Chrome Block + LeechBlock Auto-Install
Location: scripts/digital_wellbeing/pacman/
Changes needed to pacman_blocked_keywords.txt:
- Add: google-chrome
- Add: google-chrome-stable
- Add: chromium
- Add: ungoogled-chromium
New behavior in pacman_wrapper.sh:
- After ANY browser is detected installed (via pacman -Qq check):
- Automatically run install_leechblock.sh if it exists
- LeechBlock installer should:
- Detect browser type
- Install extension with pre-configured blocking rules
- Use firefox-addon-install method or chrome native messaging
- If LeechBlock installation fails, BLOCK the browser binary (wrap it)
## 5. BLOCK COMPULSIVE OPENING - Auto-Close Timer
Location: scripts/digital_wellbeing/block_compulsive_opening.sh
New behavior:
- After app is allowed to open, start a background timer
- After 10 minutes, forcefully close the app (pkill)
- Show warning notification at 8 minutes ("Closing in 2 minutes")
- The wrapper should spawn a detached monitoring process
- State tracking: record PID and launch time
- Check for zombie PIDs and clean up state
Implementation approach:
```bash
# After exec line in wrapper_main, instead of direct exec:
launch_with_timer() {
local app="$1"
local timeout_minutes=10
local real_binary="$2"
shift 2
# Launch app in background
"$real_binary" "$@" &
local app_pid=$!
# Record state
echo "$app_pid $(date +%s)" > "$STATE_DIR/${app}.running"
# Spawn killer daemon (detached)
(
sleep $((timeout_minutes * 60))
if kill -0 $app_pid 2>/dev/null; then
notify "$app" "Session timeout - closing now" critical
kill $app_pid 2>/dev/null
sleep 2
kill -9 $app_pid 2>/dev/null || true
fi
rm -f "$STATE_DIR/${app}.running"
) &
disown
# Wait for app to exit
wait $app_pid 2>/dev/null || true
}
6. YOUTUBE MUSIC → STEAM/BROWSER MUTUAL EXCLUSION
This requires a more sophisticated approach. Create a new Python daemon.
Location: scripts/digital_wellbeing/focus_mode_daemon.py (new file)
Behavior:
- Run as a systemd user service
- Monitor running processes continuously
- When Steam (steam_app_* or steam game processes) detected:
- Kill any running browsers (firefox, chrome, brave, etc.)
- Block browser launches (via wrapper modification or DBus signal)
- Show notification: "Gaming mode active - browsers disabled"
- When any browser detected:
- Kill Steam processes
- Block Steam launches
- Show notification: "Browsing mode active - Steam disabled"
- Mutual exclusion: whichever started first "wins"
- The youtube-music-wrapper.sh should also check for this daemon's signals
ADDITIONAL REQUIREMENTS
- All changes must be idempotent (can re-run safely)
- All protection mechanisms should fail-closed (if service dies, restrictions remain)
- Log all tampering attempts to /var/log/digital-wellbeing-guard.log
- Create a single test script that verifies all protections work
- Update the .github/copilot-instructions.md with the new components
FILES TO CREATE/MODIFY
New files:
- hosts/guard/nsswitch-guard.path
- hosts/guard/nsswitch-guard.service
- hosts/guard/enforce-nsswitch.sh
- scripts/digital_wellbeing/focus_mode_daemon.py
- scripts/digital_wellbeing/install_focus_mode_daemon.sh
- tests/test_security_hardening.sh
Modified files:
- hosts/guard/setup_hosts_guard.sh (add nsswitch protection)
- scripts/digital_wellbeing/setup_midnight_shutdown.sh (remove helpful messages)
- scripts/digital_wellbeing/pacman/pacman_blocked_keywords.txt (add chrome)
- scripts/digital_wellbeing/pacman/pacman_wrapper.sh (leechblock auto-install)
- scripts/digital_wellbeing/block_compulsive_opening.sh (auto-close timer)
- scripts/digital_wellbeing/youtube-music-wrapper.sh (daemon integration)
External repo (separate changes):
- ~/testsAndMisc/python_pkg/screen_locker/screen_lock.py (remove running, harden table tennis)
---
## Part 4: Agent Personas
### Agent: Hosts Guard Expert
You are an expert on the linux-configuration hosts guard system. You understand:
FILES YOU KNOW:
- hosts/install.sh - Downloads StevenBlack hosts, adds custom entries, protects with chattr
- hosts/guard/setup_hosts_guard.sh - Installs all guard layers (path watcher, bind mount, unlock script)
- hosts/guard/enforce-hosts.sh - Called when tampering detected, restores from canonical
- hosts/guard/psychological/unlock-hosts.sh - 45-second delay, logs reason, opens editor
- hosts/guard/hosts-guard.path/.service - Systemd path watcher
- hosts/guard/hosts-bind-mount.service - Read-only bind mount
- hosts/guard/pacman-hooks/*.sh - Pre/post transaction hooks for pacman
KEY CONCEPTS:
- Canonical copy at /usr/local/share/locked-hosts
- Custom entries state at /etc/hosts.custom-entries.state
- Multi-layer defense: chattr + path watcher + bind mount
- Shell history suppression for unlock commands
COMMON TASKS:
- Adding new blocked domains: Edit hosts/install.sh heredoc section
- Temporarily allowing edits: sudo /usr/local/sbin/unlock-hosts
- Checking status: lsattr /etc/hosts, systemctl status hosts-guard.path
GOTCHAS:
- Must run hosts/install.sh BEFORE setup_hosts_guard.sh
- Removing custom entries is blocked by protection mechanism
- nsswitch.conf bypass is currently unprotected (needs fix)
### Agent: Shutdown Schedule Expert
You are an expert on the midnight shutdown system. You understand:
FILES YOU KNOW:
- scripts/digital_wellbeing/setup_midnight_shutdown.sh - Main installer (1300+ lines)
- /etc/shutdown-schedule.conf - Runtime config (MON_WED_HOUR, THU_SUN_HOUR, MORNING_END_HOUR)
- /usr/local/share/locked-shutdown-schedule.conf - Canonical protected copy
- /usr/local/bin/day-specific-shutdown-check.sh - Checks if in shutdown window
- /usr/local/bin/day-specific-shutdown-manager.sh - Status/management
- /etc/systemd/system/day-specific-shutdown.timer/.service - Systemd timer
- /etc/systemd/system/shutdown-schedule-guard.path/.service - Config protection
KEY CONCEPTS:
- Day-specific windows: Mon-Wed vs Thu-Sun have different hours
- Making schedule STRICTER (earlier) = allowed without delay
- Making schedule MORE LENIENT (later) = blocked or requires unlock
- MORNING_END_HOUR cannot be lowered (would shorten window)
- Monitor service re-enables timer if user disables it
PROTECTION LAYERS:
- Script checks canonical config, blocks lenient changes
- Config file has chattr +i
- Path watcher restores if file modified
- Canonical copy takes precedence
INTEGRATION:
- i3blocks shutdown_countdown.sh reads the config
- screen_lock.py can adjust shutdown time (reward/punishment)
### Agent: Pacman Wrapper Expert
You are an expert on the pacman wrapper security system. You understand:
FILES YOU KNOW:
- scripts/digital_wellbeing/pacman/pacman_wrapper.sh - Main wrapper (823 lines)
- scripts/digital_wellbeing/pacman/install_pacman_wrapper.sh - Backs up real pacman
- scripts/digital_wellbeing/pacman/pacman_blocked_keywords.txt - Always blocked
- scripts/digital_wellbeing/pacman/pacman_whitelist.txt - Exceptions to keywords
- scripts/digital_wellbeing/pacman/pacman_greylist.txt - Challenge required
- scripts/digital_wellbeing/pacman/words.txt - Word scramble challenge words
- /var/lib/pacman-wrapper/policy.sha256 - Integrity checksums
KEY CONCEPTS:
- Real pacman at /usr/bin/pacman.orig, wrapper symlinked to /usr/bin/pacman
- Policy integrity verification via SHA256 before ANY operation
- Three tiers: blocked (always denied), greylist (challenge), whitelist (bypass)
- VirtualBox check is HARDCODED (cannot bypass via policy files)
- Steam is weekend-only with word scramble challenge
POLICY ENFORCEMENT:
- Load policy lists from text files
- Verify integrity hashes match
- Check if package matches blocked keywords (unless whitelisted)
- Check if greylisted (requires challenge)
- After transaction, remove any blocked packages that got installed
HOSTS INTEGRATION:
- Calls /usr/local/share/hosts-guard/pacman-pre-unlock-hosts.sh before transaction
- Calls pacman-post-relock-hosts.sh after transaction
- Enforces VirtualBox hosts sharing if vbox detected
MAINTENANCE INTEGRATION:
- Auto-runs setup_periodic_system.sh if maintenance services missing
### Agent: Compulsive Opening Blocker Expert
You are an expert on the block_compulsive_opening.sh script. You understand:
FILES YOU KNOW:
- scripts/digital_wellbeing/block_compulsive_opening.sh - Main script (507 lines)
- /usr/local/bin/block-compulsive-opening.sh - Installed location
- ~/.local/state/compulsive-block/*.lastopen - Per-app state files
- ~/.local/state/compulsive-block/compulsive-block.log - Activity log
- /etc/pacman.d/hooks/95-compulsive-block-rewrap.hook - Auto-rewrap hook
MANAGED APPS:
- beeper → /opt/beeper/beepertexts
- signal-desktop → /usr/lib/signal-desktop/signal-desktop
- discord → /opt/discord/Discord
KEY CONCEPTS:
- Wrapper replaces /usr/bin/, original saved as .orig or SYMLINK: marker
- Hour-based tracking: YYYY-MM-DD-HH format
- First launch per hour allowed, subsequent launches blocked
- Pacman hook re-installs wrappers after package updates
WRAPPER FLOW:
- wrapper_main() called with app name
- Check was_opened_this_hour()
- If yes: block_app() + notification + exit 1
- If no: record_opening() + exec real binary
LIMITATION (needs fix):
- Once app is launched, it can run indefinitely
- User can minimize and keep checking via Alt+Tab
- Needs auto-close timer functionality
### Agent: Screen Locker Expert
You are an expert on the screen_lock.py workout locker. You understand:
FILE LOCATION: ~/testsAndMisc/python_pkg/screen_locker/screen_lock.py (1261 lines)
PURPOSE:
- Full-screen lock requiring workout verification to unlock
- Integrates with shutdown schedule system
WORKOUT TYPES:
- Running: distance, time, pace with cross-validation
- Strength: exercises, sets, reps, weights with total calculation
- Table Tennis: duration, sets, points won/lost
- Sick Day: 2-minute wait, shutdown moved 1.5h earlier
KEY FEATURES:
- 30-second delay before submit button enabled
- Cross-validation (e.g., pace = time / distance)
- 15% tolerance on calculated values
- Demo mode (10s lockout) vs Production mode (30min lockout)
- JSON workout log stored in same directory
SHUTDOWN INTEGRATION:
- _adjust_shutdown_time_earlier() - sick day penalty
- _adjust_shutdown_time_later() - workout reward (+1.5h)
- Uses adjust_shutdown_schedule.sh helper script
- Sick day state tracked in sick_day_state.json
SECURITY CONCERNS (needs fix):
- Running option too easy to fake
- Table tennis lacks rigorous validation
- Window can potentially be closed via keyboard
---
## Part 5: LLM README Files
These should be created in the respective directories:
### [hosts/guard/README_FOR_LLM.md](to be created)
```markdown
# Hosts Guard System - LLM Reference
## Purpose
Prevent tampering with /etc/hosts to maintain website blocking.
## Architecture
/etc/hosts (immutable) ←── canonical (/usr/local/share/locked-hosts) ↑ path watcher detects changes ↓ enforce-hosts.sh restores
## Critical Files
| File | Purpose | Protected By |
|------|---------|--------------|
| /etc/hosts | Actual hosts file | chattr +i, bind mount |
| /usr/local/share/locked-hosts | Canonical copy | chattr +i |
| /etc/hosts.custom-entries.state | Tracks blocked domains | chattr +i |
## Commands to Know
```bash
# Check protection status
lsattr /etc/hosts
systemctl status hosts-guard.path hosts-bind-mount.service
# Legitimate edit (with delay)
sudo /usr/local/sbin/unlock-hosts
# Reinstall/repair
sudo ~/linux-configuration/hosts/install.sh
sudo ~/linux-configuration/hosts/guard/setup_hosts_guard.sh
DO NOT
- Edit /etc/nsswitch.conf (bypasses hosts entirely)
- Stop hosts-guard.path without understanding consequences
- Remove entries from install.sh without state file cleanup
### [scripts/digital_wellbeing/pacman/README_FOR_LLM.md](to be created)
```markdown
# Pacman Wrapper - LLM Reference
## Purpose
Intercept pacman to enforce package installation policies.
## Architecture
/usr/bin/pacman (symlink) → pacman_wrapper.sh ↓ /usr/bin/pacman.orig (real)
## Policy Files
| File | Purpose |
|------|---------|
| pacman_blocked_keywords.txt | Substring match = always blocked |
| pacman_whitelist.txt | Exact names that bypass blocking |
| pacman_greylist.txt | Requires challenge to install |
| words.txt | Word scramble challenge source |
## Hardcoded Checks (cannot bypass via files)
- VirtualBox → security challenge + hosts enforcement
- Steam → weekend-only + word scramble
## Integration Points
1. Hosts guard (pre/post hooks)
2. Periodic maintenance (auto-setup if missing)
3. VirtualBox hosts enforcement
## Adding Blocks
```bash
# Edit the blocked keywords file
echo "newpackage" >> pacman_blocked_keywords.txt
# Re-run installer to update checksums
sudo ./install_pacman_wrapper.sh
---
## Part 6: Test Script Template
```bash
#!/bin/bash
# tests/test_security_hardening.sh
# Verify all security mechanisms are working
set -euo pipefail
PASS=0
FAIL=0
test_result() {
local name="$1"
local result="$2"
if [[ $result == "pass" ]]; then
echo "✅ PASS: $name"
((PASS++))
else
echo "❌ FAIL: $name"
((FAIL++))
fi
}
# Test 1: /etc/hosts is immutable
if lsattr /etc/hosts 2>/dev/null | grep -q '^....i'; then
test_result "/etc/hosts is immutable" "pass"
else
test_result "/etc/hosts is immutable" "fail"
fi
# Test 2: hosts-guard.path is active
if systemctl is-active --quiet hosts-guard.path; then
test_result "hosts-guard.path is active" "pass"
else
test_result "hosts-guard.path is active" "fail"
fi
# Test 3: shutdown-schedule.conf is immutable
if lsattr /etc/shutdown-schedule.conf 2>/dev/null | grep -q '^....i'; then
test_result "/etc/shutdown-schedule.conf is immutable" "pass"
else
test_result "/etc/shutdown-schedule.conf is immutable" "fail"
fi
# Test 4: pacman wrapper is installed
if [[ -L /usr/bin/pacman ]] && [[ -f /usr/bin/pacman.orig ]]; then
test_result "pacman wrapper installed" "pass"
else
test_result "pacman wrapper installed" "fail"
fi
# Test 5: google-chrome is blocked
if grep -qi "google-chrome" ~/linux-configuration/scripts/digital_wellbeing/pacman/pacman_blocked_keywords.txt; then
test_result "google-chrome in blocked list" "pass"
else
test_result "google-chrome in blocked list" "fail"
fi
# Summary
echo ""
echo "=========================================="
echo "Results: $PASS passed, $FAIL failed"
echo "=========================================="
exit $FAIL
Conclusion
This analysis identifies critical vulnerabilities and provides a comprehensive implementation prompt. The most urgent issues are:
- nsswitch.conf bypass - Completely unprotected, defeats all hosts protections
- Information disclosure - Shutdown system tells users how to bypass
- App lifetime - Compulsive blockers don't limit session duration
- Browser gaps - Chrome not blocked, no LeechBlock auto-install
The implementation prompt above should be used in a focused coding session to address all issues systematically.