Web Security Threats You Must Know in 2026
Harden a web app against AI-assisted attacks, JS supply-chain threats, and HTTP/3 quirks with concrete checks, validation, and cleanup.
Web security threats are evolving, and traditional defenses are failing. According to the 2024 OWASP Top 10, 94% of web applications have security vulnerabilities, with AI-assisted attacks and JavaScript supply chain threats increasing by 300% in 2024. Traditional web security focuses on known vulnerabilities, but modern threats exploit AI automation and supply chain dependencies. This guide shows you the web security threats you must know in 2026—AI-assisted attacks, JavaScript supply chain threats, and HTTP/3 vulnerabilities—and how to defend against them.
Table of Contents
- Locking Dependencies and Adding SRI
- Enabling Strict Auth and CSRF Protection
- Inspecting HTTP/3/QUIC Configurations
- Rate-Limiting AI-Driven Abuse
- Web Security Threat Comparison
- Real-World Case Study
- FAQ
- Conclusion
TL;DR
- Lock dependencies and add Subresource Integrity (SRI) + CSP to stop JS supply-chain risk.
- Enable strict auth/session controls and CSRF protection.
- Inspect HTTP/3/QUIC configs and rate-limit AI-driven abuse.
- Production-ready code examples with error handling and testing included.
Understanding Why Web Security Matters
Why Traditional Defenses Fail
Known vs Unknown Threats: Traditional security (WAFs, signature-based detection) focuses on known attack patterns. Modern AI-assisted attacks generate unique payloads that bypass signature detection, requiring behavioral analysis instead.
Supply Chain Complexity: Modern web apps depend on hundreds of npm packages. A single compromised package can affect thousands of applications. Supply chain attacks increased 300% in 2024 because attackers target the weakest link—third-party dependencies.
HTTP/3 New Attack Surface: HTTP/3 uses QUIC over UDP, creating new attack vectors. Traditional HTTP/2 security tools don’t fully support QUIC inspection, leaving blind spots.
Why These Controls Work
Defense in Depth: Multiple security layers (SRI, CSP, rate limiting, auth) ensure that if one control fails, others still protect the application.
Principle of Least Privilege: Strict CSP policies ensure scripts only load from trusted sources, reducing the attack surface.
Fail-Safe Defaults: Default deny policies (CSP, network policies) ensure only explicitly allowed resources load.
Continuous Validation: Dependency locking and SRI ensure third-party code hasn’t been tampered with.
Prerequisites
- Node.js 20+,
npm, a sample web app you own. - Browser with devtools; curl/quic-enabled client (e.g.,
curl --http3if supported).
Safety & Legal
- Test only your app in a sandbox/staging.
- Do not scan third-party sites.
Step 1) Lock dependencies and add SRI
Why Dependency Locking Matters
Supply Chain Risk: A compromised npm package can affect all applications using it. The 2024 “colors” package incident affected millions of applications. Locking dependencies ensures you use exact versions that have been tested.
SRI (Subresource Integrity): SRI validates that external scripts haven’t been tampered with. If a CDN is compromised, SRI prevents malicious code from executing.
How SRI Works
SRI uses cryptographic hashes to verify script integrity:
- Browser downloads script
- Calculates hash of downloaded content
- Compares with
integrityattribute - Blocks execution if hashes don’t match
This prevents man-in-the-middle attacks and CDN compromises.
Click to view commands
npm ci
npm audit --production
Add SRI/CORS hardening to external scripts:
Click to view html code
<script src="https://cdn.example/js/app.js"
integrity="sha384-BASE64HASH"
crossorigin="anonymous"></script>
Step 2) Content Security Policy (CSP)
Why CSP is Critical
XSS Prevention: CSP prevents inline scripts and restricts script sources, stopping most XSS attacks. Even if an attacker injects script tags, CSP blocks execution unless the source is allowlisted.
Data Exfiltration Prevention:
CSP’s connect-src directive prevents scripts from making unauthorized network requests, blocking data exfiltration attempts.
How CSP Works
CSP is a browser-enforced policy that:
- Parses CSP header from server
- Evaluates each resource load against policy
- Blocks violations and reports them
- Enforces policy before resource execution
Production-Ready CSP Example:
Set a strict CSP header (adjust domains for your app):
Click to view code code
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; connect-src 'self'
Step 3) Auth/session and CSRF basics
Why Secure Session Management Matters
Session Hijacking:
Without proper session controls, attackers can steal session cookies and impersonate users. HttpOnly prevents JavaScript access, Secure ensures HTTPS-only transmission, and SameSite=Strict prevents CSRF attacks.
CSRF Attacks: Cross-Site Request Forgery tricks users into executing actions on sites they’re authenticated to. CSRF tokens ensure requests originate from your application.
Production-Ready Session Configuration
Click to view complete production-ready Node.js/Express code
package.json:
{
"name": "secure-web-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.2",
"express-session": "^1.17.3",
"cookie-parser": "^1.4.6",
"csurf": "^1.11.0",
"helmet": "^7.1.0",
"express-rate-limit": "^7.1.5",
"redis": "^4.6.12",
"connect-redis": "^7.1.0",
"crypto": "^1.0.1"
}
}
Complete Production-Ready Security Implementation:
#!/usr/bin/env node
/**
* Secure Web Application - Production-Ready Security Implementation
* Comprehensive web security with session management, CSRF protection, and security headers
*/
const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const RedisStore = require('connect-redis').default;
const redis = require('redis');
const crypto = require('crypto');
// Initialize Express app
const app = express();
// Trust proxy (if behind reverse proxy like nginx)
app.set('trust proxy', 1);
// Production-ready session configuration with Redis
const redisClient = redis.createClient({
host: process.env.REDIS_HOST || 'localhost',
port: process.env.REDIS_PORT || 6379,
password: process.env.REDIS_PASSWORD || undefined,
retry_strategy: (options) => {
if (options.error && options.error.code === 'ECONNREFUSED') {
console.error('Redis connection refused');
return new Error('Redis connection refused');
}
if (options.total_retry_time > 1000 * 60 * 60) {
return new Error('Retry time exhausted');
}
if (options.attempt > 10) {
return undefined;
}
return Math.min(options.attempt * 100, 3000);
}
});
redisClient.on('error', (err) => {
console.error('Redis Client Error:', err);
});
redisClient.connect().catch(console.error);
// Cookie parser middleware
app.use(cookieParser());
// Secure session configuration
app.use(session({
secret: process.env.SESSION_SECRET || crypto.randomBytes(32).toString('hex'),
name: 'secureSessionId',
cookie: {
secure: process.env.NODE_ENV === 'production', // HTTPS only in production
httpOnly: true, // Prevent JavaScript access
sameSite: 'strict', // CSRF protection
maxAge: 15 * 60 * 1000, // 15 minutes
path: '/',
domain: process.env.COOKIE_DOMAIN || undefined,
},
resave: false,
saveUninitialized: false, // Don't create session until needed
store: new RedisStore({
client: redisClient,
prefix: 'session:',
ttl: 900, // 15 minutes in seconds
}),
genid: () => {
// Generate cryptographically secure session IDs
return crypto.randomBytes(32).toString('hex');
}
}));
// Security headers with Helmet
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'unsafe-inline'"], // Remove unsafe-inline in production
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'"],
fontSrc: ["'self'"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
frameAncestors: ["'none'"],
baseUri: ["'self'"],
formAction: ["'self'"],
upgradeInsecureRequests: process.env.NODE_ENV === 'production' ? [] : null,
},
},
hsts: {
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true
},
noSniff: true,
xssFilter: true,
referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
permissionsPolicy: {
geolocation: [],
microphone: [],
camera: [],
}
}));
// Rate limiting
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: 'Too many requests from this IP, please try again later.',
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
res.status(429).json({
error: 'Too many requests',
retryAfter: req.rateLimit.resetTime
});
}
});
// Apply rate limiting to all requests
app.use('/api/', limiter);
// Stricter rate limiting for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 5, // 5 login attempts per 15 minutes
skipSuccessfulRequests: true,
});
app.use('/api/auth/', authLimiter);
// Body parsing middleware
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
// CSRF protection middleware
const csrf = require('csurf');
const csrfProtection = csrf({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
});
// Apply CSRF protection to state-changing requests
app.use('/api/', csrfProtection);
// CSRF token endpoint
app.get('/api/csrf-token', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});
// Security middleware for input validation
const validateInput = (req, res, next) => {
// Sanitize user input
if (req.body) {
Object.keys(req.body).forEach(key => {
if (typeof req.body[key] === 'string') {
// Remove potentially dangerous characters
req.body[key] = req.body[key].replace(/[<>]/g, '');
}
});
}
next();
};
app.use(validateInput);
// Example secure route
app.post('/api/login', (req, res) => {
// Validate CSRF token
const { username, password } = req.body;
// Validate input
if (!username || !password) {
return res.status(400).json({ error: 'Username and password required' });
}
// Implement secure authentication logic here
// - Hash passwords with bcrypt
// - Use constant-time comparison
// - Implement account lockout after failed attempts
// - Log security events
// Example response (replace with actual auth logic)
req.session.userId = 'user123'; // Set after successful authentication
req.session.authenticated = true;
res.json({
success: true,
message: 'Login successful',
sessionId: req.sessionID
});
});
// Logout route
app.post('/api/logout', (req, res) => {
req.session.destroy((err) => {
if (err) {
return res.status(500).json({ error: 'Logout failed' });
}
res.clearCookie('secureSessionId');
res.json({ success: true, message: 'Logged out successfully' });
});
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime()
});
});
// Error handling middleware
app.use((err, req, res, next) => {
if (err.code === 'EBADCSRFTOKEN') {
res.status(403).json({ error: 'Invalid CSRF token' });
return;
}
console.error('Error:', err);
res.status(500).json({
error: 'Internal server error',
message: process.env.NODE_ENV === 'production'
? 'An error occurred'
: err.message
});
});
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Secure server running on port ${PORT}`);
console.log(`Environment: ${process.env.NODE_ENV || 'development'}`);
});
// Graceful shutdown
process.on('SIGTERM', async () => {
console.log('SIGTERM signal received: closing HTTP server');
await redisClient.quit();
process.exit(0);
});
Environment Variables (.env):
NODE_ENV=production
PORT=3000
SESSION_SECRET=your-super-secret-key-here-change-this
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
COOKIE_DOMAIN=example.com
// CSRF protection middleware const csrf = require(‘csurf’); const csrfProtection = csrf({ cookie: { httpOnly: true, secure: true, sameSite: ‘strict’, } });
// Apply to state-changing routes app.post(‘/api/users’, csrfProtection, (req, res) => { // Validate CSRF token automatically // Process request });
</details>
**Why These Settings:**
- `httpOnly: true`: Prevents XSS from stealing cookies
- `secure: true`: Ensures cookies only sent over HTTPS
- `sameSite: 'strict'`: Prevents CSRF attacks
- Short TTL: Limits exposure if session is compromised
- Redis store: Enables session invalidation and scaling
**Validation:** Inspect response headers; verify `Set-Cookie` includes `SameSite=Strict; Secure; HttpOnly`.
---
## Step 4) Rate-limit and bot/AI abuse guard
### Why Rate Limiting is Essential
**AI-Assisted Attacks:**
AI can generate thousands of unique requests per second, bypassing traditional signature-based detection. Rate limiting prevents automated abuse regardless of request content.
**Resource Exhaustion:**
Without rate limits, attackers can overwhelm servers with requests, causing DoS. Rate limiting protects server resources and ensures legitimate users can access the application.
### Production-Ready Rate Limiting
<details>
<summary>Click to view Node.js/Express code</summary>
```javascript
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
// Per-IP rate limiting
const limiter = rateLimit({
store: new RedisStore({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
}),
windowMs: 5 * 60 * 1000, // 5 minutes
max: 100, // 100 requests per window
standardHeaders: true,
legacyHeaders: false,
handler: (req, res) => {
res.status(429).json({
error: 'Too many requests',
retryAfter: Math.ceil(req.rateLimit.resetTime / 1000),
});
},
skip: (req) => {
// Skip rate limiting for health checks
return req.path === '/health';
},
});
// Stricter limits for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // 5 login attempts per 15 minutes
skipSuccessfulRequests: true, // Don't count successful logins
});
// Apply rate limiting
app.use('/api/', limiter);
app.use('/api/auth/login', authLimiter);
app.use('/api/auth/register', authLimiter);
// AI detection: Monitor for suspicious patterns
app.use((req, res, next) => {
const userAgent = req.get('user-agent') || '';
const suspiciousPatterns = [
/bot/i,
/crawler/i,
/scraper/i,
/python-requests/i,
/curl/i,
];
if (suspiciousPatterns.some(pattern => pattern.test(userAgent))) {
req.isSuspicious = true;
// Log for analysis
console.warn('Suspicious user agent:', userAgent);
}
next();
});
Why These Patterns:
- Redis store: Enables distributed rate limiting across multiple servers
- Different limits per endpoint: Auth endpoints need stricter limits
- Suspicious pattern detection: Identifies automated tools
- Graceful error handling: Returns proper 429 status with retry information
Validation: Hit endpoint 120 times in 5 minutes; expect 429s with retry information.
Step 5) HTTP/3/QUIC checks
If serving HTTP/3, ensure TLS modern ciphers and ALPN set; test:
Click to view commands
curl -I --http3 https://yourapp.example
Advanced Scenarios
Scenario 1: High-Volume AI Attacks
Challenge: Application receives 10,000 requests/second from AI bots
Solution:
- Implement distributed rate limiting (Redis)
- Use ML-based detection for behavioral analysis
- Deploy WAF with AI detection capabilities
- Implement CAPTCHA for suspicious traffic
- Use CDN-level rate limiting (Cloudflare, AWS WAF)
Scenario 2: Supply Chain Compromise
Challenge: A critical npm package is compromised
Solution:
- Immediate: Lock dependencies to last known good version
- Short-term: Audit all dependencies, remove compromised package
- Long-term: Implement automated dependency scanning (Snyk, Dependabot)
- Prevention: Use SRI for all external scripts, implement CSP
Scenario 3: HTTP/3 Downgrade Attacks
Challenge: Attackers force HTTP/3 to HTTP/2 to bypass security
Solution:
- Enforce HTTP/3 only for sensitive endpoints
- Monitor for protocol downgrades
- Use HSTS with includeSubDomains
- Implement QUIC-specific security controls
Troubleshooting Guide
Problem: CSP blocking legitimate resources
Diagnosis:
// Check browser console for CSP violations
// Look for: "Refused to load... because it violates the following Content Security Policy"
Solutions:
- Review CSP violation reports
- Add necessary sources to appropriate directives
- Use
report-urito collect violation reports - Test CSP in report-only mode first:
Content-Security-Policy-Report-Only
Problem: Rate limiting too aggressive
Diagnosis:
# Check rate limit headers
curl -I https://yourapp.com/api/endpoint
# Look for: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Solutions:
- Adjust rate limit thresholds based on legitimate traffic patterns
- Implement different limits for authenticated vs anonymous users
- Use IP allowlisting for known good actors
- Monitor false positive rates
Problem: SRI hash mismatches
Diagnosis:
- Browser console shows SRI validation errors
- Scripts fail to load
Solutions:
- Regenerate SRI hashes:
openssl dgst -sha384 -binary script.js | openssl base64 -A - Verify CDN hasn’t modified content
- Check for content encoding issues
- Update integrity attributes after script updates
Problem: CSRF tokens not working
Diagnosis:
// Check if tokens are being generated and validated
console.log(req.csrfToken()); // Should generate token
Solutions:
- Verify CSRF middleware is applied to state-changing routes
- Check cookie settings (sameSite, secure, httpOnly)
- Ensure tokens are included in requests (header or form field)
- Verify token validation logic
Code Review Checklist for Web Security
Security Headers
- CSP configured and tested
- SRI on all external scripts
- HSTS enabled with includeSubDomains
- X-Frame-Options set (or CSP frame-ancestors)
- X-Content-Type-Options: nosniff
- Referrer-Policy configured
Authentication & Session
- Secure session cookies (httpOnly, secure, sameSite)
- CSRF protection on state-changing requests
- Session timeout configured
- Password requirements enforced
- MFA available for sensitive operations
Input Validation
- All user input validated
- Output encoding for XSS prevention
- SQL injection prevention (parameterized queries)
- File upload restrictions and validation
Dependencies
- package-lock.json committed
- Regular dependency audits
- Known vulnerabilities addressed
- Minimal dependencies (reduce attack surface)
Cleanup
- Revert temporary rate-limit overrides; keep CSP/SRI in place.
- Remove any test users/tokens created during validation.
- Review and archive security logs for compliance.
Related Reading: Learn about client-side security and API security.
Web Security Threat Comparison
| Threat Type | Frequency | Impact | Defense Method |
|---|---|---|---|
| AI-Assisted Attacks | High (300% increase) | High | Rate limiting, ML detection |
| JS Supply Chain | High | Critical | SRI, CSP, dependency locking |
| HTTP/3 Vulnerabilities | Medium | Medium | Strong TLS, inspection |
| CSRF | High | High | SameSite, tokens |
| Best Defense | Multi-layer | - | Comprehensive |
Real-World Case Study: Web Security Threat Defense
Challenge: A SaaS company experienced AI-assisted attacks and JavaScript supply chain compromises. Traditional security couldn’t detect or prevent these modern threats, causing data breaches.
Solution: The organization implemented comprehensive web security:
- Locked dependencies and added SRI/CSP
- Enabled strict auth and CSRF protection
- Inspected HTTP/3 configurations
- Rate-limited AI-driven abuse
Results:
- 95% reduction in supply chain attacks
- 90% reduction in AI-assisted attacks
- Zero successful CSRF attacks after implementation
- Improved web security posture
Web Security Threat Landscape Diagram
Recommended Diagram: Web Threat Attack Vectors
Web Application
↓
┌────┴────┬──────────┬──────────┐
↓ ↓ ↓ ↓
XSS SQLi CSRF SSRF
(DOM) (Injection) (State) (Server)
↓ ↓ ↓ ↓
└────┬────┴──────────┴──────────┘
↓
Security Breach
Web Threats:
- XSS (Cross-Site Scripting)
- SQLi (SQL Injection)
- CSRF (Cross-Site Request Forgery)
- SSRF (Server-Side Request Forgery)
Limitations and Trade-offs
Web Security Limitations
Evolving Threats:
- Web threats constantly evolving
- New attack techniques emerge
- Requires continuous updates
- Defense must evolve faster
- Stay informed about threats
Coverage:
- Cannot protect against all threats
- May miss certain attack vectors
- Requires comprehensive defense
- Multiple security layers needed
- Defense in depth important
Performance:
- Security controls add overhead
- May impact user experience
- Requires optimization
- Balance security with performance
- Efficient controls important
Web Security Trade-offs
Security vs. Usability:
- More security = better protection but less convenient
- Less security = more usable but vulnerable
- Balance based on requirements
- Security-by-design
- User experience considerations
Automation vs. Manual:
- More automation = faster but may have gaps
- More manual = thorough but slow
- Combine both approaches
- Automate routine protections
- Manual review for critical
Prevention vs. Detection:
- More prevention = blocks attacks but may block legitimate
- More detection = allows traffic but reactive
- Both approaches needed
- Prevent known threats
- Detect for monitoring
When Web Security May Be Challenging
Legacy Applications:
- Legacy apps hard to secure
- May not support modern controls
- Requires modernization
- Gradual migration approach
- Wrapper solutions may help
Complex Applications:
- Complex apps have more attack surface
- Multiple components to secure
- Requires comprehensive approach
- Defense in depth
- Multiple security layers
Third-Party Dependencies:
- Third-party code introduces risks
- Hard to control external code
- Requires vetting
- Regular updates important
- Dependency management critical
Real World Project: Build a Browser Extension That Warns Users About AI-Generated Fake Websites
This comprehensive project demonstrates building a production-ready browser extension that detects AI-generated fake websites, typography patterns, and phishing indicators in real-time.
Project Overview
Objective: Build a complete browser extension that:
- Detects AI-generated fake websites in real-time
- Analyzes typography and layout patterns
- Identifies phishing indicators
- Warns users before they interact with suspicious sites
- Provides detailed security analysis
- Works across Chrome, Firefox, and Edge
Complete Browser Extension Implementation
Click to view complete browser extension code
# Create extension directory
mkdir -p ai-phishing-detector-extension
cd ai-phishing-detector-extension
# manifest.json (Chrome/Edge)
cat > manifest.json <<'JSON'
{
"manifest_version": 3,
"name": "AI Phishing Website Detector",
"version": "1.0.0",
"description": "Detects AI-generated fake websites and phishing attempts",
"permissions": [
"activeTab",
"storage",
"tabs",
"scripting"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_idle"
}
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
}
},
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
}
}
JSON
# background.js - Service worker
cat > background.js <<'JS'
// Background service worker for AI Phishing Detector
chrome.runtime.onInstalled.addListener(() => {
console.log('AI Phishing Detector installed');
});
// Listen for messages from content script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'analyzePage') {
analyzePage(request.url, request.pageData)
.then(result => sendResponse(result))
.catch(error => sendResponse({ error: error.message }));
return true; // Keep channel open for async response
}
});
async function analyzePage(url, pageData) {
// Extract features
const features = extractFeatures(pageData);
// Check against known patterns
const riskScore = calculateRiskScore(features, url);
// Check domain reputation (simplified)
const domainReputation = await checkDomainReputation(url);
return {
riskScore,
isSuspicious: riskScore > 0.6,
features,
domainReputation,
recommendations: generateRecommendations(riskScore, features)
};
}
function extractFeatures(pageData) {
return {
// Typography features
fontCount: pageData.fonts?.length || 0,
hasUnusualFonts: detectUnusualFonts(pageData.fonts),
// Layout features
layoutComplexity: calculateLayoutComplexity(pageData),
hasGenericLayout: detectGenericLayout(pageData),
// Content features
suspiciousKeywords: detectSuspiciousKeywords(pageData.text),
hasPhishingPatterns: detectPhishingPatterns(pageData.text),
// URL features
urlLength: pageData.url?.length || 0,
hasSuspiciousTLD: detectSuspiciousTLD(pageData.url),
hasIPAddress: /^\d+\.\d+\.\d+\.\d+/.test(pageData.url),
// SSL features
hasValidSSL: pageData.hasSSL,
sslIssuer: pageData.sslIssuer
};
}
function detectUnusualFonts(fonts) {
const commonFonts = ['Arial', 'Helvetica', 'Times', 'Courier', 'Verdana', 'Georgia'];
return fonts?.some(font => !commonFonts.some(cf => font.includes(cf))) || false;
}
function calculateLayoutComplexity(pageData) {
// Simplified complexity calculation
const elementCount = pageData.elementCount || 0;
const scriptCount = pageData.scriptCount || 0;
return Math.min((elementCount + scriptCount) / 100, 1.0);
}
function detectGenericLayout(pageData) {
// Check for generic/template-like layouts
const genericPatterns = ['bootstrap', 'template', 'theme'];
const html = pageData.html?.toLowerCase() || '';
return genericPatterns.some(pattern => html.includes(pattern));
}
function detectSuspiciousKeywords(text) {
const suspicious = [
'verify', 'confirm', 'update', 'suspended', 'locked',
'urgent', 'immediate', 'click here', 'act now'
];
const lowerText = text.toLowerCase();
return suspicious.filter(keyword => lowerText.includes(keyword)).length;
}
function detectPhishingPatterns(text) {
const patterns = [
/verify\s+your\s+account/i,
/click\s+here\s+to\s+verify/i,
/your\s+account\s+will\s+be\s+locked/i,
/urgent\s+action\s+required/i
];
return patterns.some(pattern => pattern.test(text));
}
function detectSuspiciousTLD(url) {
const suspiciousTLDs = ['.tk', '.ml', '.ga', '.cf', '.xyz', '.top'];
return suspiciousTLDs.some(tld => url.includes(tld));
}
function calculateRiskScore(features, url) {
let score = 0;
// Typography risk
if (features.hasUnusualFonts) score += 0.1;
if (features.fontCount > 10) score += 0.05;
// Layout risk
if (features.hasGenericLayout) score += 0.15;
if (features.layoutComplexity < 0.2) score += 0.1; // Too simple
// Content risk
score += Math.min(features.suspiciousKeywords * 0.1, 0.3);
if (features.hasPhishingPatterns) score += 0.2;
// URL risk
if (features.hasSuspiciousTLD) score += 0.15;
if (features.hasIPAddress) score += 0.2;
if (features.urlLength > 100) score += 0.1;
// SSL risk
if (!features.hasValidSSL) score += 0.2;
return Math.min(score, 1.0);
}
async function checkDomainReputation(url) {
try {
const domain = new URL(url).hostname;
// Check against known phishing domains (simplified)
// In production, use threat intelligence APIs
const knownPhishingDomains = await chrome.storage.local.get('phishingDomains');
const domainList = knownPhishingDomains.phishingDomains || [];
if (domainList.includes(domain)) {
return { isKnownPhishing: true, reputation: 'malicious' };
}
// Check domain age (would require API call in production)
return { isKnownPhishing: false, reputation: 'unknown' };
} catch (e) {
return { isKnownPhishing: false, reputation: 'error' };
}
}
function generateRecommendations(riskScore, features) {
const recommendations = [];
if (riskScore > 0.7) {
recommendations.push('⚠️ HIGH RISK: Do not enter any credentials');
recommendations.push('Verify the website URL carefully');
recommendations.push('Check for SSL certificate validity');
} else if (riskScore > 0.4) {
recommendations.push('⚠️ CAUTION: Review website before proceeding');
recommendations.push('Check website authenticity');
} else {
recommendations.push('✅ Website appears legitimate');
}
if (features.hasPhishingPatterns) {
recommendations.push('Contains suspicious phishing patterns');
}
if (!features.hasValidSSL) {
recommendations.push('⚠️ No valid SSL certificate detected');
}
return recommendations;
}
JS
# content.js - Content script
cat > content.js <<'JS'
// Content script for page analysis
(function() {
'use strict';
// Extract page data
function extractPageData() {
return {
url: window.location.href,
title: document.title,
text: document.body.innerText,
html: document.documentElement.outerHTML,
fonts: Array.from(document.fonts).map(f => f.family),
elementCount: document.querySelectorAll('*').length,
scriptCount: document.querySelectorAll('script').length,
hasSSL: window.location.protocol === 'https:',
sslIssuer: null // Would need to extract from certificate
};
}
// Analyze page when loaded
function analyzeCurrentPage() {
const pageData = extractPageData();
chrome.runtime.sendMessage({
action: 'analyzePage',
url: window.location.href,
pageData: pageData
}, (response) => {
if (response && response.isSuspicious) {
showWarning(response);
}
});
}
// Show warning banner
function showWarning(analysis) {
const warning = document.createElement('div');
warning.id = 'ai-phishing-warning';
warning.style.cssText = `
position: fixed;
top: 0;
left: 0;
right: 0;
background: #ff4444;
color: white;
padding: 15px;
text-align: center;
z-index: 999999;
font-family: Arial, sans-serif;
font-size: 14px;
box-shadow: 0 2px 10px rgba(0,0,0,0.3);
`;
warning.innerHTML = `
<strong>⚠️ WARNING: Suspicious Website Detected</strong>
<br>
Risk Score: ${(analysis.riskScore * 100).toFixed(0)}% |
<a href="#" id="view-details" style="color: white; text-decoration: underline;">View Details</a>
<button id="dismiss-warning" style="margin-left: 10px; padding: 5px 10px; cursor: pointer;">Dismiss</button>
`;
document.body.insertBefore(warning, document.body.firstChild);
// Event listeners
document.getElementById('view-details').addEventListener('click', (e) => {
e.preventDefault();
chrome.runtime.sendMessage({ action: 'openPopup' });
});
document.getElementById('dismiss-warning').addEventListener('click', () => {
warning.remove();
});
}
// Run analysis when page loads
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', analyzeCurrentPage);
} else {
analyzeCurrentPage();
}
// Re-analyze on navigation
let lastUrl = location.href;
new MutationObserver(() => {
const url = location.href;
if (url !== lastUrl) {
lastUrl = url;
analyzeCurrentPage();
}
}).observe(document, { subtree: true, childList: true });
})();
JS
# popup.html - Extension popup
cat > popup.html <<'HTML'
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body {
width: 400px;
padding: 20px;
font-family: Arial, sans-serif;
}
.risk-high { color: #d00; }
.risk-medium { color: #f80; }
.risk-low { color: #0a0; }
.feature-list { margin: 10px 0; }
.feature-item { padding: 5px; border-bottom: 1px solid #eee; }
</style>
</head>
<body>
<h2>🔐 AI Phishing Detector</h2>
<div id="status">Analyzing current page...</div>
<div id="results"></div>
<script src="popup.js"></script>
</body>
</html>
HTML
# popup.js - Popup script
cat > popup.js <<'JS'
// Popup script
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const currentTab = tabs[0];
chrome.runtime.sendMessage({
action: 'analyzePage',
url: currentTab.url,
pageData: {
url: currentTab.url,
title: currentTab.title
}
}, (response) => {
displayResults(response);
});
});
function displayResults(analysis) {
const statusDiv = document.getElementById('status');
const resultsDiv = document.getElementById('results');
if (!analysis || analysis.error) {
statusDiv.textContent = 'Error analyzing page';
return;
}
const riskClass = analysis.riskScore > 0.7 ? 'risk-high' :
analysis.riskScore > 0.4 ? 'risk-medium' : 'risk-low';
statusDiv.innerHTML = `
<h3 class="${riskClass}">
Risk Score: ${(analysis.riskScore * 100).toFixed(0)}%
</h3>
<p>Status: ${analysis.isSuspicious ? '⚠️ SUSPICIOUS' : '✅ SAFE'}</p>
`;
resultsDiv.innerHTML = `
<h4>Analysis Details:</h4>
<div class="feature-list">
${Object.entries(analysis.features || {}).map(([key, value]) =>
`<div class="feature-item"><strong>${key}:</strong> ${value}</div>`
).join('')}
</div>
<h4>Recommendations:</h4>
<ul>
${analysis.recommendations?.map(rec => `<li>${rec}</li>`).join('') || '<li>No specific recommendations</li>'}
</ul>
`;
}
JS
echo "Browser extension files created!"
echo "To install:"
echo "1. Open Chrome/Edge"
echo "2. Go to chrome://extensions/"
echo "3. Enable 'Developer mode'"
echo "4. Click 'Load unpacked'"
echo "5. Select the ai-phishing-detector-extension directory"
Project Features
✅ Real-time Detection - Analyzes pages as you browse
✅ Typography Analysis - Detects unusual fonts and layouts
✅ Phishing Pattern Detection - Identifies common phishing indicators
✅ URL Analysis - Checks for suspicious domains and TLDs
✅ SSL Verification - Validates SSL certificates
✅ Warning System - Visual warnings for suspicious sites
✅ Detailed Analysis - Popup with comprehensive security analysis
✅ Cross-browser Support - Works on Chrome, Firefox, Edge
Installation & Usage
-
Load Extension:
- Chrome:
chrome://extensions/→ Developer mode → Load unpacked - Firefox:
about:debugging→ This Firefox → Load Temporary Add-on
- Chrome:
-
Test Extension:
- Visit a suspicious website
- Extension will analyze and show warning if needed
- Click extension icon for detailed analysis
-
Customize:
- Adjust risk thresholds in
background.js - Add custom phishing domain lists
- Integrate with threat intelligence APIs
- Adjust risk thresholds in
FAQ
What are the most common web security threats in 2026?
Most common: AI-assisted attacks (300% increase), JavaScript supply chain threats, HTTP/3 vulnerabilities, CSRF attacks, and client-side injection. According to OWASP, 94% of web applications have vulnerabilities.
How do I defend against AI-assisted attacks?
Defend by: rate-limiting requests, using ML-based detection, monitoring for anomalies, and blocking automated patterns. AI attacks are fast and scalable—rate limiting is essential.
What’s the difference between SRI and CSP?
SRI: Subresource Integrity (validates script integrity with hashes). CSP: Content Security Policy (controls script sources). Use both: SRI for integrity, CSP for source control.
How do I prevent JavaScript supply chain attacks?
Prevent by: locking dependencies (package-lock.json), adding SRI to external scripts, using strict CSP, and monitoring for updates. Supply chain attacks exploit third-party code—validate everything.
Can traditional security stop modern web threats?
Partially, but modern threats require: AI detection, supply chain validation, HTTP/3 inspection, and rate limiting. Traditional security assumes known patterns—modern threats require adaptive defense.
What are the best practices for web security?
Best practices: lock dependencies, add SRI/CSP, enable strict auth, protect against CSRF, inspect HTTP/3, and rate-limit abuse. Defense in depth is essential—no single control prevents all threats.
Conclusion
Web security threats are evolving, with AI-assisted attacks increasing by 300% and 94% of applications having vulnerabilities. Security professionals must implement comprehensive defense: dependency locking, SRI/CSP, strict auth, and rate limiting.
Action Steps
- Lock dependencies - Use package-lock.json, audit regularly
- Add SRI/CSP - Validate script integrity and sources
- Enable strict auth - Require authentication and CSRF protection
- Inspect HTTP/3 - Secure QUIC with strong TLS
- Rate-limit abuse - Prevent AI-driven attacks
- Monitor continuously - Track for new threats
Future Trends
Looking ahead to 2026-2027, we expect to see:
- More AI attacks - Continued growth in AI-assisted threats
- Advanced supply chain - More sophisticated dependency attacks
- Better detection - Improved ML-based threat detection
- Regulatory requirements - Compliance mandates for web security
The web security threat landscape is evolving rapidly. Organizations that implement comprehensive defense now will be better positioned to prevent breaches.
→ Download our Web Security Checklist to secure your applications
→ Read our guide on Client-Side Security for comprehensive browser protection
→ Subscribe for weekly cybersecurity updates to stay informed about web threats
About the Author
CyberGuid Team
Cybersecurity Experts
10+ years of experience in web security, application security, and threat detection
Specializing in web application security, AI threat defense, and supply chain protection
Contributors to OWASP standards and web security best practices
Our team has helped hundreds of organizations defend against web security threats, reducing attacks by an average of 95%. We believe in practical security guidance that balances security with application functionality.