{"id":396570,"date":"2026-11-01T10:58:32","date_gmt":"2026-11-01T10:58:32","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/jm-website-security-hardening\/"},"modified":"2026-11-01T10:57:57","modified_gmt":"2026-11-01T10:57:57","slug":"jm-website-security-hardening","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/jm-website-security-hardening\/","author":15497876,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.0","stable_tag":"1.0.0","tested":"7.1.4","requires":"6.3","requires_php":"8.0","requires_plugins":null,"header_name":"JM Website Security Hardening","header_author":"Jose Mortellaro","header_description":"Lets an administrator decide what the site may load and who may use its files, then applies the matching security headers and Content Security Policy.","assets_banners_color":"ddeffd","last_updated":"2026-11-01 10:57:57","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/josemortellaro.com\/","rating":0,"author_block_rating":0,"active_installs":0,"downloads":107,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.0":{"tag":"1.0.0","author":"giuse","date":"2026-11-01 10:57:57","revision":3777884}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128-rtl.jpg":{"filename":"icon-128x128-rtl.jpg","revision":3777884,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-128x128.jpg":{"filename":"icon-128x128.jpg","revision":3777884,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256-rtl.jpg":{"filename":"icon-256x256-rtl.jpg","revision":3777884,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon-256x256.jpg":{"filename":"icon-256x256.jpg","revision":3777884,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500-rtl.jpg":{"filename":"banner-1544x500-rtl.jpg","revision":3777884,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-1544x500.jpg":{"filename":"banner-1544x500.jpg","revision":3777884,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250-rtl.jpg":{"filename":"banner-772x250-rtl.jpg","revision":3777884,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250},"banner-772x250.jpg":{"filename":"banner-772x250.jpg","revision":3777884,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.0"],"block_files":[],"assets_screenshots":[],"screenshots":[]},"plugin_section":[],"plugin_tags":[7642,31093,2846,396,600],"plugin_category":[54],"plugin_contributors":[157933],"plugin_business_model":[],"class_list":["post-396570","plugin","type-plugin","status-publish","hentry","plugin_tags-clickjacking","plugin_tags-hardening","plugin_tags-headers","plugin_tags-privacy","plugin_tags-security","plugin_category-security-and-spam-protection","plugin_contributors-giuse","plugin_committers-giuse"],"banners":{"banner":"https:\/\/ps.w.org\/jm-website-security-hardening\/assets\/banner-772x250.jpg?rev=3777884","banner_2x":"https:\/\/ps.w.org\/jm-website-security-hardening\/assets\/banner-1544x500.jpg?rev=3777884","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/jm-website-security-hardening\/assets\/icon-128x128.jpg?rev=3777884","icon_2x":"https:\/\/ps.w.org\/jm-website-security-hardening\/assets\/icon-256x256.jpg?rev=3777884","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>JM Website Security Hardening asks what the site is allowed to do, in plain language, and sends the matching browser rules.<\/p>\n\n<p>You choose:<\/p>\n\n<ul>\n<li>where JavaScript, styles, images, fonts, audio, video, and frames may come from<\/li>\n<li>which sites the page may contact in the background<\/li>\n<li>where forms may send their data<\/li>\n<li>who may place this site inside a frame<\/li>\n<li>who may display images hosted in the media library<\/li>\n<li>how much of the page address is shared with the next site<\/li>\n<li>whether the browser should remember HTTPS<\/li>\n<li>which browser features, such as the camera and the microphone, a page may use<\/li>\n<\/ul>\n\n<p>The plugin writes the Content Security Policy and the related security headers from those answers. A log shows addresses that fell outside the rules, so you can start without blocking anything and turn blocking on when the result looks right.<\/p>\n\n<p>The recommended answers suit a normal site. Strict answers refuse code written directly in the page and can break a theme, a plugin, the dashboard, or the login screen.<\/p>\n\n<p>Image limits are checked for requests WordPress handles. On Apache and LiteSpeed they are also written into the uploads folder, between the markers <code>BEGIN JMWSH<\/code> and <code>END JMWSH<\/code>. On other servers the settings screen shows configuration you can add yourself.<\/p>\n\n<h4>Headers<\/h4>\n\n<p>Depending on the answers, the plugin can send:<\/p>\n\n<ul>\n<li>Content-Security-Policy, or Content-Security-Policy-Report-Only<\/li>\n<li>X-Frame-Options<\/li>\n<li>X-Content-Type-Options<\/li>\n<li>X-XSS-Protection<\/li>\n<li>X-Permitted-Cross-Domain-Policies<\/li>\n<li>Referrer-Policy<\/li>\n<li>Permissions-Policy<\/li>\n<li>Strict-Transport-Security, only on HTTPS<\/li>\n<li>Cross-Origin-Opener-Policy<\/li>\n<li>Report-To and Reporting-Endpoints<\/li>\n<li>Cross-Origin-Resource-Policy, on image files when only this site may display them<\/li>\n<\/ul>\n\n<h4>Developer hooks<\/h4>\n\n<ul>\n<li><code>jmwsh_settings<\/code> filters the normalized settings before headers are built.<\/li>\n<li><code>jmwsh_headers<\/code> filters the final header names and values.<\/li>\n<li><code>jmwsh_download_hosts<\/code> filters the host names allowed to display hosted files.<\/li>\n<li><code>jmwsh_htaccess_rules<\/code> filters the Apache lines written to the uploads folder.<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Upload the plugin folder to <code>\/wp-content\/plugins\/<\/code>, or install the zip from the Plugins screen.<\/li>\n<li>Activate JM Website Security Hardening.<\/li>\n<li>Open Settings \u2192 Website Security.<\/li>\n<li>Review the answers. Leave \u201cAllow it, and keep a note\u201d selected at first.<\/li>\n<li>Turn protection on and save.<\/li>\n<li>Browse the public site, then read the notes at the bottom of the settings screen.<\/li>\n<li>Switch to \u201cBlock it\u201d when you are ready.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20need%20to%20understand%20content%20security%20policy%3F\"><h3>Do I need to understand Content Security Policy?<\/h3><\/dt>\n<dd><p>No. The screen asks where files may come from and who may use this site. The policy is built from the answers.<\/p><\/dd>\n<dt id=\"will%20this%20break%20my%20site%3F\"><h3>Will this break my site?<\/h3><\/dt>\n<dd><p>It can, if you block code that a theme or plugin writes directly into the page. Start with notes instead of blocking. The recommended answers allow that inline code. The strict answers do not.<\/p><\/dd>\n<dt id=\"can%20i%20see%20what%20would%20have%20been%20blocked%3F\"><h3>Can I see what would have been blocked?<\/h3><\/dt>\n<dd><p>Yes. Choose \u201cAllow it, and keep a note\u201d, turn on \u201cKeep a note when a rule matches\u201d, save, and visit the public site. The settings screen lists the page, the kind of file, and the address.<\/p><\/dd>\n<dt id=\"who%20can%20display%20images%20from%20the%20media%20library%3F\"><h3>Who can display images from the media library?<\/h3><\/dt>\n<dd><p>Anyone, only this website, or this website plus the domains you list. A visitor who types the image address can still open it. Browsers that hide the previous page are treated as a direct visit. On Apache, saving the rule updates the uploads folder. On nginx, copy the configuration shown on the settings screen.<\/p><\/dd>\n<dt id=\"are%20the%20notes%20sent%20anywhere%3F\"><h3>Are the notes sent anywhere?<\/h3><\/dt>\n<dd><p>No. They are written to wp-content\/uploads\/jm-website-security-hardening\/csp.log. Only the latest notes are kept. Clear them from the settings screen, or delete the plugin to remove the file.<\/p><\/dd>\n<dt id=\"does%20each%20site%20in%20a%20network%20have%20its%20own%20rules%3F\"><h3>Does each site in a network have its own rules?<\/h3><\/dt>\n<dd><p>Yes. Settings are saved per site.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Decide what your site may load and who may use its files. Security headers are written for you.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/396570","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=396570"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/giuse"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=396570"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=396570"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=396570"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=396570"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=396570"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=396570"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}