Skip to content

MediaWiki Security — Hardening, .htaccess, CSP, XSS Prevention, and CAPTCHA

DodaTech Updated 2026-06-26 10 min read

In this tutorial, you will learn about MediaWiki Security. We cover key concepts, practical examples, and best practices to help you master this topic.

Security hardening in MediaWiki protects your wiki against common web threats through multiple layers — server-level .htaccess restrictions, Content Security Policy headers, built-in XSS and CSRF protections, CAPTCHA configuration, input validation, and secure authentication practices, the same defense-in-depth approach Wikipedia uses to protect one of the world's most targeted websites.

What You'll Learn

  • Server-level security with .htaccess
  • Content Security Policy configuration
  • Understanding XSS and CSRF prevention
  • Configuring CAPTCHA
  • Securing file uploads
  • Protecting user accounts
  • Security hardening checklist

Why It Matters

A wiki is a target. It stores valuable content, user data, and runs on a public-facing web server. Attackers target wikis for spam, malware distribution, data theft, and defacement. MediaWiki has strong built-in security, but it must be properly configured. A single misconfiguration — like allowing uploaded HTML files or disabling CSRF tokens — can compromise your entire installation.

Real-World Use

A DodaTech wiki implements defense in depth. The .htaccess file blocks direct access to configuration files. Content Security Policy prevents injected scripts from executing. CAPTCHA stops automated spam registrations. File uploads are restricted to safe types with MIME verification. User passwords require 12+ characters. The wiki has never been successfully attacked.

Learning Path

flowchart RL
  A["38: Performance Tuning"] --> B["39: Upgrading MediaWiki"]
  B --> C["40: Security"]
  C:::current

  classDef current fill#38bdf8,color#0f172a,stroke-width:2px

Server-Level Security with .htaccess

Protect sensitive files and directories at the web server level.

Protect LocalSettings.php

Create or edit .htaccess in the MediaWiki root:

# Block access to sensitive files
<FilesMatch "^(LocalSettings\.php|\.htaccess|\.git)">
    Require all denied
</FilesMatch>

# Block access to configuration directory
<DirectoryMatch "^\.|\/cache\/|\/logs\/">
    Require all denied
</DirectoryMatch>

Protect the includes Directory

# Block direct access to PHP includes
<Directory "/var/www/mediawiki/includes">
    Require all denied
</Directory>

Protect the maintenance Directory

# Block public access to maintenance scripts
<Directory "/var/www/mediawiki/maintenance">
    Require all denied
</Directory>

Secure Image Uploads

# Prevent execution of PHP files in uploads
<Directory "/var/www/mediawiki/images">
    php_flag engine off
    <FilesMatch "\.(php|php5|phtml|shtml|cgi)$">
        Require all denied
    </FilesMatch>
</Directory>

Content Security Policy (CSP)

CSP prevents cross-site scripting (XSS) by controlling which resources the browser can load.

Basic CSP Configuration

// In LocalSettings.php
$wgCSPHeader = [
    'default-src' => [
        "'self'",
    ],
    'script-src' => [
        "'self'",
        "'unsafe-inline'",  // Required for some wiki features
    ],
    'style-src' => [
        "'self'",
        "'unsafe-inline'",  // Required for user CSS
    ],
    'img-src' => [
        "'self'",
        "data:",
        "https://upload.wikimedia.org",
    ],
    'connect-src' => [
        "'self'",
        "https://api.dodatech.com",
    ],
];

Testing CSP

Start with report-only mode to test without blocking:

$wgCSPReportOnlyHeader = true;
$wgCSPHeader = [
    'default-src' => "'self'",
    'report-uri' => 'https://your-report-endpoint.com/csp',
];

Check CSP reports for blocked resources and adjust the policy.

CSP Best Practices

  • Start strict and loosen as needed
  • Avoid 'unsafe-inline' for scripts if possible
  • Use nonces or hashes for inline scripts
  • Keep the policy as restrictive as your extensions allow
  • Test in report-only mode before enforcing

XSS Prevention

Cross-Site Scripting (XSS) allows attackers to inject malicious scripts into pages.

Built-in XSS Protection

MediaWiki has strong built-in XSS protection:

  • HTML sanitization: User-generated HTML is sanitized on output
  • Escaping: All user input is escaped by default
  • Edit filters: The AbuseFilter extension can block suspicious edits
  • No raw HTML by default: Users cannot inject raw HTML without specific permissions

Configuring HTML Whitelist

// Allow specific HTML tags (restrictive is safer)
$wgRawHtml = false;  // Disable raw HTML entirely

// If raw HTML is needed, use a whitelist
$wgRawHtmlMimeTypes = [ 'text/html' ];

XSS Risks to Avoid

❌ Allowing raw HTML for all users
❌ Using $wgAllowExternalImages without restrictions
❌ Disabling $wgMiserMode (which controls expensive operations)
❌ Installing untested extensions
❌ Granting editinterface to untrusted users

CSRF Prevention

