inc/import.php:48
Filtyp validerades enbart via filändelse (.csv). En angripare kan byta namn på en körbar fil till .csv och ladda upp den via importverktyget.
$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
if ($ext !== 'csv') { ... }
OWASP A03:2021 – Injection · OWASP File Upload Cheat Sheet
inc/terms.php:96
Identisk problematik som TEMA-SEC-007 – enbart filändelse (.json) kontrollerades.
$ext = strtolower(pathinfo($_FILES['terms_file']['name'], PATHINFO_EXTENSION));
if ($ext !== 'json') { ... }
OWASP A03:2021 – Injection · OWASP File Upload Cheat Sheet
inc/integrity.php:196
Filuppladdning av audit-JSON-filer godkändes baserat på klient-side accept-attribut och filändelse. Ingen server-side MIME-kontroll gjordes.
// Ingen MIME-kontroll, enbart storlek och JSON-parsning
OWASP A03:2021 – Injection · OWASP File Upload Cheat Sheet
Plugin: Antispam Bee
Plugin: Open Messages (security-audit.json)
front-page.php:24
setcookie() för 'blogtree_visited' saknar säkerhetsflaggorna HttpOnly (hindrar JS-åtkomst), Secure (kräver HTTPS) och SameSite (skyddar mot CSRF). Kakan är visserligen funktionell och innehåller ingen känslig data, men mönstret bör följa best practice.
setcookie('blogtree_visited', time(), time() + 365 * DAY_IN_SECONDS, '/');
OWASP A05:2021 – Security Misconfiguration · RFC 6265bis SameSite
inc/maintenance.php:107
str_contains() introducerades i PHP 8.0. Om servern kör PHP 7.x kraschar underhållsfunktionen med ett fatalt fel, vilket kan blockera hela webbplatsen.
if (str_contains($path, $slug)) return;
PHP Compatibility
inc/integrity.php:52
file_get_contents() körs på den uppladdade temporära filen utan att kontrollera filstorleken. En administratör (eller komprometterat admin-konto) kan ladda upp en extremt stor JSON-fil som orsakar minnesproblem.
$content = file_get_contents($tmp);
OWASP A05:2021 – Security Misconfiguration
inc/comments.php:17
wp_ajax_blogtree_post_comment saknar begränsning på antal kommentarer per användare eller tidsperiod. En inloggad användare kan spamma obegränsat antal kommentarer och fylla databasen.
add_action('wp_ajax_blogtree_post_comment', 'blogtree_handle_comment');
OWASP A05:2021 – Security Misconfiguration
inc/community.php:12
blogtree_handle_submission saknar begränsning på hur många inlägg en inloggad användare kan skicka in. En användare kan skicka in hundratals inlägg och belasta databasen.
add_action('wp_ajax_blogtree_submit_post', 'blogtree_handle_submission');
OWASP A05:2021 – Security Misconfiguration
front-page.php:152
get_avatar_url(1) och get_avatar(1, …) förutsätter att administratören alltid har user ID 1. Om webbplatsen migreras eller admin-kontot skapas om kan fel bild visas eller anrop misslyckas.
echo esc_url(get_avatar_url(1, ['size' => 200]));
inc/likes.php:22
blogtree_liked_by sparar en array av alla user IDs som gillat ett inlägg. Om WordPress REST API är aktiverat kan denna meta vara tillgänglig publikt. User IDs kan i kombination med profil-URL kopplas till identifierbara personer.
$liked_by = (array) get_post_meta($post_id, 'blogtree_liked_by', true);
GDPR Art. 4(1) – Definition of personal data · WordPress REST API Handbook
inc/follow.php:1
blogtree_followed_topics sparas i user meta men ingen hook på delete_user rensar datan. Vid kontoborttagning finns kvarliggande data i wp_usermeta-tabellen.
update_user_meta($user_id, 'blogtree_followed_topics', $followed);
GDPR Art. 17 – Right to erasure
inc/likes.php:1
User IDs i blogtree_liked_by rensas inte när ett konto raderas. En raderad användares ID kvarstår i post meta och kan kopplas till anonymiserat eller återanvänt konto.
// Ingen delete_user-hook registrerad
GDPR Art. 17 – Right to erasure
inc/avatars.php:12
Om en användare inte laddat upp en lokal avatar skickas en MD5-hash av e-postadressen till gravatar.com. Gravatar kan använda detta för spårning. Temat har visserligen ett lokalt avatar-system men det är frivilligt.
if (!$attachment_id) return $args; // Faller tillbaka till Gravatar
GDPR Art. 5(1)(c) – Data minimisation · Gravatar Privacy Policy
antispam-bee/
Antispam Bee analyserar spam lokalt utan att skicka kommentarsdata till externa servrar (till skillnad från Akismet). Ingen persondata lämnar servern vid grundläggande spamkontroll. Godkänt.
Antispam Bee GitHub – Privacy Statement
antispam-bee/
Antispam Bee kan logga IP-adressen för spammade kommentarer i spam-loggen. IP-adresser klassas som personuppgifter enligt GDPR. Inställningen 'Anonymisera IP-adresser' finns inte i Antispam Bee 6.9.4.
GDPR Art. 4(1) – Personal data · CJEU C-582/14 Breyer – IP addresses
antispam-bee/
Om landbaserad blockering aktiveras i Antispam Bee behandlas besökarens IP-adress för att avgöra geografiskt ursprung. Detta är behandling av personuppgifter och kräver rättslig grund (t.ex. berättigat intresse).
GDPR Art. 6(1)(f) – Legitimate interest
antispam-bee/
Antispam Bees honeypot-fält har ett relativt statiskt klassnamn. Sofistikerade bots som analyserar källkoden kan identifiera och hoppa över fältet.
Antispam Bee Settings Documentation
antispam-bee/
Antispam Bee är GPL-licensierat och underhålls av WordPress-communityt. Koden är publik på GitHub och kan granskas av vem som helst. Godkänt.
github.com/pluginkollektiv/antispam-bee
includes/class-om-form.php:57
Kontaktformuläret samlar in namn, e-postadress och meddelande och sparar dem i databasen utan att informera besökaren eller begära uttryckligt samtycke. Strider mot GDPR Artikel 6 och 13.
// Ingen samtyckescheckbox eller integritetspolicylänk i render_shortcode()
GDPR Art. 6 – Lawfulness of processing · GDPR Art. 13 – Information to be provided
includes/class-om-cleanup.php:1
Pluginet erbjuder ingen mekanism för att på begäran radera en specifik persons data. Automatisk 30-dagarsrensning uppfyller inte kravet på manuell hantering av raderingsbegäran.
// Ingen hook, admin-åtgärd eller sökning på e-postadress för manuell radering
GDPR Art. 17 – Right to erasure
includes/
Pluginet registrerar inte register_personal_data_exporter(). En registrerad person kan inte exportera sina uppgifter via WordPress inbyggda verktyg.
// register_personal_data_exporter() saknas helt
GDPR Art. 20 – Right to data portability · WordPress Privacy API
wp-openmessages.php:1
Pluginet registrerar inte sig i WordPress inbyggda Privacy API. Webbplatsägare kan inte använda WordPress inbyggda GDPR-verktyg för att hantera förfrågningar.
// register_personal_data_eraser() och register_personal_data_exporter() saknas
GDPR Art. 17, Art. 20 · WordPress Privacy API Handbook
includes/class-om-cleanup.php:89
Meddelande-ID:n sammanfogas med implode() och interpoleras direkt i en SQL-sträng utan $wpdb->prepare(). Även om intval() används är mönstret riskabelt.
$wpdb->query( "UPDATE {$wpdb->prefix}om_messages SET warn_sent = 1 WHERE id IN ($ids)" );
OWASP A03:2021 – Injection · WordPress Coding Standards – DB.PreparedSQL
includes/class-om-crypto.php:10
Om AUTH_KEY inte är definierat används strängen 'om-fallback-salt-change-me' som krypteringsnyckel. Denna kända sträng exponeras i källkoden och ger inget skydd.
$salt = defined( 'AUTH_KEY' ) ? AUTH_KEY : 'om-fallback-salt-change-me';
OWASP A02:2021 – Cryptographic Failures
includes/class-om-crypto.php:19
AES-256-CBC utan HMAC eller GCM-läge ger inget integritetsskydd. En angripare med databasåtkomst kan modifiera chiffertexten utan att dekrypteringen misslyckas.
openssl_encrypt( $plaintext, 'aes-256-cbc', self::key(), OPENSSL_RAW_DATA, $iv );
OWASP A02:2021 – Cryptographic Failures · CWE-326 Inadequate Encryption Strength
includes/class-om-form.php:106
Inga begränsningar per IP eller session hindrar en angripare från att skicka tusentals formulärmeddelanden.
// Ingen kontroll av antal inskickningar per IP/tidsenhet
OWASP A05:2021 – Security Misconfiguration
includes/class-om-form.php:175
Besökarens IP-adress lagras som MD5-hash i transient-nyckeln. IP-adresser är personuppgifter enligt GDPR. MD5 av en känd IP är trivial att reversa.
return substr( md5( $_SERVER['REMOTE_ADDR'] ?? 'x' ), 0, 12 );
GDPR Art. 4(1) – Definition of personal data · CJEU C-582/14 Breyer
includes/class-om-database.php:177
IMAP/SMTP-lösenord lagras krypterade i WordPress-databasen. Vid en fullständig databaskompromettering kan lösenorden dekrypteras om angriparen också känner till AUTH_KEY.
$data['password_enc'] = OM_Crypto::encrypt( $data['password'] );
OWASP A02:2021 – Cryptographic Failures · CWE-312 Cleartext Storage of Sensitive Information
admin/views/settings.php:8
edit_imap och edit_smtp GET-parametrar saknar nonce-verifiering. En angripare kan lura en inloggad admin att öppna en redigerings-URL via länk.
$edit_imap = isset( $_GET['edit_imap'] ) ? OM_Database::get_imap_account( (int) $_GET['edit_imap'] ) : null;
OWASP A01:2021 – Broken Access Control · CWE-352 CSRF
includes/class-om-admin.php:60
Det finns ingen audit-logg över vilken admin-användare som läste, svarade på, raderade eller stjärnmärkte ett meddelande.
// Ingen loggning av get_current_user_id() vid känsliga åtgärder
OWASP A09:2021 – Security Logging and Monitoring Failures
includes/class-om-captcha.php:12
session_start() anropas utan session_regenerate_id() efter CAPTCHA-validering. Risk för session fixation.
if ( ! session_id() ) { session_start(); }
OWASP A07:2021 – Identification and Authentication Failures · CWE-384 Session Fixation
includes/class-om-admin.php:286
$_SERVER['HTTP_REFERER'] används som redirect-destination utan whitelist-validering. wp_safe_redirect() stoppar externa domäner men skyddar inte mot intern URL-manipulation.
$url = $_SERVER['HTTP_REFERER'] ?? admin_url( 'admin.php?page=open-messages' );
OWASP A01:2021 – Broken Access Control
includes/class-om-imap.php:58
Kontrollen om ett imap_uid redan finns och efterföljande INSERT är inte atomisk. Två parallella WP-Cron-körningar kan importera samma e-post dubbelt.
$exists = $wpdb->get_var(...);
if ( $exists ) { continue; }
// INSERT här – race window
CWE-362 Race Condition
admin/views/compose.php:37
reply_to och reply_subject från $_GET skyddas med esc_attr() i output men saniteras inte vid inläsning. Längdvalidering saknas.
value="<?php echo esc_attr( $_GET['reply_to'] ?? '' ); ?>"
OWASP A03:2021 – Injection
includes/class-om-imap.php:31
error_log() anropas med kontonamn och ID vid misslyckad dekryptering. Risk att lösenord loggas av framtida ändringar.
error_log( "[Open Messages] Kunde inte dekryptera lösenord för IMAP-konto #{$account->id}" );
OWASP A09:2021 – Security Logging and Monitoring Failures · CWE-532 Insertion of Sensitive Information into Log File
includes/class-om-form.php:89
Honeypot-fältet döljs med CSS-klassen om-hp men är synligt i HTML-källkoden med klassnamnet 'om-hp'. Sofistikerade bots kan känna igen och hoppa över det.
<div class="om-hp" aria-hidden="true">
includes/class-om-database.php:59
replied_body lagras permanent i om_messages-tabellen utan möjlighet att radera enbart ett svar. Strider mot GDPR-principen om dataminimering.
replied_body LONGTEXT, replied_at DATETIME,
GDPR Art. 5(1)(c) – Data minimisation
includes/class-om-form.php:57
Besökaren informeras inte om att deras meddelande lagras i 30 dagar. Lagringstiden framgår inte i formuläret.
// Ingen information om lagringstid i formulärets HTML
GDPR Art. 13(2)(a) – Storage period