#!/usr/bin/expect -f # Script to cycle through password history on macOS # Usage: ./cycle_passwords.exp if {$argc != 2} { puts "Usage: $argv0 " puts "This script will change your password 25 times to clear history," puts "then set it to your target password." exit 1 } set current_pass [lindex $argv 0] set target_pass [lindex $argv 1] set username [exec whoami] # Generate 24 temporary passwords (we'll use target as #25) proc generate_temp_password {index} { return "TempPass${index}![clock seconds]" } puts "=========================================" puts "Starting password history cycling for user: $username" puts "This will perform 25 password changes" puts "=========================================" puts "" set timeout 10 # Function to change password proc change_password {old_pw new_pw iteration} { global username puts "Attempt $iteration/25: Changing password..." puts " New password: $new_pw" spawn passwd expect { timeout { puts "ERROR: Timeout waiting for Old Password prompt" exit 1 } "Old Password:" { send "$old_pw\r" } } expect { timeout { puts "ERROR: Timeout waiting for New Password prompt" exit 1 } "New Password:" { send "$new_pw\r" } } expect { timeout { puts "ERROR: Timeout waiting for Retype New Password prompt" exit 1 } "Retype New Password:" { send "$new_pw\r" } } # Wait for the warning message and command completion expect { timeout { puts "ERROR: Timeout waiting for completion" exit 1 } -re ".*WARNING.*" { # Got the keychain warning, wait for prompt to return expect { -re "\[#$%>\] $" { # Back at shell prompt } timeout { # Warning displayed but prompt detection failed, that's ok } } } -re "\[#$%>\] $" { # Back at shell prompt (in case warning doesn't appear) } } # Small delay to ensure change is committed sleep 0.5 puts " ✓ Successfully changed (iteration $iteration)" puts "" return $new_pw } # Perform 24 intermediate changes for {set i 1} {$i <= 24} {incr i} { set temp_pass [generate_temp_password $i] set current_pass [change_password $current_pass $temp_pass $i] } # Final change to target password puts "Final change (25/25): Setting to target password..." puts " New password: $target_pass" change_password $current_pass $target_pass 25 puts "" puts "=========================================" puts "SUCCESS: Password history cleared" puts "Your password is now set to: $target_pass" puts "Entra sync should now succeed" puts "=========================================" puts "" puts "NOTE: The login keychain password was NOT updated by this script." puts "If needed, run: security set-keychain-password" exit 0