Conduct systematic threat modeling using STRIDE framework, attack trees, and security architecture analysis for CIA platform
This skill provides structured methodology for identifying, analyzing, and mitigating security threats in the CIA platform using industry-standard frameworks including STRIDE, PASTA, and attack tree analysis. It ensures proactive security design aligned with Hack23 ISMS requirements.
Apply this skill when:
Do NOT use for:
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Attacker impersonates politician to modify profile data
├─ Entry Point: User authentication endpoint (/login)
├─ Attack Vector: Credential stuffing with breached password databases
├─ Impact: Reputational damage, data integrity loss
└─ Mitigation:
├─ Implement rate limiting (5 attempts per 15 minutes)
├─ Enable 2FA for sensitive accounts
├─ Monitor for suspicious login patterns
└─ Enforce strong password policy (12+ chars, complexity)
Mitigation Checklist:
Code Pattern:
@Service
public class AuthenticationService {
private static final int MAX_LOGIN_ATTEMPTS = 5;
private static final Duration LOCKOUT_PERIOD = Duration.ofMinutes(15);
@Autowired
private LoginAttemptService loginAttemptService;
@Autowired
private UserDetailsService userDetailsService;
public AuthenticationToken authenticate(LoginRequest request) {
String username = request.getUsername();
// Check if account is locked due to failed attempts
if (loginAttemptService.isLocked(username)) {
throw new AccountLockedException(
"Account temporarily locked. Try again in " +
loginAttemptService.getTimeUntilUnlock(username) + " minutes"
);
}
try {
// Authenticate user
UserDetails user = userDetailsService.loadUserByUsername(username);
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
loginAttemptService.recordFailedAttempt(username);
throw new BadCredentialsException("Invalid credentials");
}
// Success - reset attempt counter
loginAttemptService.resetAttempts(username);
// Generate secure token
return tokenService.generateToken(user);
} catch (UsernameNotFoundException e) {
// Don't reveal if username exists
throw new BadCredentialsException("Invalid credentials");
}
}
}
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Attacker modifies politician absence rate to damage reputation
├─ Entry Point: REST API endpoint /api/politicians/{id}/data
├─ Attack Vector: SQL injection via unvalidated input parameters
├─ Impact: Data integrity compromise, false political analysis
└─ Mitigation:
├─ Use JPA parameterized queries exclusively
├─ Implement data integrity checks (checksums, timestamps)
├─ Enable database audit logging
└─ Apply digital signatures to critical data
Mitigation Checklist:
Code Pattern:
@Entity
@Table(name = "politician_voting_record")
@Audited // Hibernate Envers for audit trail
public class VotingRecord {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String politicianId;
@Column(nullable = false)
private String voteType;
@Column(nullable = false)
private LocalDateTime voteDate;
// Integrity protection - computed hash of critical fields
@Column(name = "data_hash")
private String dataHash;
@PrePersist
@PreUpdate
private void calculateHash() {
this.dataHash = DigestUtils.sha256Hex(
politicianId + voteType + voteDate.toString()
);
}
public boolean verifyIntegrity() {
String expectedHash = DigestUtils.sha256Hex(
politicianId + voteType + voteDate.toString()
);
return expectedHash.equals(this.dataHash);
}
}
@Repository
public interface VotingRecordRepository extends JpaRepository<VotingRecord, Long> {
// Safe: JPA query with named parameters
@Query("SELECT v FROM VotingRecord v WHERE v.politicianId = :politicianId " +
"AND v.voteDate BETWEEN :startDate AND :endDate")
List<VotingRecord> findByPoliticianAndDateRange(
@Param("politicianId") String politicianId,
@Param("startDate") LocalDateTime startDate,
@Param("endDate") LocalDateTime endDate
);
}
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Administrator denies modifying user permissions
├─ Entry Point: Admin panel /admin/users/{id}/permissions
├─ Attack Vector: No audit logging of administrative actions
├─ Impact: Accountability loss, inability to investigate incidents
└─ Mitigation:
├─ Implement comprehensive audit logging
├─ Log all authentication and authorization events
├─ Include timestamps, user identity, IP address, action details
└─ Store logs in tamper-proof storage (write-once)
Mitigation Checklist:
Code Pattern:
@Component
@Aspect
public class AuditLoggingAspect {
private static final Logger auditLog = LoggerFactory.getLogger("AUDIT");
@Autowired
private AuditLogRepository auditLogRepository;
@Around("@annotation(Audited)")
public Object logAuditEvent(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
String methodName = signature.getName();
String className = signature.getDeclaringTypeName();
// Capture context
String username = SecurityContextHolder.getContext()
.getAuthentication().getName();
String ipAddress = RequestContextHolder.currentRequestAttributes()
.getSessionId();
AuditLogEntry entry = new AuditLogEntry();
entry.setTimestamp(Instant.now());
entry.setUsername(username);
entry.setIpAddress(ipAddress);
entry.setAction(className + "." + methodName);
entry.setParameters(Arrays.toString(joinPoint.getArgs()));
try {
// Execute the method
Object result = joinPoint.proceed();
entry.setOutcome("SUCCESS");
entry.setResult(result != null ? result.toString() : "void");
return result;
} catch (Exception e) {
entry.setOutcome("FAILURE");
entry.setErrorMessage(e.getMessage());
throw e;
} finally {
// Always log, even on failure
auditLogRepository.save(entry);
auditLog.info("Audit: {}", entry.toJson());
}
}
}
@Entity
@Table(name = "audit_log")
public class AuditLogEntry {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false, updatable = false)
private Instant timestamp;
@Column(nullable = false, updatable = false)
private String username;
@Column(updatable = false)
private String ipAddress;
@Column(nullable = false, updatable = false)
private String action;
@Column(updatable = false, columnDefinition = "TEXT")
private String parameters;
@Column(nullable = false, updatable = false)
private String outcome;
// Immutable - prevent tampering
@PreUpdate
private void preventUpdate() {
throw new IllegalStateException("Audit log entries cannot be modified");
}
}
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Attacker accesses politician personal contact information
├─ Entry Point: Public API endpoint /api/politicians/{id}
├─ Attack Vector: Insufficient access control, over-fetching data
├─ Impact: GDPR violation, privacy breach
└─ Mitigation:
├─ Implement field-level access control
├─ Return only public data in API responses
├─ Redact or mask sensitive fields (phone, email)
└─ Log all access to PII for audit purposes
Mitigation Checklist:
Code Pattern:
@RestController
@RequestMapping("/api/politicians")
public class PoliticianController {
@GetMapping("/{id}")
public ResponseEntity<PoliticianDTO> getPolitician(
@PathVariable String id,
@AuthenticationPrincipal UserDetails currentUser) {
Politician politician = politicianService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Politician not found"));
// Apply field-level filtering based on user role
PoliticianDTO dto = mapToDTO(politician, currentUser);
// Log PII access for audit
auditLogger.logPIIAccess(currentUser.getUsername(), "Politician", id);
return ResponseEntity.ok(dto);
}
private PoliticianDTO mapToDTO(Politician politician, UserDetails user) {
PoliticianDTO dto = new PoliticianDTO();
// Always include public information
dto.setFirstName(politician.getFirstName());
dto.setLastName(politician.getLastName());
dto.setParty(politician.getParty());
dto.setDistrict(politician.getDistrict());
// Only include sensitive data for authorized users
if (hasRole(user, "ADMIN") || hasRole(user, "RESEARCHER")) {
// Redact instead of exposing full data
dto.setEmail(redactEmail(politician.getEmail()));
dto.setPhone(redactPhone(politician.getPhone()));
}
return dto;
}
private String redactEmail(String email) {
if (email == null) return null;
int atIndex = email.indexOf('@');
if (atIndex > 2) {
return email.substring(0, 2) + "***" + email.substring(atIndex);
}
return "***" + email.substring(atIndex);
}
}
@Configuration
public class SecurityHeadersConfig {
@Bean
public SecurityFilterChain securityHeaders(HttpSecurity http) throws Exception {
http.headers(headers -> headers
.contentSecurityPolicy("default-src 'self'; script-src 'self'; style-src 'self'")
.xssProtection()
.frameOptions().deny()
.httpStrictTransportSecurity()
.maxAgeInSeconds(31536000)
.includeSubDomains(true)
);
return http.build();
}
}
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Attacker overwhelms system with expensive political data queries
├─ Entry Point: Public search API /api/search?query=*
├─ Attack Vector: Recursive queries, unbounded result sets
├─ Impact: Service unavailability, degraded performance for legitimate users
└─ Mitigation:
├─ Implement rate limiting (100 requests/minute per IP)
├─ Query result pagination (max 100 results per page)
├─ Timeout for long-running queries (30 seconds)
└─ Resource quotas per user tier
Mitigation Checklist:
Code Pattern:
@Configuration
public class RateLimitingConfig {
@Bean
public RateLimiter apiRateLimiter() {
return RateLimiter.create(100.0); // 100 requests per second
}
}
@Component
public class RateLimitingInterceptor implements HandlerInterceptor {
@Autowired
private RateLimiter rateLimiter;
private final LoadingCache<String, AtomicInteger> requestCounts = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<String, AtomicInteger>() {
public AtomicInteger load(String key) {
return new AtomicInteger(0);
}
});
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
String clientIp = getClientIP(request);
// Apply rate limit
if (!rateLimiter.tryAcquire(1, TimeUnit.SECONDS)) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("Rate limit exceeded. Try again later.");
return false;
}
// Check per-IP limit
int requestCount = requestCounts.get(clientIp).incrementAndGet();
if (requestCount > 1000) {
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.getWriter().write("IP-based rate limit exceeded.");
return false;
}
return true;
}
}
@Repository
public interface PoliticianSearchRepository extends JpaRepository<Politician, Long> {
// Pageable prevents unbounded result sets
@Query("SELECT p FROM Politician p WHERE " +
"LOWER(p.firstName) LIKE LOWER(CONCAT('%', :searchTerm, '%')) OR " +
"LOWER(p.lastName) LIKE LOWER(CONCAT('%', :searchTerm, '%'))")
@QueryHints(@QueryHint(name = "org.hibernate.timeout", value = "30")) // 30 second timeout
Page<Politician> search(@Param("searchTerm") String searchTerm, Pageable pageable);
}
@RestController
public class SearchController {
private static final int MAX_PAGE_SIZE = 100;
@GetMapping("/api/search")
public Page<PoliticianDTO> search(
@RequestParam String query,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
// Enforce maximum page size
if (size > MAX_PAGE_SIZE) {
size = MAX_PAGE_SIZE;
}
Pageable pageable = PageRequest.of(page, size);
return searchService.search(query, pageable);
}
}
Threats to Consider:
CIA Platform Attack Scenarios:
Threat: Regular user gains administrative access to modify site configuration
├─ Entry Point: Admin API endpoint /api/admin/settings
├─ Attack Vector: Missing @PreAuthorize annotation on controller method
├─ Impact: Unauthorized configuration changes, system compromise
└─ Mitigation:
├─ Enforce role-based access control on all endpoints
├─ Use Spring Security annotations (@PreAuthorize, @Secured)
├─ Implement defense in depth (controller + service layer checks)
└─ Regular access control audits
Mitigation Checklist:
Code Pattern:
@RestController
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ADMIN')") // Controller-level authorization
public class AdminController {
@PostMapping("/settings")
@PreAuthorize("hasAuthority('MODIFY_SETTINGS')") // Method-level check
public ResponseEntity<SystemSettings> updateSettings(
@RequestBody @Valid SystemSettingsRequest request,
@AuthenticationPrincipal UserDetails currentUser) {
// Log privileged action
auditLogger.logPrivilegedAction(
currentUser.getUsername(),
"UPDATE_SYSTEM_SETTINGS",
request.toString()
);
// Service layer also enforces authorization
SystemSettings updated = adminService.updateSettings(request);
return ResponseEntity.ok(updated);
}
}
@Service
public class AdminService {
@PreAuthorize("hasRole('ADMIN')")
public SystemSettings updateSettings(SystemSettingsRequest request) {
// Verify authorization again at service layer (defense in depth)
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!auth.getAuthorities().stream()
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
throw new AccessDeniedException("Admin role required");
}
// Perform update
SystemSettings settings = settingsRepository.findCurrent();
settings.updateFrom(request);
return settingsRepository.save(settings);
}
}
// Global method security enabled
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler =
new DefaultMethodSecurityExpressionHandler();
handler.setPermissionEvaluator(new CustomPermissionEvaluator());
return handler;
}
}
ROOT: Compromise Politician Voting Record Data
├─ AND: Gain Write Access
│ ├─ OR: Exploit Authentication
│ │ ├─ Brute force credentials [Mitigated: Rate limiting]
│ │ ├─ Credential stuffing [Mitigated: 2FA]
│ │ └─ Session hijacking [Mitigated: Secure cookies]
│ └─ OR: Exploit Authorization
│ ├─ Privilege escalation [Mitigated: RBAC]
│ └─ IDOR vulnerability [Mitigated: Ownership checks]
└─ AND: Modify Data
├─ OR: Direct Database Access
│ ├─ SQL injection [Mitigated: Parameterized queries]
│ └─ Database credential theft [Mitigated: Secrets management]
└─ OR: API Manipulation
├─ Parameter tampering [Mitigated: Input validation]
└─ CSRF attack [Mitigated: CSRF tokens]
Internet Users (Untrusted)
│
├─→ Application Firewall / Rate Limiter
│ │
│ ├─→ Spring Boot Application (DMZ)
│ │ │
│ │ ├─→ Authentication Filter
│ │ ├─→ Authorization Filter
│ │ └─→ CSRF Protection
│ │
│ └─→ Internal Network (Trusted)
│ │
│ ├─→ PostgreSQL Database (Encrypted)
│ └─→ Redis Session Store (Encrypted)
│
└─→ External APIs (Semi-Trusted)
├─→ Riksdagen API (HTTPS only)
├─→ World Bank API (HTTPS only)
└─→ Election Authority API (HTTPS only)
Level 0 DFD - Context Diagram:
[Public Users] → (CIA Web App) → [Database]
[Admin Users] → (CIA Web App) → [External APIs]
Security Analysis:
# Threat Model: [Feature Name]
## Overview
- **Component**: [Component being analyzed]
- **Last Updated**: [Date]
- **Reviewer**: [Name]
- **Risk Rating**: [Critical/High/Medium/Low]
## Assets
1. Politician personal information (GDPR protected)
2. Voting records (integrity critical)
3. User credentials (confidentiality critical)
4. API keys for external services
## Trust Boundaries
- Internet → Application Server
- Application Server → Database
- Application Server → External APIs
## STRIDE Analysis
### Spoofing
- **Threat**: [Description]
- **Likelihood**: [High/Medium/Low]
- **Impact**: [High/Medium/Low]
- **Risk**: [Critical/High/Medium/Low]
- **Mitigation**: [Controls in place]
- **Residual Risk**: [Accepted/Needs treatment]
[Repeat for T, R, I, D, E]
## Attack Trees
[Attach attack tree diagrams]
## Security Requirements
1. [Requirement 1]
2. [Requirement 2]
## Security Test Cases
1. Test authentication bypass attempts
2. Test authorization escalation
3. Test input validation
## ISMS Compliance
- ISO 27001:2022 A.5.15 (Access Control)
- NIST CSF PR.AC-4 (Access Permissions)
- CIS Control 6.1 (Access Control Management)
## Sign-off
- **Security Team**: [Approved/Rejected]
- **Development Team**: [Approved/Rejected]
- **Date**: [Date]
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer