⚠️ Malware / Trojaner / VirenAurora Ransomware Operators Use Cursor AI in Attacks Against 10 Targets(01.09.2026 um 05:17 Uhr)
🕵️ SicherheitslückenCisco FMC Flaws Exploited to Steal Credentials and Deploy Qilin Ransomware(12.09.2026 um 05:17 Uhr)
🕵️ SicherheitslückenVLC Media Player Flaws Let Attackers Corrupt Memory and Leak Sensitive Data(11.09.2026 um 14:03 Uhr)
⚠️ Malware / Trojaner / VirenResearchers Uncover 10,000+ Malware Loaders Behind YouTube and SEO Poisoning Campaign(11.09.2026 um 14:24 Uhr)
🕵️ SicherheitslückenCISA Warns of Critical GitLab Vulnerability Exploited in Attacks(12.09.2026 um 07:17 Uhr)
⚠️ Malware / Trojaner / VirenAsyncRAT Malware Abuses AutoIt and PowerShell to Hide Inside Legitimate Windows Process(14.09.2026 um 07:24 Uhr)
⚠️ Malware / Trojaner / VirenAurora Ransomware Operators Use Cursor AI in Attacks Against 10 Targets(01.09.2026 um 05:17 Uhr)
🕵️ SicherheitslückenCisco FMC Flaws Exploited to Steal Credentials and Deploy Qilin Ransomware(12.09.2026 um 05:17 Uhr)
🕵️ SicherheitslückenVLC Media Player Flaws Let Attackers Corrupt Memory and Leak Sensitive Data(11.09.2026 um 14:03 Uhr)
⚠️ Malware / Trojaner / VirenResearchers Uncover 10,000+ Malware Loaders Behind YouTube and SEO Poisoning Campaign(11.09.2026 um 14:24 Uhr)
🕵️ SicherheitslückenCISA Warns of Critical GitLab Vulnerability Exploited in Attacks(12.09.2026 um 07:17 Uhr)
⚠️ Malware / Trojaner / VirenAsyncRAT Malware Abuses AutoIt and PowerShell to Hide Inside Legitimate Windows Process(14.09.2026 um 07:24 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 6 Min Lesezeit
0

Maintaining WordPress sites behind HTTP Basic auth — Playwright, urllib, and encrypted credentials

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

It's pretty common to throw a layer of HTTP Basic auth on a WordPress site: a staging environment before launch, an internal test instance only employees should see, or any environment that wants an extra gate before the WordPress login screen itself.



From a maintenance-tool point of view, this setup creates a peculiar "half-working, half-broken" asymmetry. The SSH/WP-CLI side runs fine. But everything HTTP-based — visual checks, thumbnail generation, browser-based fallback updates — hits 401 and dies. This post walks through how we resolved that asymmetry.






What was breaking — two parallel paths, both blocked



A maintenance tool actually touches a Basic-auth-protected site through two distinct paths:





  • Playwright path: visual checks, thumbnail capture, browser fallback updates when SSH isn't available. browser.new_context() → navigation → screenshot


  • urllib path: HTTP status checks (pre/post-update 200/5xx/4xx monitoring, rollback decisions)



With no credentials, both paths see a 401 Unauthorized from the protected site.



The Playwright symptom is the obvious one: the screenshot you save is the browser's "authentication required" dialog. The thumbnail grid fills with dark auth-prompt images, and you start wondering whether anything actually works.



The urllib symptom is much worse — it silently breaks rollback decisions. A 401 baseline followed by another 401 after the update looks like "nothing changed = healthy." Real failures can hide behind that match, and the rollback that should have fired never does.






The design — consolidate credential extraction into one helper



When the same credentials need to flow through multiple code paths, picking them out of the site dict separately at each call site invites format-mismatch and missed-update bugs. So the first thing we did was build a small core/basic_auth_utils.py module that owns every form of credential extraction.




CODE
# core/basic_auth_utils.py
def get_basic_auth_tuple(site):
"""Return (user, password), or None if not configured."""
if not isinstance(site, dict):
return None
user = (site.get('basic_auth_user') or '').strip()
pw = site.get('basic_auth_password') or ''
if not user:
return None # No user → treat as "no auth"
return (user, pw)

def get_playwright_http_credentials(site):
"""Returns dict for Playwright's new_context(http_credentials=...)."""
auth = get_basic_auth_tuple(site)
if auth is None:
return None
return {'username': auth[0], 'password': auth[1]}

def get_basic_auth_header(site):
"""Returns {'Authorization': 'Basic <base64>'} for urllib."""
auth = get_basic_auth_tuple(site)
if auth is None:
return {}
raw = f"{auth[0]}:{auth[1]}".encode('utf-8')
encoded = base64.b64encode(raw).decode('ascii')
return {'Authorization': f'Basic {encoded}'}






The key idea: both the Playwright and urllib forms derive from the same get_basic_auth_tuple() root. Format drift between the two callers becomes structurally impossible.






Backward compatibility — existing sites don't have these fields



A small but important detail: the existing site-configuration JSON has no basic_auth_user / basic_auth_password keys. Naively writing site['basic_auth_user'] would crash with KeyError the moment someone opens an existing site.



We went with the site.get('basic_auth_user') or '' empty-string-fallback pattern. Missing key, empty string, or None all collapse to "no auth," so existing sites behave exactly as before. Only the sites that actually set Basic auth flip into the authenticated path.



On top of that, the Basic auth password gets the same treatment as the WordPress admin password: Fernet-encrypted at rest. Adding 'basic_auth_password' to the ENCRYPTED_SITE_KEYS constant is all it takes — encryption and decryption happen automatically on save and load.






Wiring both paths



With the helpers in place, the call sites get rewired.



Playwright path: one shared helper _new_context_with_auth(browser, site) replaces three new_context() call sites (visual check, thumbnail capture, browser residual update) at once.




CODE
def _new_context_with_auth(browser, site):
http_credentials = get_playwright_http_credentials(site)
if http_credentials:
return browser.new_context(http_credentials=http_credentials)
return browser.new_context()






urllib path: _http_status_check(url, basic_auth=None) gains a basic_auth parameter and sends the Authorization header internally. The "baseline 401 → post-update 401" false negative disappears — the rollback decision now sees the real status code after authentication (200 / 5xx / etc.) and fires correctly.



Inside the maintenance main loop run_ssh_maintenance, we extract _basic_auth from the site dict exactly once and pass it into all five _http_status_check_stable() calls. Pulling it out from the dict at every call site invites "this one place forgot," so a local variable is the safer move.






UI — keep the rare case out of the way



From a user perspective, Basic-auth-protected sites are the minority. Putting two always-visible input fields in the site-add modal would clutter the UI for the 99% of sites that don't need them.



So we put the credentials behind a <details> element — a collapsed-by-default "🔐 Basic Auth (optional)" section at the end of the WordPress info group in the site-add/edit modal.




CODE
<details>
<summary>🔐 Basic Auth (optional)</summary>
<input name="basic_auth_user" placeholder="Auth username">
<input type="password" name="basic_auth_password"
placeholder="Auth password">
</details>






Users with Basic-auth-protected sites expand and fill it in; the rest see no change. Saved passwords go through Fernet with the ENC: prefix.






Closing — patterns for "same credentials, multiple paths"



Three principles worth keeping from this round:





  1. When multiple paths need the same credentials, consolidate extraction into one helper. Playwright form, urllib form, boolean check — each consumer wants a different shape, but they should all derive from a single (user, password) root function. That keeps format drift from happening


  2. For new fields on existing data, lean on empty-fallback patterns. site.get(key) or '' treats missing keys as "feature off," letting you add functionality without touching existing data. No migration needed


  3. Hide rare features behind disclosure widgets. A field used by 1% of sites doesn't deserve top-billing visual space. A <details> collapse with a small icon expresses "optional feature" cleanly, and gets out of the way for everyone else



Staging environments behind Basic auth aren't rare in the WordPress world. If your automation tool is "half working" against those sites, teams quickly fall back to manual maintenance just for that subset. Designing a clean credential path through both the Playwright and urllib sides — once — is worth the up-front investment.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
4 Quellen
CISA Adds Seven Exploited Flaws as Attackers Deploy Reverse Shells and Crypto Miners
1 Quelle
WordlistLoader Delivers Amatera via ClickFix, SynkLoader Phishes Windows Passwords
1 Quelle
ThreatsDay: 296K IoT Botnet, 100+ Water Systems Targeted, SharePoint RCE Chain + 27 New Stories
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Maintaining WordPress sites behind HTTP Basic auth — Playwright, urllib, and encrypted credentials

Thematisch verwandte Begriffe: Maintaining, WordPress, sites, behind · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...