UNPKG

@casoon/auditmysite

Version:

A comprehensive command-line tool for automated accessibility, security, performance, and SEO testing using Playwright and pa11y, based on sitemap URLs

167 lines 8.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HttpsTest = void 0; const base_test_1 = require("../base-test"); class HttpsTest extends base_test_1.BaseAccessibilityTest { constructor() { super(...arguments); this.name = 'HTTPS Compliance Test'; this.description = 'Checks HTTPS implementation, SSL/TLS configuration, and secure communication'; this.category = 'security'; this.priority = 'critical'; this.standards = ['OWASP Security Guidelines', 'HTTPS Best Practices', 'SSL/TLS Standards']; } async run(context) { const { page, url } = context; try { const issues = []; const warnings = []; const details = {}; // Check if URL uses HTTPS if (!url.startsWith('https://')) { issues.push('Site is not using HTTPS - critical security requirement'); return this.createResult(false, 1, issues, warnings, details); } // Navigate to the page await page.goto(url, { waitUntil: 'networkidle' }); // Get security info from the page const securityInfo = await this.evaluateOnPage(page, () => { const info = {}; // Check if page is served over HTTPS info.isHttps = window.location.protocol === 'https:'; // Check for mixed content const mixedContentIssues = []; const images = document.querySelectorAll('img[src^="http:"]'); const scripts = document.querySelectorAll('script[src^="http:"]'); const links = document.querySelectorAll('link[href^="http:"]'); const iframes = document.querySelectorAll('iframe[src^="http:"]'); if (images.length > 0) { mixedContentIssues.push(`${images.length} HTTP images found`); } if (scripts.length > 0) { mixedContentIssues.push(`${scripts.length} HTTP scripts found`); } if (links.length > 0) { mixedContentIssues.push(`${links.length} HTTP stylesheets found`); } if (iframes.length > 0) { mixedContentIssues.push(`${iframes.length} HTTP iframes found`); } info.mixedContentIssues = mixedContentIssues; info.mixedContentCount = images.length + scripts.length + links.length + iframes.length; // Check for insecure forms const forms = document.querySelectorAll('form'); const insecureForms = []; forms.forEach((form, index) => { const action = form.getAttribute('action'); if (action && action.startsWith('http:')) { insecureForms.push(`Form ${index + 1} submits to HTTP: ${action}`); } }); info.insecureForms = insecureForms; info.formCount = forms.length; // Check for insecure redirects const metaRefresh = document.querySelector('meta[http-equiv="refresh"]'); if (metaRefresh) { const content = metaRefresh.getAttribute('content'); if (content && content.includes('http://')) { info.insecureRedirect = content; } } // Check for insecure WebSocket connections const wsConnections = []; const scriptElements = document.querySelectorAll('script'); scriptElements.forEach(script => { const content = script.textContent || ''; if (content.includes('ws://')) { wsConnections.push('WebSocket connection over insecure protocol (ws://)'); } }); info.wsConnections = wsConnections; return info; }); details.securityInfo = securityInfo; // Check for mixed content if (securityInfo.mixedContentCount > 0) { issues.push(`Mixed content detected: ${securityInfo.mixedContentCount} insecure resources loaded over HTTP`); details.mixedContentIssues = securityInfo.mixedContentIssues; } // Check for insecure forms if (securityInfo.insecureForms.length > 0) { issues.push(`Insecure forms detected: ${securityInfo.insecureForms.length} forms submit to HTTP`); details.insecureForms = securityInfo.insecureForms; } // Check for insecure redirects if (securityInfo.insecureRedirect) { issues.push(`Insecure redirect detected: ${securityInfo.insecureRedirect}`); details.insecureRedirect = securityInfo.insecureRedirect; } // Check for insecure WebSocket connections if (securityInfo.wsConnections.length > 0) { issues.push(`Insecure WebSocket connections detected: ${securityInfo.wsConnections.length} connections use ws://`); details.wsConnections = securityInfo.wsConnections; } // Check response headers for security indicators const response = await page.waitForResponse(url); const headers = response.headers(); // Check for HSTS header const hsts = headers['strict-transport-security']; if (!hsts) { warnings.push('Missing HTTP Strict Transport Security (HSTS) header'); } else { details.hsts = hsts; if (!hsts.includes('max-age=')) { warnings.push('HSTS missing max-age directive'); } if (!hsts.includes('includeSubDomains')) { warnings.push('HSTS should include includeSubDomains directive'); } } // Check for secure cookies const setCookieHeaders = headers['set-cookie']; if (setCookieHeaders) { const cookies = Array.isArray(setCookieHeaders) ? setCookieHeaders : [setCookieHeaders]; const insecureCookies = []; cookies.forEach((cookie, index) => { if (!cookie.includes('Secure') && !cookie.includes('HttpOnly')) { insecureCookies.push(`Cookie ${index + 1}: Missing Secure and HttpOnly flags`); } else if (!cookie.includes('Secure')) { insecureCookies.push(`Cookie ${index + 1}: Missing Secure flag`); } else if (!cookie.includes('HttpOnly')) { insecureCookies.push(`Cookie ${index + 1}: Missing HttpOnly flag`); } }); if (insecureCookies.length > 0) { warnings.push(`Insecure cookies detected: ${insecureCookies.length} cookies missing security flags`); details.insecureCookies = insecureCookies; } } // Check for secure content type const contentType = headers['content-type']; if (contentType && contentType.includes('text/html')) { // Check for secure HTML content const htmlContent = await page.content(); if (htmlContent.includes('http://')) { warnings.push('HTML content contains HTTP URLs'); } } // Calculate HTTPS compliance score const totalChecks = 8; const passedChecks = totalChecks - issues.length - warnings.length; const httpsScore = Math.round((passedChecks / totalChecks) * 100); details.httpsScore = httpsScore; details.totalChecks = totalChecks; details.passedChecks = passedChecks; details.isHttps = true; return this.createResult(issues.length === 0, issues.length + warnings.length, issues, warnings, details); } catch (error) { return this.createErrorResult(`HTTPS Test failed: ${error}`); } } } exports.HttpsTest = HttpsTest; //# sourceMappingURL=https-test.js.map