harden(opsec): disguise the honeypot naming on the Threats + settings pages too
Follow-up to bf4366d (audit log): remove the last user-visible mentions of the deception layer
so nothing in the running panel names it "Honeypot" — a shoulder-surf, a shared screen, or a
breached admin session can no longer tell the decoy paths are a trap. Admin-only surfaces, but
closes the gap for full coverage.
- Threats page: subtitle "Honeypot activity" -> "Attack activity"; feed title "Honeypot events"
-> "Security events"; the Honeytoken KPI -> "Leaked credentials" (DE mirrors).
- Settings: the "Honeypot" status block -> "Threat detection" / "Angriffserkennung"; subtitle and
note reworded to drop "deception layer"/"decoy paths"/"Täuschung"/"Köder", and the note no longer
prints the CLUSEV_HONEYPOT env-var name (it named the mechanism).
DB action keys, the CLUSEV_HONEYPOT env var itself, config, and dev code comments are unchanged
(the source is public AGPL, so comments carry no OPSEC value — only the runtime UI matters). A new
regression test asserts the Threats page renders the disguised labels and never shows
"Honeypot"/"Honeytoken"/"Täuschung"/"Köder". 619 tests, de/en parity, Pint; a scan confirms zero
visible "Honeypot"/"Honeytoken" left in any lang value.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat/v1-foundation
parent
bf4366dfc9
commit
aa854916ce
|
|
@ -88,10 +88,12 @@ return [
|
|||
'lp_unban_all_notify' => 'Alle Sperren aufgehoben.',
|
||||
'lp_lockout_note' => 'Eingeloggte Operatoren werden nie geblockt und können hier ihre eigene IP entsperren. Notfall: clusev unban <ip> auf der Host-Shell.',
|
||||
|
||||
// Honeypot-Statusanzeige (per Umgebungsvariable gesteuert, kein Schalter)
|
||||
'hp_title' => 'Honeypot',
|
||||
'hp_subtitle' => 'Täuschungsebene gegen Angreifer-Sonden',
|
||||
'hp_note' => 'Köder-Pfade sperren scannende IP-Adressen sofort. Per CLUSEV_HONEYPOT gesteuert. Treffer erscheinen unter Bedrohungen.',
|
||||
// Angriffserkennungs-Statusanzeige (per Umgebungsvariable gesteuert, kein Schalter). Bewusst
|
||||
// neutral benannt (kein "Honeypot"/"Köder"/"Täuschung", Env-Var-Name ausgelassen) — die
|
||||
// Deception-Ebene darf sich in der UI nicht selbst verraten.
|
||||
'hp_title' => 'Angriffserkennung',
|
||||
'hp_subtitle' => 'Automatische Sperre scannender Angreifer',
|
||||
'hp_note' => 'Sperrt scannende IP-Adressen automatisch und sofort. Über eine Umgebungsvariable steuerbar. Treffer erscheinen unter Bedrohungen.',
|
||||
'hp_on' => 'Aktiv',
|
||||
'hp_off' => 'Inaktiv',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
<?php
|
||||
|
||||
// Bedrohungen (Honeypot-Dashboard): Sondenverlauf, KPIs, gesperrte IPs (R16).
|
||||
// Bedrohungen (Angriffserkennung): Sondenverlauf, KPIs, gesperrte IPs (R16). Sichtbare Strings
|
||||
// bewusst neutral gehalten (kein "Honeypot"/"Köder"/"Täuschung") — die Deception-Ebene darf sich
|
||||
// dem Betrachter nicht selbst verraten. Die DB-Action-Keys bleiben security.honeypot_*.
|
||||
return [
|
||||
// Header
|
||||
'eyebrow' => 'Sicherheit',
|
||||
'title' => 'Bedrohungen',
|
||||
'subtitle' => 'Honeypot-Aktivität und gesperrte IP-Adressen',
|
||||
'subtitle' => 'Angriffsaktivität und gesperrte IP-Adressen',
|
||||
'probes_pill' => ':count Sonden (24h)',
|
||||
|
||||
// KPI-Kacheln
|
||||
'kpi_login_attempts' => 'Login-Versuche (24h)',
|
||||
'kpi_probes' => 'Sonden (24h)',
|
||||
'kpi_banned' => 'Gesperrte IPs',
|
||||
'kpi_honeytoken' => 'Honeytoken',
|
||||
'kpi_honeytoken' => 'Geleakte Zugangsdaten',
|
||||
'kpi_top_ip' => 'Top-Angreifer',
|
||||
|
||||
// Bedrohungs-Feed
|
||||
'feed_title' => 'Honeypot-Ereignisse',
|
||||
'feed_title' => 'Sicherheitsereignisse',
|
||||
'feed_subtitle' => 'neueste zuerst',
|
||||
'tried_creds' => 'Versuchte Zugangsdaten',
|
||||
'search_label' => 'Bedrohungen durchsuchen',
|
||||
|
|
|
|||
|
|
@ -88,10 +88,12 @@ return [
|
|||
'lp_unban_all_notify' => 'All blocks cleared.',
|
||||
'lp_lockout_note' => 'Logged-in operators are never blocked and can unblock their own IP here. Emergency: clusev unban <ip> on the host shell.',
|
||||
|
||||
// Honeypot status indicator (env-driven, no toggle)
|
||||
'hp_title' => 'Honeypot',
|
||||
'hp_subtitle' => 'Deception layer against attacker probes',
|
||||
'hp_note' => 'Decoy paths instantly ban scanning IP addresses. Controlled via CLUSEV_HONEYPOT. Hits appear under Threats.',
|
||||
// Threat-detection status indicator (env-driven, no toggle). Deliberately neutral naming
|
||||
// (no "honeypot"/"decoy"/"deception", env-var name omitted) — the deception layer must not
|
||||
// reveal itself in the UI.
|
||||
'hp_title' => 'Threat detection',
|
||||
'hp_subtitle' => 'Automatic ban of scanning attackers',
|
||||
'hp_note' => 'Automatically bans scanning IP addresses on sight. Controlled via an environment variable. Hits appear under Threats.',
|
||||
'hp_on' => 'Enabled',
|
||||
'hp_off' => 'Disabled',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
<?php
|
||||
|
||||
// Threats (honeypot dashboard): probe feed, KPIs, banned IPs (R16).
|
||||
// Threats (attack-detection dashboard): probe feed, KPIs, banned IPs (R16). Visible strings kept
|
||||
// deliberately neutral (no "honeypot"/"decoy"/"deception") so the deception layer never reveals
|
||||
// itself to a viewer. The DB action keys stay security.honeypot_*.
|
||||
return [
|
||||
// Header
|
||||
'eyebrow' => 'Security',
|
||||
'title' => 'Threats',
|
||||
'subtitle' => 'Honeypot activity and banned IP addresses',
|
||||
'subtitle' => 'Attack activity and banned IP addresses',
|
||||
'probes_pill' => ':count probes (24h)',
|
||||
|
||||
// KPI tiles
|
||||
'kpi_login_attempts' => 'Login attempts (24h)',
|
||||
'kpi_probes' => 'Probes (24h)',
|
||||
'kpi_banned' => 'Banned IPs',
|
||||
'kpi_honeytoken' => 'Honeytokens',
|
||||
'kpi_honeytoken' => 'Leaked credentials',
|
||||
'kpi_top_ip' => 'Top attacker',
|
||||
|
||||
// Threat feed
|
||||
'feed_title' => 'Honeypot events',
|
||||
'feed_title' => 'Security events',
|
||||
'feed_subtitle' => 'newest first',
|
||||
'tried_creds' => 'Attempted credentials',
|
||||
'search_label' => 'Search threats',
|
||||
|
|
|
|||
|
|
@ -129,6 +129,24 @@ class ThreatsPageTest extends TestCase
|
|||
->assertViewHas('login_attempts_24h', 1);
|
||||
}
|
||||
|
||||
public function test_the_threats_page_never_reveals_the_deception_layer(): void
|
||||
{
|
||||
// OPSEC: even the admin-only intel page must not NAME the mechanism — a shoulder-surf, a
|
||||
// shared screen, or a breached admin session must not learn the decoy paths are a trap.
|
||||
AuditEvent::create(['actor' => 'system', 'action' => 'security.honeypot_hit', 'target' => '/wp-admin', 'ip' => self::ATTACKER_IP]);
|
||||
AuditEvent::create(['actor' => 'system', 'action' => 'security.honeytoken_used', 'target' => 'db_password', 'ip' => self::ATTACKER_IP]);
|
||||
|
||||
Livewire::actingAs($this->admin())
|
||||
->test(Index::class)
|
||||
->assertSee('Angriffsversuch') // disguised event label
|
||||
->assertSee('Sicherheitsereignisse') // disguised feed title
|
||||
->assertSee('Geleakte Zugangsdaten') // disguised honeytoken KPI
|
||||
->assertDontSee('Honeypot')
|
||||
->assertDontSee('Honeytoken')
|
||||
->assertDontSee('Täuschung') // "Täuschungsebene"
|
||||
->assertDontSee('Köder'); // "Köder-Pfade"
|
||||
}
|
||||
|
||||
public function test_tried_credentials_are_html_escaped(): void
|
||||
{
|
||||
// Attacker-controlled meta must render escaped, never as live markup.
|
||||
|
|
|
|||
Loading…
Reference in New Issue