Files
gh-ehssanatassi-angular-mar…/commands/audit-security.md
2025-11-29 18:25:02 +08:00

10 KiB

Audit Security Command

Comprehensive security audit for Angular applications following OWASP guidelines.

Usage

/angular-security:audit-security

Audit Categories

1. Dependency Vulnerabilities

# Check for vulnerable packages
npm audit

# Fix automatically
npm audit fix

# View detailed report
npm audit --json

# Check specific severity
npm audit --audit-level=high

2. XSS Vulnerabilities

// Scan for dangerous patterns:
// - innerHTML with user data
// - bypassSecurityTrust* methods
// - [style], [href], [src] with user input
// - Dynamic script/style injection

// ❌ Found issues:
[innerHTML]="userContent"          // XSS risk
[src]="untrustedUrl"               // URL injection
[style]="userStyle"                // Style injection
bypassSecurityTrustHtml(userHtml)  // Bypassing protection

3. Authentication & Authorization

// ✅ Secure auth implementation
export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = inject(AuthService).getToken();
  
  if (token) {
    req = req.clone({
      setHeaders: {
        'Authorization': `Bearer ${token}`,
        'X-Requested-With': 'XMLHttpRequest' // CSRF protection
      }
    });
  }
  
  return next(req).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status === 401) {
        inject(Router).navigate(['/login']);
      }
      return throwError(() => error);
    })
  );
};

// ✅ Secure route guard
export const authGuard: CanActivateFn = (route, state) => {
  const authService = inject(AuthService);
  const router = inject(Router);
  
  if (authService.isAuthenticated()) {
    // Check role-based access
    const requiredRole = route.data['role'];
    if (requiredRole && !authService.hasRole(requiredRole)) {
      return router.parseUrl('/unauthorized');
    }
    return true;
  }
  
  return router.parseUrl('/login');
};

4. CSRF Protection

// ✅ CSRF token implementation
export class CsrfInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // Get CSRF token from cookie
    const csrfToken = this.getCookie('XSRF-TOKEN');
    
    // Add to header for state-changing requests
    if (req.method !== 'GET' && req.method !== 'HEAD') {
      req = req.clone({
        setHeaders: {
          'X-XSRF-TOKEN': csrfToken
        }
      });
    }
    
    return next.handle(req);
  }
  
  private getCookie(name: string): string {
    const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
    return match ? match[2] : '';
  }
}

5. Token Storage

// ❌ INSECURE: localStorage
localStorage.setItem('token', jwt);  // Vulnerable to XSS

// ✅ SECURE: HttpOnly cookie (server-side)
// Set-Cookie: token=xxx; HttpOnly; Secure; SameSite=Strict

// ✅ ALTERNATIVE: Memory + refresh token
@Injectable({ providedIn: 'root' })
export class TokenService {
  private accessToken: string | null = null;
  
  setToken(token: string) {
    this.accessToken = token;
    // Refresh token in HttpOnly cookie
  }
  
  getToken(): string | null {
    return this.accessToken;
  }
  
  clearToken() {
    this.accessToken = null;
  }
}

6. Input Validation

// ✅ Comprehensive validation
export class SecureFormComponent {
  form = this.fb.group({
    username: ['', [
      Validators.required,
      Validators.minLength(3),
      Validators.maxLength(20),
      Validators.pattern(/^[a-zA-Z0-9_]+$/)
    ]],
    email: ['', [
      Validators.required,
      Validators.email
    ]],
    age: ['', [
      Validators.required,
      Validators.min(18),
      Validators.max(120)
    ]],
    website: ['', [
      this.urlValidator()
    ]]
  });
  
  private urlValidator(): ValidatorFn {
    return (control: AbstractControl): ValidationErrors | null => {
      if (!control.value) return null;
      
      try {
        const url = new URL(control.value);
        // Only allow https
        if (url.protocol !== 'https:') {
          return { invalidProtocol: true };
        }
        return null;
      } catch {
        return { invalidUrl: true };
      }
    };
  }
}

7. Secure HTTP Communication

// ✅ HTTPS enforcement
export class AppComponent implements OnInit {
  ngOnInit() {
    // Redirect HTTP to HTTPS
    if (location.protocol !== 'https:' && 
        !location.hostname.includes('localhost')) {
      location.replace(`https:${location.href.substring(location.protocol.length)}`);
    }
  }
}

// ✅ Security headers (server-side config)
// Strict-Transport-Security: max-age=31536000; includeSubDomains
// X-Content-Type-Options: nosniff
// X-Frame-Options: DENY
// X-XSS-Protection: 1; mode=block
// Referrer-Policy: strict-origin-when-cross-origin

8. Content Security Policy

<!-- Strict CSP -->
<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self';
  style-src 'self';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
">

9. Rate Limiting

// ✅ Client-side rate limiting
@Injectable({ providedIn: 'root' })
export class RateLimitService {
  private requests = new Map<string, number[]>();
  private readonly WINDOW_MS = 60000; // 1 minute
  private readonly MAX_REQUESTS = 10;
  