Cross-Site Request Forgery (CSRF) tricks authenticated users into performing actions without their consent.

Built-in CSRF Protection

MediaWiki uses CSRF tokens for every write operation:

// CSRF tokens are enabled by default
$wgEnableWriteAPI = true;    // API requires tokens
$wgCSRFTokenDuration = 3600;  // Token valid for 1 hour

How CSRF Tokens Work

  1. User loads a page with an edit form
  2. MediaWiki generates a unique token tied to the user's session
  3. The token is embedded in the form as a hidden field
  4. When the form is submitted, MediaWiki validates the token
  5. If the token is missing or invalid, the request is rejected

CSRF Best Practices

  • Keep $wgEnableWriteAPI set to true
  • Use api.php with tokens for all write operations
  • Never use GET requests for write operations
  • Keep session timeout reasonable (not too long)

CAPTCHA Configuration

CAPTCHA prevents automated spam and abuse by requiring human interaction.

Install ConfirmEdit

cd /opt/lampp/htdocs/mediawiki/extensions
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/ConfirmEdit.git
cd ConfirmEdit
git checkout REL1_42

Enable CAPTCHA

wfLoadExtension( 'ConfirmEdit' );

// Choose a CAPTCHA module
$wgCaptchaClass = 'Captcha\SimpleCaptcha\SimpleCaptcha';

// Triggers: when to show CAPTCHA
$wgCaptchaTriggers['edit'] = true;              // On every edit
$wgCaptchaTriggers['create'] = true;            // On page creation
$wgCaptchaTriggers['addurl'] = true;            // When adding external links
$wgCaptchaTriggers['createaccount'] = true;     // On account registration
$wgCaptchaTriggers['badlogin'] = true;          // After failed login attempts

CAPTCHA Modules

// Simple CAPTCHA (math question) — no external dependencies
$wgCaptchaClass = 'Captcha\SimpleCaptcha\SimpleCaptcha';

// ReCAPTCHA (Google)
wfLoadExtension( 'ConfirmEdit/ReCaptchaNoCaptcha' );
$wgCaptchaClass = 'ReCaptchaNoCaptcha';
$wgReCaptchaSiteKey = 'your-site-key';
$wgReCaptchaSecretKey = 'your-secret-key';

// Questy CAPTCHA (custom questions)
wfLoadExtension( 'ConfirmEdit/QuestyCaptcha' );
$wgCaptchaClass = 'QuestyCaptcha';
$wgCaptchaQuestions = [
    'What color is the sky?' => 'blue',
    'What is 2 + 2?' => '4',
];

CAPTCHA Best Practices

  • Always enable for account registration
  • Enable for anonymous edits (if allowed)
  • Consider disabling for trusted user groups
  • Use QuestyCaptcha if you cannot use external services

File Upload Security

Restrict File Types

// Only allow safe file types
$wgFileExtensions = [ 'png', 'gif', 'jpg', 'jpeg', 'svg', 'pdf', 'webp' ];

// Strict checking
$wgCheckFileExtensions = true;
$wgStrictFileExtensions = true;

// MIME type verification
$wgVerifyMimeType = true;

Disable Dangerous File Types

// Explicitly forbid dangerous types
$wgFileBlacklist = [
    'html', 'htm', 'php', 'php5', 'phtml', 'exe', 'bat',
    'cmd', 'com', 'dll', 'js', 'vbs', 'asp', 'aspx', 'jsp',
];

SVG Security

// SVGs can contain JavaScript — sanitize them
$wgSVGMetadataCutoff = 262144;
$wgAllowTitlesInSVG = false;

// Disable SVG upload if not needed
// Just remove 'svg' from $wgFileExtensions

User Account Security

Password Policy

// Enforce strong passwords
$wgPasswordPolicy['policies']['default'] = [
    'MinimalPasswordLength' => 10,
    'MinimumPasswordLengthToLogin' => 1,
    'MaximalPasswordLength' => 4096,
    'PasswordCannotMatchUsername' => true,
    'PasswordCannotMatchBlacklist' => true,
];

// More aggressive for administrators
$wgPasswordPolicy['policies']['sysop'] = [
    'MinimalPasswordLength' => 14,
    'MinimumPasswordLengthToLogin' => 10,
];

Account Creation Control

// Require email confirmation to edit
$wgEmailConfirmToEdit = true;

// Disable anonymous account creation
$wgGroupPermissions['*']['createaccount'] = false;
$wgGroupPermissions['user']['createaccount'] = true;

// Require admin approval for account creation
$wgConfirmAccountRequest = true;

Security Headers

Add security headers in your web server configuration:

# Apache
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "same-origin"
Header always set X-XSS-Protection "1; mode=block"
# Nginx
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "same-origin" always;

Security Hardening Checklist

Server Level:
  ☐ Block direct access to LocalSettings.php
  ☐ Protect includes/, maintenance/, cache/ directories
  ☐ Disable directory listing
  ☐ Use HTTPS (not HTTP)
  ☐ Keep PHP, MySQL, and web server updated

