Skip to content

Commit e8ae795

Browse files
LeafCreeperclaude
andcommitted
Sanitize console output: remove tokens, URLs, PII from print and error messages
GitHub Actions logs are publicly visible. Removed: - Session tokens (lck, authChainCode, loginToken) - Ticket URLs and redirect URLs - User real name from verification - Full API response dumps in error messages Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 44adf3a commit e8ae795

3 files changed

Lines changed: 27 additions & 44 deletions

File tree

main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ def login_with_retry(max_attempts: int = 5) -> WebVPNSession:
9090
return vpn
9191
except Exception as e:
9292
if attempt < max_attempts - 1:
93-
print(f" Failed: {e}, retrying...")
93+
print(f" Failed: {type(e).__name__}, retrying...")
9494
time.sleep(3)
9595
else:
9696
raise

src/icourse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ def get_video_url(self, course_id: str, sub_id: str) -> str | None:
242242
try:
243243
info = self.get_sub_info(course_id, sub_id)
244244
except Exception as e:
245-
print(f" Failed to get sub info: {e}")
245+
print(f" Failed to get sub info for {sub_id}")
246246
return None
247247

248248
# Get server timestamp for signing

src/webvpn.py

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,11 @@ def authenticate_icourse(
224224
break
225225
if not lck:
226226
raise RuntimeError(
227-
f"Failed to extract lck from CAS redirect chain. "
228-
f"Status: {resp.status_code}, URL: {resp.url[:200]}"
227+
f"Failed to extract lck from CAS redirect chain (status={resp.status_code})"
229228
)
230229

231230
entity_id = config.ICOURSE_BASE
232-
print(f" lck: {lck[:20]}...")
231+
print(" lck: OK")
233232

234233
# Step 2: Query auth methods (through WebVPN)
235234
print("[2/7] Querying auth methods (via WebVPN)...")
@@ -254,10 +253,8 @@ def authenticate_icourse(
254253
auth_chain_code = method.get("authChainCode", "")
255254
break
256255
if not auth_chain_code:
257-
raise RuntimeError(
258-
f"No authChainCode found. Response: {data}"
259-
)
260-
print(f" authChainCode: {auth_chain_code[:20]}...")
256+
raise RuntimeError("No authChainCode found in response")
257+
print(" authChainCode: OK")
261258

262259
# Step 3: Get RSA public key (through WebVPN)
263260
print("[3/7] Getting RSA public key (via WebVPN)...")
@@ -270,10 +267,8 @@ def authenticate_icourse(
270267
data = resp.json()
271268
pub_key_b64 = data.get("data", "")
272269
if not pub_key_b64:
273-
raise RuntimeError(
274-
f"Failed to get public key via WebVPN. Response: {data}"
275-
)
276-
print(f" Got RSA public key ({len(pub_key_b64)} chars)")
270+
raise RuntimeError("Failed to get public key via WebVPN")
271+
print(" Got RSA public key")
277272

278273
# Step 4: Encrypt password
279274
print("[4/7] Encrypting password...")
@@ -308,15 +303,13 @@ def authenticate_icourse(
308303

309304
if str(data.get("code")) != "200":
310305
raise RuntimeError(
311-
f"iCourse CAS auth failed: {data.get('message', data)}"
306+
f"iCourse CAS auth failed (code={data.get('code')})"
312307
)
313308

314309
login_token = data.get("loginToken", "")
315310
if not login_token:
316-
raise RuntimeError(
317-
f"No loginToken in iCourse CAS response: {data}"
318-
)
319-
print(f" loginToken: {login_token[:30]}...")
311+
raise RuntimeError("No loginToken in iCourse CAS response")
312+
print(" loginToken: OK")
320313

321314
# Step 6: Get CAS ticket (through WebVPN)
322315
print("[6/7] Getting CAS ticket (via WebVPN)...")
@@ -343,23 +336,20 @@ def authenticate_icourse(
343336
)
344337
if not ticket_match:
345338
raise RuntimeError(
346-
f"Failed to extract iCourse ticket URL. "
347-
f"Response length: {len(html)}, preview: {html[:500]}"
339+
f"Failed to extract iCourse ticket URL (response length: {len(html)})"
348340
)
349341

350342
ticket_url = html_mod.unescape(ticket_match.group(1))
351-
print(f" ticket URL: {ticket_url[:80]}...")
343+
print(" Ticket extracted.")
352344

353345
# Step 7: Follow ticket to iCourse (through WebVPN)
354346
print("[7/7] Following ticket to iCourse (via WebVPN)...")
355347
if not ticket_url.startswith(config.WEBVPN_BASE):
356348
ticket_url = get_vpn_url(ticket_url)
357-
print(f" Converted to VPN URL: {ticket_url[:80]}...")
358349

359350
resp = self.session.get(
360351
ticket_url, allow_redirects=True, timeout=90
361352
)
362-
print(f" Final URL: {resp.url[:80]}...")
363353
print(f" Status: {resp.status_code}")
364354

365355
# Verify by making a test API call
@@ -371,9 +361,7 @@ def authenticate_icourse(
371361
try:
372362
user_data = resp.json()
373363
if user_data.get("code") in (0, 200):
374-
params = user_data.get("params") or user_data.get("data", {})
375-
realname = params.get("realname", "Unknown")
376-
print(f" Verified: logged in as {realname}")
364+
print(" Verified: login OK")
377365
print("[*] iCourse authentication successful!")
378366
return True
379367
except Exception:
@@ -428,13 +416,12 @@ def _get_auth_context(self) -> tuple[str, str]:
428416
lck_match = re.search(r"[?&]lck=([^&]+)", location)
429417
if not lck_match:
430418
raise RuntimeError(
431-
f"Failed to extract lck from redirect. "
432-
f"Status: {resp.status_code}, Location: {location}"
419+
f"Failed to extract lck from redirect (status={resp.status_code})"
433420
)
434421

435422
lck = lck_match.group(1)
436423
entity_id = config.WEBVPN_BASE
437-
print(f" lck: {lck[:20]}...")
424+
print(" lck: OK")
438425
return lck, entity_id
439426

440427
def _query_auth_methods(
@@ -467,11 +454,9 @@ def _query_auth_methods(
467454
break
468455

469456
if not auth_chain_code:
470-
raise RuntimeError(
471-
f"Failed to get authChainCode. Response: {data}"
472-
)
457+
raise RuntimeError("Failed to get authChainCode")
473458

474-
print(f" authChainCode: {auth_chain_code[:20]}...")
459+
print(" authChainCode: OK")
475460
return auth_chain_code, request_type
476461

477462
def _get_public_key(self) -> str:
@@ -487,9 +472,9 @@ def _get_public_key(self) -> str:
487472
data = resp.json()
488473
pub_key_b64 = data.get("data", "")
489474
if not pub_key_b64:
490-
raise RuntimeError(f"Failed to get public key. Response: {data}")
475+
raise RuntimeError("Failed to get public key")
491476

492-
print(f" Got RSA public key ({len(pub_key_b64)} chars)")
477+
print(" Got RSA public key")
493478
return pub_key_b64
494479

495480
def _encrypt_password(self, password: str, pub_key_b64: str) -> str:
@@ -542,15 +527,15 @@ def _auth_execute(
542527

543528
if str(data.get("code")) != "200":
544529
raise RuntimeError(
545-
f"Authentication failed: {data.get('message', data)}"
530+
f"Authentication failed (code={data.get('code')})"
546531
)
547532

548533
# loginToken is at top level, not nested under "data"
549534
login_token = data.get("loginToken", "")
550535
if not login_token:
551-
raise RuntimeError(f"No loginToken in response: {data}")
536+
raise RuntimeError("No loginToken in response")
552537

553-
print(f" loginToken: {login_token[:30]}...")
538+
print(" loginToken: OK")
554539
return login_token
555540

556541
def _get_cas_ticket(self, login_token: str) -> str:
@@ -581,14 +566,13 @@ def _get_cas_ticket(self, login_token: str) -> str:
581566

582567
if not ticket_match:
583568
raise RuntimeError(
584-
f"Failed to extract ticket URL from authnEngine response. "
585-
f"Response length: {len(html)}, preview: {html[:500]}"
569+
f"Failed to extract ticket URL (response length: {len(html)})"
586570
)
587571

588572
ticket_url = ticket_match.group(1)
589573
# Unescape HTML entities (e.g., &amp; -> &)
590574
ticket_url = html_mod.unescape(ticket_url)
591-
print(f" ticket URL: {ticket_url[:60]}...")
575+
print(" Ticket extracted.")
592576
return ticket_url
593577

594578
def _establish_session(self, ticket_url: str):
@@ -603,11 +587,10 @@ def _establish_session(self, ticket_url: str):
603587
ticket_url, allow_redirects=True, timeout=90
604588
)
605589
if resp.status_code == 200:
606-
print(f" Final URL: {resp.url}")
590+
print(" Session established.")
607591
return
608592
raise RuntimeError(
609-
f"Failed to establish WebVPN session. "
610-
f"Status: {resp.status_code}, URL: {resp.url}"
593+
f"Failed to establish WebVPN session (status={resp.status_code})"
611594
)
612595
except requests.exceptions.Timeout:
613596
# Check if session was established despite timeout

0 commit comments

Comments
 (0)