muse-signin: mask secrets in progress output at the source
Identifier, OTP code, and account-name values replaced with [redacted] in all progress prints. Line structure and markers preserved (APPROVAL_NEEDED/NEEDS_HUMAN/SUCCESS prefixes intact); exit codes 0/2/3/4 unchanged, no consumer parses stdout. Defense in depth: onboard-driver already scrubs its passthrough; this covers manual operator flows too.
This commit is contained in:
+13
-13
@@ -7,7 +7,7 @@ Usage:
|
|||||||
|
|
||||||
If --otp is not provided, the script will:
|
If --otp is not provided, the script will:
|
||||||
1. Navigate through login flow up to OTP prompt
|
1. Navigate through login flow up to OTP prompt
|
||||||
2. Print "APPROVAL_NEEDED: OTP required for <email>"
|
2. Print "APPROVAL_NEEDED: OTP required for [redacted]"
|
||||||
3. Exit with code 2
|
3. Exit with code 2
|
||||||
|
|
||||||
The operator then obtains the OTP (via chat with user) and re-runs:
|
The operator then obtains the OTP (via chat with user) and re-runs:
|
||||||
@@ -83,7 +83,7 @@ def main():
|
|||||||
args = p.parse_args()
|
args = p.parse_args()
|
||||||
|
|
||||||
if is_registered_in_accounts(args.email):
|
if is_registered_in_accounts(args.email):
|
||||||
print(f"Registry check: {args.email} is registered in ACCOUNTS.md")
|
print("Registry check: [redacted] is registered in ACCOUNTS.md")
|
||||||
|
|
||||||
if args.cdp_port:
|
if args.cdp_port:
|
||||||
port = args.cdp_port
|
port = args.cdp_port
|
||||||
@@ -113,7 +113,7 @@ def main():
|
|||||||
time.sleep(3)
|
time.sleep(3)
|
||||||
|
|
||||||
# Step 3: Enter email
|
# Step 3: Enter email
|
||||||
print(f"Entering email: {args.email}")
|
print("Entering email: [redacted]")
|
||||||
result = ev(ws, f"""(async()=>{{
|
result = ev(ws, f"""(async()=>{{
|
||||||
const inp=[...document.querySelectorAll('input')].find(i=>
|
const inp=[...document.querySelectorAll('input')].find(i=>
|
||||||
(i.placeholder&&i.placeholder.toLowerCase().includes('email'))||
|
(i.placeholder&&i.placeholder.toLowerCase().includes('email'))||
|
||||||
@@ -125,7 +125,7 @@ def main():
|
|||||||
await new Promise(r=>setTimeout(r,500));
|
await new Promise(r=>setTimeout(r,500));
|
||||||
return 'entered:'+inp.value;
|
return 'entered:'+inp.value;
|
||||||
}})()""", True)
|
}})()""", True)
|
||||||
print(f"Email: {result}")
|
print("Email: [redacted]")
|
||||||
if result == 'NOINPUT':
|
if result == 'NOINPUT':
|
||||||
print("ERROR: Email input not found", file=sys.stderr)
|
print("ERROR: Email input not found", file=sys.stderr)
|
||||||
ws.close()
|
ws.close()
|
||||||
@@ -143,10 +143,10 @@ def main():
|
|||||||
# Step 5: Check for OTP prompt
|
# Step 5: Check for OTP prompt
|
||||||
body = ev(ws, "document.body.innerText.slice(0,500)")
|
body = ev(ws, "document.body.innerText.slice(0,500)")
|
||||||
if "Enter your code" in body or "code we sent" in body or "To log in" in body or "To confirm your account" in body:
|
if "Enter your code" in body or "code we sent" in body or "To log in" in body or "To confirm your account" in body:
|
||||||
print(f"OTP prompt detected for {args.email}")
|
print("OTP prompt detected for [redacted]")
|
||||||
if not args.otp:
|
if not args.otp:
|
||||||
print(f"APPROVAL_NEEDED: OTP required for {args.email}")
|
print("APPROVAL_NEEDED: OTP required for [redacted]")
|
||||||
print("Re-run with: signin.py --email {} --otp <code>".format(args.email))
|
print("Re-run with: signin.py --email [redacted] --otp <code>")
|
||||||
ws.close()
|
ws.close()
|
||||||
sys.exit(2) # Approval needed
|
sys.exit(2) # Approval needed
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ def main():
|
|||||||
await new Promise(r=>setTimeout(r,500));
|
await new Promise(r=>setTimeout(r,500));
|
||||||
return 'entered:'+inp.value;
|
return 'entered:'+inp.value;
|
||||||
}})()""", True)
|
}})()""", True)
|
||||||
print(f"OTP: {result}")
|
print("OTP: [redacted]")
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# Click Next/Verify/Confirm
|
# Click Next/Verify/Confirm
|
||||||
@@ -177,7 +177,7 @@ def main():
|
|||||||
body = ev(ws, "document.body.innerText.slice(0,500)")
|
body = ev(ws, "document.body.innerText.slice(0,500)")
|
||||||
title = ev(ws, "document.title") or ""
|
title = ev(ws, "document.title") or ""
|
||||||
if "Connected" in body or "Chats" in body or "Muse" in title or "Chat" in title:
|
if "Connected" in body or "Chats" in body or "Muse" in title or "Chat" in title:
|
||||||
print(f"SUCCESS: Logged in as {args.email} (title: {title})")
|
print(f"SUCCESS: Logged in as [redacted] (title: {title})")
|
||||||
ws.close()
|
ws.close()
|
||||||
return 0
|
return 0
|
||||||
# Multi-account selection: Meta shows one button per matching
|
# Multi-account selection: Meta shows one button per matching
|
||||||
@@ -200,16 +200,16 @@ def main():
|
|||||||
})()""" % json.dumps(args.account_name), True)
|
})()""" % json.dumps(args.account_name), True)
|
||||||
if not picked:
|
if not picked:
|
||||||
print(f"NEEDS_HUMAN: no account button matched "
|
print(f"NEEDS_HUMAN: no account button matched "
|
||||||
f"'{args.account_name}'", file=sys.stderr)
|
f"'[redacted]'", file=sys.stderr)
|
||||||
ws.close()
|
ws.close()
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
print(f"Selected account '{args.account_name}', waiting...")
|
print(f"Selected account '[redacted]', waiting...")
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
body = ev(ws, "document.body.innerText.slice(0,500)")
|
body = ev(ws, "document.body.innerText.slice(0,500)")
|
||||||
title = ev(ws, "document.title") or ""
|
title = ev(ws, "document.title") or ""
|
||||||
if "Connected" in body or "Chats" in body or "Muse" in title or "Chat" in title:
|
if "Connected" in body or "Chats" in body or "Muse" in title or "Chat" in title:
|
||||||
print(f"SUCCESS: Logged in as {args.email} "
|
print("SUCCESS: Logged in as [redacted] "
|
||||||
f"(account: {args.account_name})")
|
"(account: [redacted])")
|
||||||
ws.close()
|
ws.close()
|
||||||
return 0
|
return 0
|
||||||
print("WARNING: account selection did not land in chat",
|
print("WARNING: account selection did not land in chat",
|
||||||
|
|||||||
Reference in New Issue
Block a user