github-password-rotator
Use when a GitHub account password needs to be changed or rotated, or when Codex should log in to GitHub security settings so the user can manually change 2FA/passkeys. Applies when Codex should prefi
SKILL.mdskills/github-password-rotator/SKILL.md
GitHubGitHub Password Rotator
Boundaries
- Never pass GitHub passwords on the command line.
- Never print, store, commit, or summarize old passwords, new passwords, 2FA codes, cookies, or session tokens.
- Never print, store, commit, or summarize TOTP/2FA secrets from
2fa.fun. - Use an isolated Chrome profile and the HTTP proxy for the whole browser flow. Default proxy:
http://127.0.0.1:11111. - Treat 2FA, passkeys, CAPTCHA, unusual verification, and suspended-account pages as manual user steps.
- Do not claim the password changed unless the script reports completion or the user confirms success in the browser.
- For 2FA/passkey changes, use
--login-only; do not run the password-change flow and try to avoid the password form at runtime.
Standard Flow
For logging in to GitHub security settings without changing the password, use
--login-only. This keeps the isolated browser open after the helper reaches
https://github.com/settings/security:
read -rsp 'Current GitHub password: ' GITHUB_CURRENT_PASSWORD; echo
export GITHUB_CURRENT_PASSWORD
python3 skills/github-password-rotator/scripts/rotate_github_password.py \
--github-login username \
--login-only \
--manual-timeout-seconds 900
unset GITHUB_CURRENT_PASSWORD
Use this mode when the user wants to manually change 2FA, passkeys, recovery methods, or other security settings. The helper only logs in, handles sudo password confirmation when detected, and stops before any password-change form.
Use environment variables or hidden TTY prompts for both passwords:
read -rsp 'Current GitHub password: ' GITHUB_CURRENT_PASSWORD; echo
read -rsp 'New GitHub password: ' GITHUB_NEW_PASSWORD; echo
read -rsp 'GitHub TOTP secret for 2fa.fun: ' GITHUB_TOTP_SECRET; echo
export GITHUB_CURRENT_PASSWORD GITHUB_NEW_PASSWORD GITHUB_TOTP_SECRET
python3 skills/github-password-rotator/scripts/rotate_github_password.py \
--github-login username \
--manual-timeout-seconds 900 \
--auto-2fa-fun \
--create-learning-repo
unset GITHUB_CURRENT_PASSWORD GITHUB_NEW_PASSWORD GITHUB_TOTP_SECRET
The helper:
- Opens
https://github.com/settings/securityin an isolated Chrome profile through the proxy. - Fills the GitHub login page with
--github-loginand the current password. - If
--auto-2fa-funis set and GitHub shows an app-code 2FA prompt, opens or reuseshttps://2fa.fun/, enters the TOTP secret, reads the generated code frominput.faotp.value, and submits it to GitHub without printing the code. - Waits for the user to complete passkey, device verification, CAPTCHA, suspended-account inspection, or any 2FA step that cannot be handled from
2fa.fun. - Handles GitHub sudo password confirmation with the current password when detected.
- Fills the password-change form with current password, new password, and confirmation.
- Exits successfully after GitHub reports success, or after a submitted password form collapses back to the
Change passwordstate without an explicit success message. - Navigates back to
https://github.com/settings/securityafter a completed submit so browser refresh will not resubmit the password form. - When
--create-learning-repois set, waits a random 3-10 seconds after the password change before creating the repository, then createshello-world-from-<account-slug>and writes a beginner-friendly EnglishREADME.md.
Useful Options
--github-login USER: required GitHub username or email.--current-password-env NAME: defaults toGITHUB_CURRENT_PASSWORD.--new-password-env NAME: defaults toGITHUB_NEW_PASSWORD.--totp-secret-env NAME: defaults toGITHUB_TOTP_SECRET; only read when--auto-2fa-funis set.--proxy http://127.0.0.1:11111: override login proxy.--settings-url URL: override GitHub password settings URL.--manual-timeout-seconds 900: time allowed for manual verification.--keep-browser: keep the isolated browser open after the helper exits.--login-only: log in to GitHub security settings without reading a new password or submitting the password-change form; implies--keep-browser.--auto-2fa-fun: use the hidden TOTP secret with2fa.funto fill GitHub app-code 2FA prompts.--create-learning-repo: after password rotation, create a public beginner learning repository namedhello-world-from-<github-login-slug>.--dry-run: print redacted plan and verify script wiring without launching a browser or requiring passwords.
Learning Repository
- Repository name is deterministic:
hello-world-from-<account-slug>, where the slug lowercases the GitHub login and replaces non-alphanumeric runs with-. - README content must be English, beginner-oriented, and generated from multiple randomized sections at runtime. Do not make it a fixed template keyed only by account name.
- The README should still include the account name in the heading so the repository looks account-specific.
- If GitHub reports the repository already exists or the editor cannot be found, stop with a clear failure instead of silently skipping the repository.
Failure Handling
- If GitHub shows a suspended/disabled account page, stop the script and record the account in the appeal tracker instead of retrying.
- If the helper times out while GitHub is logged in, inspect the visible browser. Do not scrape or print cookies/tokens.
- If
2fa.funis used, read generated codes only frominput.faotp.value; do not parse arbitrary page text or secret fields as codes. - If GitHub changed the settings DOM, rerun with
--keep-browser, inspect visible labels/selectors, then patchdrive_github_password_change.mjs. - GitHub may not show a password success flash. After a submit, treat the collapsed password form plus visible
Change passwordentry as a completed no-flash state, then force a GET navigation back to the settings URL to avoid refresh resubmission. - If the password-change form remains visible after submit, do not assume success. Check visible validation text or ask the user to confirm.
Verification
Dry-run and syntax checks are safe:
python3 skills/github-password-rotator/scripts/rotate_github_password.py \
--github-login username \
--login-only \
--dry-run
python3 -m py_compile skills/github-password-rotator/scripts/rotate_github_password.py
node --check skills/github-password-rotator/scripts/drive_github_password_change.mjs
For live verification, rely on GitHub's success page, the completed no-flash
collapsed form state, a login_completed status for --login-only, or a
user-confirmed successful login with the new password. Do not log the password
itself.