Awesome-omni-skill security-patterns
Zero-trust security patterns for frontend and backend
install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/security-patterns" ~/.claude/skills/diegosouzapw-awesome-omni-skill-security-patterns && rm -rf "$T"
manifest:
skills/development/security-patterns/SKILL.mdsource content
Security Patterns Skill
Enforce zero-trust security across frontend and backend.
When to Use
Automatically activate when:
- Implementing authentication/authorization
- Handling tokens or sessions
- Writing API endpoints
- Storing sensitive data
Zero Trust Principles
Never Trust, Always Verify, Least Privilege
- Every request is authenticated
- Every action is authorized
- Minimal permissions granted
- All data encrypted at rest and in transit
- Complete audit trail
Frontend Security (Angular)
Token Storage — Memory ONLY
// ✅ CORRECT - Store in memory @Injectable({ providedIn: 'root' }) export class AuthService { private accessToken = signal<string | null>(null); private refreshToken = signal<string | null>(null); setTokens(access: string, refresh: string) { this.accessToken.set(access); this.refreshToken.set(refresh); } clearTokens() { this.accessToken.set(null); this.refreshToken.set(null); } } // ❌ WRONG - Never use localStorage localStorage.setItem('token', token); // FORBIDDEN sessionStorage.setItem('token', token); // FORBIDDEN
XSS Prevention
// ✅ Use Angular's built-in sanitization import { DomSanitizer } from '@angular/platform-browser'; @Component({...}) class SafeComponent { private sanitizer = inject(DomSanitizer); // Only when absolutely necessary trustedHtml = this.sanitizer.bypassSecurityTrustHtml(userContent); } // ❌ WRONG - Never bypass without sanitization [innerHTML]="userContent" // DANGEROUS
Auto-Logout on Inactivity
@Injectable({ providedIn: 'root' }) export class InactivityService { private readonly TIMEOUT_MS = 15 * 60 * 1000; // 15 minutes private timeoutId?: number; resetTimer() { clearTimeout(this.timeoutId); this.timeoutId = window.setTimeout(() => this.logout(), this.TIMEOUT_MS); } private logout() { this.authService.clearTokens(); this.router.navigate(['/login']); } }
Clear PII on Logout
logout() { // Clear all sensitive data this.accessToken.set(null); this.refreshToken.set(null); this.userProfile.set(null); // Clear IndexedDB await this.indexedDb.clear(); // Clear service worker cache if ('serviceWorker' in navigator) { const caches = await window.caches.keys(); await Promise.all(caches.map(c => window.caches.delete(c))); } }
Backend Security (Spring Boot)
Method-Level Authorization
@RestController @RequestMapping("/api/v1/learners") @RequiredArgsConstructor public class LearnerController { @GetMapping @PreAuthorize("hasAnyRole('TEACHER', 'ADMIN')") public List<LearnerResponse> listLearners() { ... } @PostMapping @PreAuthorize("hasRole('ADMIN')") public LearnerResponse createLearner(@Valid @RequestBody request) { ... } @DeleteMapping("/{id}") @PreAuthorize("hasRole('SUPER_ADMIN')") public void deleteLearner(@PathVariable UUID id) { ... } }
PII Masking in Responses
public record LearnerResponse( UUID id, @JsonSerialize(using = MaskedStringSerializer.class) String lrn, // Returns: "****8901" String firstName, @JsonSerialize(using = MaskedStringSerializer.class) String birthDate // Returns: "****-**-15" ) {}
Audit Logging
@Aspect @Component public class AuditAspect { @Around("@annotation(Auditable)") public Object audit(ProceedingJoinPoint pjp) throws Throwable { AuditLog log = AuditLog.builder() .userId(SecurityContextHolder.getContext().getUserId()) .tenantId(TenantContext.getTenantId()) .action(pjp.getSignature().getName()) .timestamp(Instant.now()) .build(); try { Object result = pjp.proceed(); log.setStatus("SUCCESS"); return result; } catch (Exception e) { log.setStatus("FAILURE"); log.setError(e.getMessage()); throw e; } finally { auditRepository.save(log); } } }
Input Validation
public record CreateLearnerRequest( @NotBlank @Size(max = 100) @Pattern(regexp = "^[a-zA-Z\\s]+$", message = "Only letters allowed") String firstName, @NotNull @Pattern(regexp = "\\d{12}", message = "LRN must be 12 digits") String lrn, @NotNull @Past(message = "Birth date must be in the past") LocalDate birthDate ) {}
API Security
OAuth2 + PKCE Flow
1. Client generates code_verifier (random string) 2. Client creates code_challenge = SHA256(code_verifier) 3. Client redirects to /authorize?code_challenge=... 4. User authenticates 5. Server returns authorization_code 6. Client exchanges code + code_verifier for tokens 7. Server validates SHA256(code_verifier) == code_challenge
Rate Limiting
@Configuration public class RateLimitConfig { @Bean public RateLimiter rateLimiter() { return RateLimiter.of("api", RateLimiterConfig.custom() .limitForPeriod(100) // 100 requests .limitRefreshPeriod(Duration.ofMinutes(1)) .timeoutDuration(Duration.ofMillis(500)) .build()); } }
Data Encryption
At Rest (Database)
-- Encrypt sensitive columns CREATE TABLE learners ( id UUID PRIMARY KEY, lrn TEXT, -- Stored encrypted first_name TEXT, birth_date DATE ); -- Use pgcrypto for column encryption INSERT INTO learners (id, lrn, first_name, birth_date) VALUES ( gen_random_uuid(), pgp_sym_encrypt('123456789012', 'encryption-key'), 'Juan', '2010-01-15' );
In Transit
- TLS 1.3 for all connections
- mTLS between services
- Certificate pinning in mobile apps
Security Headers (CSP)
@Configuration public class SecurityHeadersConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) { return http .headers(headers -> headers .contentSecurityPolicy(csp -> csp .policyDirectives("default-src 'self'; script-src 'self'")) .frameOptions(frame -> frame.deny()) .xssProtection(xss -> xss.enable())) .build(); } }
Checklist
Frontend
- Tokens stored in memory only
- XSS prevention (Angular sanitization + CSP)
- 15-minute inactivity auto-logout
- Clear all PII on logout
- Certificate pinning (mobile)
Backend
-
on all controller methods@PreAuthorize - PII masking in responses
- Audit logging for all data access
- Input validation with Bean Validation
- Rate limiting per tenant
Infrastructure
- TLS 1.3 everywhere
- HSM for key management
- WAF + DDoS protection
- SIEM/SOAR integration