tl-shared-security
Version:
Enterprise-grade security module for frontend and backend applications with comprehensive protection against XSS, CSRF, SQL injection, and other security vulnerabilities
205 lines • 7.53 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecurityScanner = void 0;
class SecurityScanner {
scan() {
const issues = [];
// Check security headers
issues.push(...this.checkSecurityHeaders());
// Check for XSS vulnerabilities
issues.push(...this.checkXssVulnerabilities());
// Check HTTPS usage
issues.push(...this.checkHttpsUsage());
// Check local storage security
issues.push(...this.checkStorageSecurity());
// Check for mixed content
issues.push(...this.checkMixedContent());
// Check CSP
issues.push(...this.checkContentSecurityPolicy());
const score = this.calculateScore(issues);
const recommendations = this.generateRecommendations(issues);
return { score, issues, recommendations };
}
checkSecurityHeaders() {
const issues = [];
// Check if running in secure context
if (!window.isSecureContext) {
issues.push({
type: 'high',
category: 'network',
message: 'Page not served over HTTPS',
fix: 'Ensure all pages are served over HTTPS in production',
});
}
return issues;
}
checkXssVulnerabilities() {
const issues = [];
// Check for dangerous innerHTML usage
const scripts = document.querySelectorAll('script');
scripts.forEach((script, index) => {
if (script.innerHTML.includes('innerHTML') && script.innerHTML.includes('user')) {
issues.push({
type: 'high',
category: 'xss',
message: 'Potential XSS vulnerability in script',
element: `script[${index}]`,
fix: 'Use textContent instead of innerHTML or sanitize input',
});
}
});
// Check for eval usage
if (document.documentElement.innerHTML.includes('eval(')) {
issues.push({
type: 'high',
category: 'xss',
message: 'Use of eval() detected',
fix: 'Avoid using eval() - use JSON.parse() or other safe alternatives',
});
}
return issues;
}
checkHttpsUsage() {
const issues = [];
if (location.protocol !== 'https:' && location.hostname !== 'localhost') {
issues.push({
type: 'high',
category: 'network',
message: 'Site not using HTTPS',
fix: 'Configure HTTPS for all production environments',
});
}
// Check for mixed content
const httpResources = document.querySelectorAll('[src^="http:"], [href^="http:"]');
if (httpResources.length > 0) {
issues.push({
type: 'medium',
category: 'network',
message: `${httpResources.length} HTTP resources found on HTTPS page`,
fix: 'Update all resource URLs to use HTTPS',
});
}
return issues;
}
checkStorageSecurity() {
const issues = [];
// Check localStorage for sensitive data patterns
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key) {
const value = localStorage.getItem(key);
if (value && this.containsSensitiveData(key, value)) {
issues.push({
type: 'medium',
category: 'storage',
message: `Potentially sensitive data in localStorage: ${key}`,
fix: 'Use secure storage or encrypt sensitive data',
});
}
}
}
return issues;
}
checkMixedContent() {
const issues = [];
if (location.protocol === 'https:') {
const httpImages = document.querySelectorAll('img[src^="http:"]');
const httpIframes = document.querySelectorAll('iframe[src^="http:"]');
if (httpImages.length > 0) {
issues.push({
type: 'medium',
category: 'network',
message: `${httpImages.length} HTTP images on HTTPS page`,
fix: 'Update image URLs to use HTTPS',
});
}
if (httpIframes.length > 0) {
issues.push({
type: 'high',
category: 'network',
message: `${httpIframes.length} HTTP iframes on HTTPS page`,
fix: 'Update iframe URLs to use HTTPS',
});
}
}
return issues;
}
checkContentSecurityPolicy() {
const issues = [];
const cspMeta = document.querySelector('meta[http-equiv="Content-Security-Policy"]');
if (!cspMeta) {
issues.push({
type: 'medium',
category: 'headers',
message: 'No Content Security Policy found',
fix: 'Implement CSP headers to prevent XSS attacks',
});
}
else {
const cspContent = cspMeta.getAttribute('content') || '';
if (cspContent.includes("'unsafe-inline'")) {
issues.push({
type: 'medium',
category: 'headers',
message: 'CSP allows unsafe-inline',
fix: 'Remove unsafe-inline and use nonces or hashes',
});
}
}
return issues;
}
containsSensitiveData(key, value) {
const sensitivePatterns = [
/password/i,
/token/i,
/secret/i,
/key/i,
/auth/i,
/session/i,
/credit.*card/i,
/ssn/i,
/social.*security/i,
];
const keyLower = key.toLowerCase();
const valueLower = value.toLowerCase();
return sensitivePatterns.some(pattern => pattern.test(keyLower) || pattern.test(valueLower));
}
calculateScore(issues) {
let score = 100;
issues.forEach(issue => {
switch (issue.type) {
case 'high':
score -= 20;
break;
case 'medium':
score -= 10;
break;
case 'low':
score -= 5;
break;
}
});
return Math.max(0, score);
}
generateRecommendations(issues) {
const recommendations = new Set();
issues.forEach(issue => {
if (issue.fix) {
recommendations.add(issue.fix);
}
});
// General recommendations
if (issues.some(i => i.category === 'xss')) {
recommendations.add('Implement input sanitization and output encoding');
}
if (issues.some(i => i.category === 'network')) {
recommendations.add('Ensure all communications use HTTPS');
}
if (issues.some(i => i.category === 'headers')) {
recommendations.add('Implement comprehensive security headers');
}
return Array.from(recommendations);
}
}
exports.SecurityScanner = SecurityScanner;
//# sourceMappingURL=security-scanner.js.map
;