/**
* HVAC Community Events - Build System Security Tests
*
* Focused security testing for the critical vulnerabilities identified:
* 1. Manifest integrity vulnerability - no validation of manifest.json tampering
* 2. User agent security vulnerability - unsanitized user agent parsing
* 3. Missing bundle validation - bundles enqueued without existence checks
* 4. No graceful degradation - no fallback when bundles fail
*
* @package HVAC_Community_Events
* @since 2.0.0
*/
const fs = require('fs').promises;
const path = require('path');
const { test, expect } = require('@playwright/test');
const { execSync } = require('child_process');
// Security test configuration
const SECURITY_CONFIG = {
PROJECT_ROOT: path.resolve(__dirname, '..'),
MANIFEST_PATH: path.resolve(__dirname, '../assets/js/dist/manifest.json'),
BUNDLED_ASSETS_CLASS: path.resolve(__dirname, '../includes/class-hvac-bundled-assets.php'),
BASE_URL: process.env.BASE_URL || 'http://localhost:8080',
// Critical security payloads
ATTACK_PAYLOADS: {
// Manifest integrity attacks
MANIFEST_XSS: '{"hvac-core.js": ".js"}',
MANIFEST_SCRIPT_INJECTION: '{"hvac-core.js": "javascript:alert(\'MANIFEST_INJECTION\')"}',
MANIFEST_PATH_TRAVERSAL: '{"hvac-core.js": "../../../../etc/passwd"}',
MANIFEST_DATA_URI: '{"hvac-core.js": "data:text/javascript,alert(\'DATA_URI_ATTACK\')"}',
MANIFEST_PROTOCOL_POLLUTION: '{"hvac-core.js": "file:///etc/passwd"}',
// User agent injection attacks
USER_AGENT_SCRIPT: 'Mozilla/5.0 (X11; Linux x86_64) ',
USER_AGENT_SQL: 'Mozilla/5.0\'; DROP TABLE wp_users; --',
USER_AGENT_PHP_INJECTION: 'Mozilla/5.0 ',
USER_AGENT_COMMAND_INJECTION: 'Mozilla/5.0 $(rm -rf /)',
USER_AGENT_NULL_BYTE: 'Mozilla/5.0\x00',
// Bundle path attacks
BUNDLE_PATH_TRAVERSAL: '../../../wp-config.php',
BUNDLE_ABSOLUTE_PATH: '/etc/passwd',
BUNDLE_PROTOCOL_ATTACK: 'http://evil.com/malicious.js',
BUNDLE_DOUBLE_ENCODING: '%2e%2e%2f%2e%2e%2f%2e%2e%2fwp-config.php'
}
};
/**
* Security Test Framework
*/
class SecurityTestFramework {
/**
* Backup original files before security testing
*/
static async backupOriginalFiles() {
const backups = {};
try {
// Backup manifest
if (await fs.access(SECURITY_CONFIG.MANIFEST_PATH).then(() => true).catch(() => false)) {
const manifestContent = await fs.readFile(SECURITY_CONFIG.MANIFEST_PATH, 'utf-8');
backups.manifest = manifestContent;
}
} catch (error) {
console.warn('Could not backup manifest:', error.message);
}
return backups;
}
/**
* Restore original files after testing
*/
static async restoreOriginalFiles(backups) {
try {
if (backups.manifest) {
await fs.writeFile(SECURITY_CONFIG.MANIFEST_PATH, backups.manifest);
} else {
// Remove test manifest if no backup existed
await fs.unlink(SECURITY_CONFIG.MANIFEST_PATH).catch(() => {});
}
} catch (error) {
console.warn('Could not restore files:', error.message);
}
}
/**
* Create malicious manifest for testing
*/
static async createMaliciousManifest(payload) {
await fs.writeFile(SECURITY_CONFIG.MANIFEST_PATH, payload);
console.log(`š Created malicious manifest: ${payload.substring(0, 100)}...`);
}
/**
* Analyze PHP code for security vulnerabilities
*/
static async analyzePHPSecurity() {
try {
const phpCode = await fs.readFile(SECURITY_CONFIG.BUNDLED_ASSETS_CLASS, 'utf-8');
return {
// Check for unsanitized user input
hasUnsanitizedUserAgent: phpCode.includes('$_SERVER[\'HTTP_USER_AGENT\']') &&
!phpCode.includes('sanitize_text_field') &&
!phpCode.includes('esc_attr'),
// Check for unvalidated file paths
hasUnvalidatedPaths: phpCode.includes('file_get_contents') &&
!phpCode.includes('wp_safe_remote_get') &&
!phpCode.includes('validate_file'),
// Check for missing nonce verification
hasMissingNonce: phpCode.includes('$_POST') &&
!phpCode.includes('wp_verify_nonce'),
// Check for direct file inclusion
hasDirectInclusion: phpCode.includes('include') ||
phpCode.includes('require') ||
phpCode.includes('file_get_contents'),
// Check for output escaping
hasMissingEscaping: phpCode.includes('echo ') &&
!phpCode.includes('esc_html') &&
!phpCode.includes('esc_attr'),
codeLength: phpCode.length
};
} catch (error) {
console.error('Could not analyze PHP security:', error.message);
return { error: error.message };
}
}
/**
* Test for common web vulnerabilities
*/
static async testWebVulnerabilities(page, testUrl) {
const vulnerabilities = {
xss: false,
sqli: false,
pathTraversal: false,
codeInjection: false,
errorDisclosure: false
};
const errors = [];
// Monitor console errors that might indicate vulnerabilities
page.on('console', (message) => {
if (message.type() === 'error') {
errors.push(message.text());
// Check for XSS execution
if (message.text().includes('XSS') || message.text().includes('alert')) {
vulnerabilities.xss = true;
}
}
});
// Monitor network requests for suspicious activity
const suspiciousRequests = [];
page.on('request', (request) => {
const url = request.url();
if (url.includes('../') || url.includes('/etc/') || url.includes('passwd') ||
url.includes('DROP TABLE') || url.includes('