  canMakeRequest(key: string): boolean {
    const now = Date.now();
    const timestamps = this.requests.get(key) || [];
    
    // Remove old timestamps
    const validTimestamps = timestamps.filter(ts => 
      now - ts < this.WINDOW_MS
    );
    
    if (validTimestamps.length >= this.MAX_REQUESTS) {
      return false;
    }
    
    validTimestamps.push(now);
    this.requests.set(key, validTimestamps);
    return true;
  }
}

10. Logging & Monitoring

// ✅ Security event logging
@Injectable({ providedIn: 'root' })
export class SecurityLogger {
  logSecurityEvent(event: SecurityEvent) {
    const log = {
      timestamp: new Date().toISOString(),
      event: event.type,
      severity: event.severity,
      user: this.authService.getCurrentUser()?.id,
      details: event.details,
      userAgent: navigator.userAgent,
      ip: this.getClientIp()
    };
    
    // Send to security monitoring service
    this.http.post('/api/security/log', log).subscribe();
  }
  
  logFailedLogin(username: string) {
    this.logSecurityEvent({
      type: 'FAILED_LOGIN',
      severity: 'HIGH',
      details: { username }
    });
  }
  
  logXSSAttempt(payload: string) {
    this.logSecurityEvent({
      type: 'XSS_ATTEMPT',
      severity: 'CRITICAL',
      details: { payload }
    });
  }
}

Audit Report Example

🔒 Security Audit Report
Generated: 2025-10-21 15:30:00

┌─────────────────────────────────────────┐
│ OWASP Top 10 Compliance                 │
├─────────────────────────────────────────┤
│ A01: Broken Access Control     ✅ PASS  │
│ A02: Cryptographic Failures    ✅ PASS  │
│ A03: Injection                 ⚠️  WARN │
│ A04: Insecure Design           ✅ PASS  │
│ A05: Security Misconfiguration ❌ FAIL  │
│ A06: Vulnerable Components     ⚠️  WARN │
│ A07: Auth Failures             ✅ PASS  │
│ A08: Software/Data Integrity   ✅ PASS  │
│ A09: Logging Failures          ⚠️  WARN │
│ A10: Server-Side Forgery       ✅ PASS  │
└─────────────────────────────────────────┘

📊 Severity Breakdown:
┌──────────┬───────┬──────────────────┐
│ Severity │ Count │ Issues           │
├──────────┼───────┼──────────────────┤
│ 🔴 CRITICAL │ 0  │                  │
│ 🔴 HIGH     │ 2  │ XSS, CSP missing │
│ 🟡 MEDIUM   │ 5  │ Various          │
│ 🟢 LOW      │ 3  │ Improvements     │
└──────────┴───────┴──────────────────┘

🔴 HIGH Priority Issues:

1. XSS Vulnerability in UserProfileComponent
   File: user-profile.component.ts:45
   Code: [innerHTML]="userBio"
   Fix: Use DomSanitizer or remove innerHTML
   
2. Missing Content-Security-Policy
   File: index.html
   Impact: No XSS protection layer
   Fix: Add CSP meta tag

🟡 MEDIUM Priority Issues:

3. Hardcoded API credentials
   File: environment.ts:8
   Fix: Use environment variables
   
4. No rate limiting on login
   File: auth.service.ts:23
   Fix: Implement rate limiting

5. JWT in localStorage
   File: token.service.ts:12
   Fix: Use HttpOnly cookies

🟢 LOW Priority Issues:

6. Missing security headers
   Fix: Configure server headers
   
7. No input sanitization
   Fix: Add validation to forms

8. Console.log in production
   Fix: Remove debug logs

📋 npm audit Results:
┌──────────┬───────┐
│ Critical │ 0     │
│ High     │ 1     │
│ Moderate │ 3     │
│ Low      │ 8     │
└──────────┴───────┘

Vulnerable packages:
- lodash@4.17.15 (HIGH) → Update to 4.17.21
- axios@0.21.1 (MODERATE) → Update to 1.6.0

✅ Secure Practices Found:
- HTTPS enforced
- Route guards implemented
- Form validation present
- CSRF tokens in use
- Password hashing (bcrypt)

🎯 Security Score: 7.2/10

📈 After Fixes: 9.5/10

⏱️ Estimated Fix Time: 4-6 hours

🔧 Action Plan:
1. Fix XSS vulnerability (30 min)
2. Add CSP headers (15 min)
3. Move JWT to HttpOnly cookie (1 hour)
4. Update vulnerable dependencies (30 min)
5. Add rate limiting (1 hour)
6. Implement security logging (1 hour)

Continuous Security

# .github/workflows/security.yml
name: Security Audit

on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: npm audit
        run: npm audit --audit-level=moderate
      
      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main
      
      - name: Snyk Security Scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

Audit regularly, fix proactively! 🛡️