MediaWiki Configuration:
  ☐ Restrict file upload types
  ☐ Enable MIME verification
  ☐ Configure CAPTCHA (at minimum for registration)
  ☐ Enforce strong passwords
  ☐ Require email confirmation for editing
  ☐ Enable CSP headers
  ☐ Keep CSRF protection enabled

User Management:
  ☐ Review user groups regularly
  ☐ Remove inactive administrator accounts
  ☐ Use principle of least privilege
  ☐ Monitor failed login attempts

Extensions:
  ☐ Keep extensions updated
  ☐ Remove unused extensions
  ☐ Vet extensions before installation
  ☐ Check extension security advisories

Monitoring:
  ☐ Review logs weekly
  ☐ Monitor for suspicious edits
  ☐ Set up intrusion detection alerts
  ☐ Review firewall logs

Backup:
  ☐ Regular backups (verified)
  ☐ Offsite backup copy
  ☐ Test restore procedure

What You Learned

  • .htaccess protects sensitive files at the server level
  • CSP headers prevent XSS Attacks
  • MediaWiki has built-in XSS and CSRF protection
  • CAPTCHA stops automated abuse
  • File uploads require strict type and MIME checking
  • Strong password policies protect user accounts
  • Security headers add browser-level protection
  • Regular monitoring and updates are essential

Common Mistakes

Mistake Why It Happens How to Fix
Leaving LocalSettings.php world-readable Default file permissions not changed Set permissions: chmod 600 LocalSettings.php. It should only be readable by the web server user.
Allowing raw HTML for all users $wgRawHtml = true Disable raw HTML: $wgRawHtml = false. If needed, restrict to trusted groups only.
Not updating MediaWiki for months Security patches missed Subscribe to MediaWiki security announcements. Apply security updates within 48 hours.
Installing extensions without checking Untrusted code on the server Only install extensions from the official MediaWiki extension registry. Check reviews and maintenance status.
Weak admin password Easy to guess or brute-force Enforce minimum 14-character passwords for administrators. Use a password manager. Enable two-factor authentication.

Practice Questions

  1. What is Content Security Policy and how does it prevent XSS attacks?
  2. How does the CAPTCHA system prevent automated spam, and what triggers should you enable?
  3. What file types should you allow for uploads, and which should you explicitly block?
  4. Challenge: Perform a security audit of your wiki. Review LocalSettings.php for security-related settings. Check .htaccess for directory protection. Verify CSP headers are enabled. Test CAPTCHA by simulating a registration. Review file upload permissions. Check password policy configuration. Review user groups and remove unused administrators. Create a "Security Hardening" page documenting all security measures in place. List any vulnerabilities found and their remediation steps. Finally, create a regular security review schedule.

FAQ

Is HTTPS required for MediaWiki?

Yes, strongly recommended. Without HTTPS, all traffic (including passwords) is transmitted in plain text. Let's Encrypt provides free SSL certificates. All modern wikis should use HTTPS exclusively.

How do I know if my wiki has been compromised?

Check for: unfamiliar administrator accounts, unexplained page creations/deletions, suspicious edits adding external links, unusual error log entries, unexpected file modifications in the MediaWiki directory, and slow performance from spam traffic.

What is the most common attack vector for wikis?

Spam is the most common attack. Automated bots register accounts and add spam links. This is prevented by CAPTCHA, email confirmation, and spam blacklists. The AbuseFilter extension adds additional protection.

Can I use two-factor authentication with MediaWiki?

Yes. The TOTP (Time-based One-Time Password) extension provides two-factor authentication. Users generate codes from an authenticator app. Enable it at least for administrator accounts.

Should I install a web application firewall?

A WAF (like ModSecurity or Cloudflare's WAF) adds an additional layer of protection. It can block common attack patterns before they reach MediaWiki. It is recommended for production wikis.

Mini Project

Goal: Perform a complete security audit and hardening of your wiki.

  1. Review and secure LocalSettings.php permissions (chmod 600)
  2. Create or update .htaccess to protect sensitive directories
  3. Configure CSP headers (start in report-only mode)
  4. Install and configure ConfirmEdit with appropriate triggers
  5. Review and restrict file upload types
  6. Enforce strong password policy (12+ chars, no username match)
  7. Enable email confirmation for editing
  8. Review all user groups and remove inactive admins
  9. Enable HTTPS (if not already)
  10. Set up security monitoring (log review, backup verification)
  11. Create a "Security Posture" page documenting all hardening measures
  12. Schedule quarterly security reviews

What's Next

Congratulations — you have completed the full MediaWiki tutorial series. You now have the skills to install, configure, maintain, secure, and scale a MediaWiki wiki for any purpose.

Review the full course on the MediaWiki Tutorials homepage or start building your production wiki using the skills you have learned.

For additional help, explore extensions at the MediaWiki Extension Registry or join the MediaWiki community at mediawiki.org.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro