Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Extract and formalize security requirements from specs and architecture docs into actionable controls.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: security-requirement-extraction3description: Derive security requirements from threat models and business context. Use when translating threats into actionable requirements, creating security user stories, or building security test cases.4---56# Security Requirement Extraction78Transform threat analysis into actionable security requirements.910## When to Use This Skill1112- Converting threat models to requirements13- Writing security user stories14- Creating security test cases15- Building security acceptance criteria16- Compliance requirement mapping17- Security architecture documentation1819## Core Concepts2021### 1. Requirement Categories2223```24Business Requirements → Security Requirements → Technical Controls25↓ ↓ ↓26"Protect customer "Encrypt PII at rest" "AES-256 encryption27data" with KMS key rotation"28```2930### 2. Security Requirement Types3132| Type | Focus | Example |33| ------------------ | ----------------------- | ------------------------------------- |34| **Functional** | What system must do | "System must authenticate users" |35| **Non-functional** | How system must perform | "Authentication must complete in <2s" |36| **Constraint** | Limitations imposed | "Must use approved crypto libraries" |3738### 3. Requirement Attributes3940| Attribute | Description |41| ---------------- | --------------------------- |42| **Traceability** | Links to threats/compliance |43| **Testability** | Can be verified |44| **Priority** | Business importance |45| **Risk Level** | Impact if not met |4647## Templates4849### Template 1: Security Requirement Model5051```python52from dataclasses import dataclass, field53from enum import Enum54from typing import List, Dict, Optional, Set55from datetime import datetime5657class RequirementType(Enum):58FUNCTIONAL = "functional"59NON_FUNCTIONAL = "non_functional"60CONSTRAINT = "constraint"616263class Priority(Enum):64CRITICAL = 165HIGH = 266MEDIUM = 367LOW = 4686970class SecurityDomain(Enum):71AUTHENTICATION = "authentication"72AUTHORIZATION = "authorization"73DATA_PROTECTION = "data_protection"74AUDIT_LOGGING = "audit_logging"75INPUT_VALIDATION = "input_validation"76ERROR_HANDLING = "error_handling"77SESSION_MANAGEMENT = "session_management"78CRYPTOGRAPHY = "cryptography"79NETWORK_SECURITY = "network_security"80AVAILABILITY = "availability"818283class ComplianceFramework(Enum):84PCI_DSS = "pci_dss"85HIPAA = "hipaa"86GDPR = "gdpr"87SOC2 = "soc2"88NIST_CSF = "nist_csf"89ISO_27001 = "iso_27001"90OWASP = "owasp"919293@dataclass94class SecurityRequirement:95id: str96title: str97description: str98req_type: RequirementType99domain: SecurityDomain100priority: Priority101rationale: str = ""102acceptance_criteria: List[str] = field(default_factory=list)103test_cases: List[str] = field(default_factory=list)104threat_refs: List[str] = field(default_factory=list)105compliance_refs: List[str] = field(default_factory=list)106dependencies: List[str] = field(default_factory=list)107status: str = "draft"108owner: str = ""109created_date: datetime = field(default_factory=datetime.now)110111def to_user_story(self) -> str:112"""Convert to user story format."""113return f"""114**{self.id}: {self.title}**115116As a security-conscious system,117I need to {self.description.lower()},118So that {self.rationale.lower()}.119120**Acceptance Criteria:**121{chr(10).join(f'- [ ] {ac}' for ac in self.acceptance_criteria)}122123**Priority:** {self.priority.name}124**Domain:** {self.domain.value}125**Threat References:** {', '.join(self.threat_refs)}126"""127128def to_test_spec(self) -> str:129"""Convert to test specification."""130return f"""131## Test Specification: {self.id}132133### Requirement134{self.description}135136### Test Cases137{chr(10).join(f'{i+1}. {tc}' for i, tc in enumerate(self.test_cases))}138139### Acceptance Criteria Verification140{chr(10).join(f'- {ac}' for ac in self.acceptance_criteria)}141"""142143144@dataclass145class RequirementSet:146name: str147version: str148requirements: List[SecurityRequirement] = field(default_factory=list)149150def add(self, req: SecurityRequirement) -> None:151self.requirements.append(req)152153def get_by_domain(self, domain: SecurityDomain) -> List[SecurityRequirement]:154return [r for r in self.requirements if r.domain == domain]155156def get_by_priority(self, priority: Priority) -> List[SecurityRequirement]:157return [r for r in self.requirements if r.priority == priority]158159def get_by_threat(self, threat_id: str) -> List[SecurityRequirement]:160return [r for r in self.requirements if threat_id in r.threat_refs]161162def get_critical_requirements(self) -> List[SecurityRequirement]:163return [r for r in self.requirements if r.priority == Priority.CRITICAL]164165def export_markdown(self) -> str:166"""Export all requirements as markdown."""167lines = [f"# Security Requirements: {self.name}\n"]168lines.append(f"Version: {self.version}\n")169170for domain in SecurityDomain:171domain_reqs = self.get_by_domain(domain)172if domain_reqs:173lines.append(f"\n## {domain.value.replace('_', ' ').title()}\n")174for req in domain_reqs:175lines.append(req.to_user_story())176177return "\n".join(lines)178179def traceability_matrix(self) -> Dict[str, List[str]]:180"""Generate threat-to-requirement traceability."""181matrix = {}182for req in self.requirements:183for threat_id in req.threat_refs:184if threat_id not in matrix:185matrix[threat_id] = []186matrix[threat_id].append(req.id)187return matrix188```189190### Template 2: Threat-to-Requirement Extractor191192```python193from dataclasses import dataclass194from typing import List, Dict, Tuple195196@dataclass197class ThreatInput:198id: str199category: str # STRIDE category200title: str201description: str202target: str203impact: str204likelihood: str205206207class RequirementExtractor:208"""Extract security requirements from threats."""209210# Mapping of STRIDE categories to security domains and requirement patterns211STRIDE_MAPPINGS = {212"SPOOFING": {213"domains": [SecurityDomain.AUTHENTICATION, SecurityDomain.SESSION_MANAGEMENT],214"patterns": [215("Implement strong authentication for {target}",216"Ensure {target} authenticates all users before granting access"),217("Validate identity tokens for {target}",218"All authentication tokens must be cryptographically verified"),219("Implement session management for {target}",220"Sessions must be securely managed with proper expiration"),221]222},223"TAMPERING": {224"domains": [SecurityDomain.INPUT_VALIDATION, SecurityDomain.DATA_PROTECTION],225"patterns": [226("Validate all input to {target}",227"All input must be validated against expected formats"),228("Implement integrity checks for {target}",229"Data integrity must be verified using cryptographic signatures"),230("Protect {target} from modification",231"Implement controls to prevent unauthorized data modification"),232]233},234"REPUDIATION": {235"domains": [SecurityDomain.AUDIT_LOGGING],236"patterns": [237("Log all security events for {target}",238"Security-relevant events must be logged for audit purposes"),239("Implement non-repudiation for {target}",240"Critical actions must have cryptographic proof of origin"),241("Protect audit logs for {target}",242"Audit logs must be tamper-evident and protected"),243]244},245"INFORMATION_DISCLOSURE": {246"domains": [SecurityDomain.DATA_PROTECTION, SecurityDomain.CRYPTOGRAPHY],247"patterns": [248("Encrypt sensitive data in {target}",249"Sensitive data must be encrypted at rest and in transit"),250("Implement access controls for {target}",251"Data access must be restricted based on need-to-know"),252("Prevent information leakage from {target}",253"Error messages and logs must not expose sensitive information"),254]255},256"DENIAL_OF_SERVICE": {257"domains": [SecurityDomain.AVAILABILITY, SecurityDomain.INPUT_VALIDATION],258"patterns": [259("Implement rate limiting for {target}",260"Requests must be rate-limited to prevent resource exhaustion"),261("Ensure availability of {target}",262"System must remain available under high load conditions"),263("Implement resource quotas for {target}",264"Resource consumption must be bounded and monitored"),265]266},267"ELEVATION_OF_PRIVILEGE": {268"domains": [SecurityDomain.AUTHORIZATION],269"patterns": [270("Enforce authorization for {target}",271"All actions must be authorized based on user permissions"),272("Implement least privilege for {target}",273"Users must only have minimum necessary permissions"),274("Validate permissions for {target}",275"Permission checks must be performed server-side"),276]277},278}279280def extract_requirements(281self,282threats: List[ThreatInput],283project_name: str284) -> RequirementSet:285"""Extract security requirements from threats."""286req_set = RequirementSet(287name=f"{project_name} Security Requirements",288version="1.0"289)290291req_counter = 1292for threat in threats:293reqs = self._threat_to_requirements(threat, req_counter)294for req in reqs:295req_set.add(req)296req_counter += len(reqs)297298return req_set299300def _threat_to_requirements(301self,302threat: ThreatInput,303start_id: int304) -> List[SecurityRequirement]:305"""Convert a single threat to requirements."""306requirements = []307mapping = self.STRIDE_MAPPINGS.get(threat.category, {})308domains = mapping.get("domains", [])309patterns = mapping.get("patterns", [])310311priority = self._calculate_priority(threat.impact, threat.likelihood)312313for i, (title_pattern, desc_pattern) in enumerate(patterns):314req = SecurityRequirement(315id=f"SR-{start_id + i:03d}",316title=title_pattern.format(target=threat.target),317description=desc_pattern.format(target=threat.target),318req_type=RequirementType.FUNCTIONAL,319domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,320priority=priority,321rationale=f"Mitigates threat: {threat.title}",322threat_refs=[threat.id],323acceptance_criteria=self._generate_acceptance_criteria(324threat.category, threat.target325),326test_cases=self._generate_test_cases(327threat.category, threat.target328)329)330requirements.append(req)331332return requirements333334def _calculate_priority(self, impact: str, likelihood: str) -> Priority:335"""Calculate requirement priority from threat attributes."""336score_map = {"LOW": 1, "MEDIUM": 2, "HIGH": 3, "CRITICAL": 4}337impact_score = score_map.get(impact.upper(), 2)338likelihood_score = score_map.get(likelihood.upper(), 2)339340combined = impact_score * likelihood_score341342if combined >= 12:343return Priority.CRITICAL344elif combined >= 6:345return Priority.HIGH346elif combined >= 3:347return Priority.MEDIUM348return Priority.LOW349350def _generate_acceptance_criteria(351self,352category: str,353target: str354) -> List[str]:355"""Generate acceptance criteria for requirement."""356criteria_templates = {357"SPOOFING": [358f"Users must authenticate before accessing {target}",359"Authentication failures are logged and monitored",360"Multi-factor authentication is available for sensitive operations",361],362"TAMPERING": [363f"All input to {target} is validated",364"Data integrity is verified before processing",365"Modification attempts trigger alerts",366],367"REPUDIATION": [368f"All actions on {target} are logged with user identity",369"Logs cannot be modified by regular users",370"Log retention meets compliance requirements",371],372"INFORMATION_DISCLOSURE": [373f"Sensitive data in {target} is encrypted",374"Access to sensitive data is logged",375"Error messages do not reveal sensitive information",376],377"DENIAL_OF_SERVICE": [378f"Rate limiting is enforced on {target}",379"System degrades gracefully under load",380"Resource exhaustion triggers alerts",381],382"ELEVATION_OF_PRIVILEGE": [383f"Authorization is checked for all {target} operations",384"Users cannot access resources beyond their permissions",385"Privilege changes are logged and monitored",386],387}388return criteria_templates.get(category, [])389390def _generate_test_cases(391self,392category: str,393target: str394) -> List[str]:395"""Generate test cases for requirement."""396test_templates = {397"SPOOFING": [398f"Test: Unauthenticated access to {target} is denied",399"Test: Invalid credentials are rejected",400"Test: Session tokens cannot be forged",401],402"TAMPERING": [403f"Test: Invalid input to {target} is rejected",404"Test: Tampered data is detected and rejected",405"Test: SQL injection attempts are blocked",406],407"REPUDIATION": [408"Test: Security events are logged",409"Test: Logs include sufficient detail for forensics",410"Test: Log integrity is protected",411],412"INFORMATION_DISCLOSURE": [413f"Test: {target} data is encrypted in transit",414f"Test: {target} data is encrypted at rest",415"Test: Error messages are sanitized",416],417"DENIAL_OF_SERVICE": [418f"Test: Rate limiting on {target} works correctly",419"Test: System handles burst traffic gracefully",420"Test: Resource limits are enforced",421],422"ELEVATION_OF_PRIVILEGE": [423f"Test: Unauthorized access to {target} is denied",424"Test: Privilege escalation attempts are blocked",425"Test: IDOR vulnerabilities are not present",426],427}428return test_templates.get(category, [])429```430431### Template 3: Compliance Mapping432433```python434from typing import Dict, List, Set435436class ComplianceMapper:437"""Map security requirements to compliance frameworks."""438439FRAMEWORK_CONTROLS = {440ComplianceFramework.PCI_DSS: {441SecurityDomain.AUTHENTICATION: ["8.1", "8.2", "8.3"],442SecurityDomain.AUTHORIZATION: ["7.1", "7.2"],443SecurityDomain.DATA_PROTECTION: ["3.4", "3.5", "4.1"],444SecurityDomain.AUDIT_LOGGING: ["10.1", "10.2", "10.3"],445SecurityDomain.NETWORK_SECURITY: ["1.1", "1.2", "1.3"],446SecurityDomain.CRYPTOGRAPHY: ["3.5", "3.6", "4.1"],447},448ComplianceFramework.HIPAA: {449SecurityDomain.AUTHENTICATION: ["164.312(d)"],450SecurityDomain.AUTHORIZATION: ["164.312(a)(1)"],451SecurityDomain.DATA_PROTECTION: ["164.312(a)(2)(iv)", "164.312(e)(2)(ii)"],452SecurityDomain.AUDIT_LOGGING: ["164.312(b)"],453},454ComplianceFramework.GDPR: {455SecurityDomain.DATA_PROTECTION: ["Art. 32", "Art. 25"],456SecurityDomain.AUDIT_LOGGING: ["Art. 30"],457SecurityDomain.AUTHORIZATION: ["Art. 25"],458},459ComplianceFramework.OWASP: {460SecurityDomain.AUTHENTICATION: ["V2.1", "V2.2", "V2.3"],461SecurityDomain.SESSION_MANAGEMENT: ["V3.1", "V3.2", "V3.3"],462SecurityDomain.INPUT_VALIDATION: ["V5.1", "V5.2", "V5.3"],463SecurityDomain.CRYPTOGRAPHY: ["V6.1", "V6.2"],464SecurityDomain.ERROR_HANDLING: ["V7.1", "V7.2"],465SecurityDomain.DATA_PROTECTION: ["V8.1", "V8.2", "V8.3"],466SecurityDomain.AUDIT_LOGGING: ["V7.1", "V7.2"],467},468}469470def map_requirement_to_compliance(471self,472requirement: SecurityRequirement,473frameworks: List[ComplianceFramework]474) -> Dict[str, List[str]]:475"""Map a requirement to compliance controls."""476mapping = {}477for framework in frameworks:478controls = self.FRAMEWORK_CONTROLS.get(framework, {})479domain_controls = controls.get(requirement.domain, [])480if domain_controls:481mapping[framework.value] = domain_controls482return mapping483484def get_requirements_for_control(485self,486requirement_set: RequirementSet,487framework: ComplianceFramework,488control_id: str489) -> List[SecurityRequirement]:490"""Find requirements that satisfy a compliance control."""491matching = []492framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})493494for domain, controls in framework_controls.items():495if control_id in controls:496matching.extend(requirement_set.get_by_domain(domain))497498return matching499500def generate_compliance_matrix(501self,502requirement_set: RequirementSet,503frameworks: List[ComplianceFramework]504) -> Dict[str, Dict[str, List[str]]]:505"""Generate compliance traceability matrix."""506matrix = {}507508for framework in frameworks:509matrix[framework.value] = {}510framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})511512for domain, controls in framework_controls.items():513for control in controls:514reqs = self.get_requirements_for_control(515requirement_set, framework, control516)517if reqs:518matrix[framework.value][control] = [r.id for r in reqs]519520return matrix521522def gap_analysis(523self,524requirement_set: RequirementSet,525framework: ComplianceFramework526) -> Dict[str, List[str]]:527"""Identify compliance gaps."""528gaps = {"missing_controls": [], "weak_coverage": []}529framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})530531for domain, controls in framework_controls.items():532domain_reqs = requirement_set.get_by_domain(domain)533for control in controls:534matching = self.get_requirements_for_control(535requirement_set, framework, control536)537if not matching:538gaps["missing_controls"].append(f"{framework.value}:{control}")539elif len(matching) < 2:540gaps["weak_coverage"].append(f"{framework.value}:{control}")541542return gaps543```544545### Template 4: Security User Story Generator546547```python548class SecurityUserStoryGenerator:549"""Generate security-focused user stories."""550551STORY_TEMPLATES = {552SecurityDomain.AUTHENTICATION: {553"as_a": "security-conscious user",554"so_that": "my identity is protected from impersonation",555},556SecurityDomain.AUTHORIZATION: {557"as_a": "system administrator",558"so_that": "users can only access resources appropriate to their role",559},560SecurityDomain.DATA_PROTECTION: {561"as_a": "data owner",562"so_that": "my sensitive information remains confidential",563},564SecurityDomain.AUDIT_LOGGING: {565"as_a": "security analyst",566"so_that": "I can investigate security incidents",567},568SecurityDomain.INPUT_VALIDATION: {569"as_a": "application developer",570"so_that": "the system is protected from malicious input",571},572}573574def generate_story(self, requirement: SecurityRequirement) -> str:575"""Generate a user story from requirement."""576template = self.STORY_TEMPLATES.get(577requirement.domain,578{"as_a": "user", "so_that": "the system is secure"}579)580581story = f"""582## {requirement.id}: {requirement.title}583584**User Story:**585As a {template['as_a']},586I want the system to {requirement.description.lower()},587So that {template['so_that']}.588589**Priority:** {requirement.priority.name}590**Type:** {requirement.req_type.value}591**Domain:** {requirement.domain.value}592593**Acceptance Criteria:**594{self._format_acceptance_criteria(requirement.acceptance_criteria)}595596**Definition of Done:**597- [ ] Implementation complete598- [ ] Security tests pass599- [ ] Code review complete600- [ ] Security review approved601- [ ] Documentation updated602603**Security Test Cases:**604{self._format_test_cases(requirement.test_cases)}605606**Traceability:**607- Threats: {', '.join(requirement.threat_refs) or 'N/A'}608- Compliance: {', '.join(requirement.compliance_refs) or 'N/A'}609"""610return story611612def _format_acceptance_criteria(self, criteria: List[str]) -> str:613return "\n".join(f"- [ ] {c}" for c in criteria) if criteria else "- [ ] TBD"614615def _format_test_cases(self, tests: List[str]) -> str:616return "\n".join(f"- {t}" for t in tests) if tests else "- TBD"617618def generate_epic(619self,620requirement_set: RequirementSet,621domain: SecurityDomain622) -> str:623"""Generate an epic for a security domain."""624reqs = requirement_set.get_by_domain(domain)625626epic = f"""627# Security Epic: {domain.value.replace('_', ' ').title()}628629## Overview630This epic covers all security requirements related to {domain.value.replace('_', ' ')}.631632## Business Value633- Protect against {domain.value.replace('_', ' ')} related threats634- Meet compliance requirements635- Reduce security risk636637## Stories in this Epic638{chr(10).join(f'- [{r.id}] {r.title}' for r in reqs)}639640## Acceptance Criteria641- All stories complete642- Security tests passing643- Security review approved644- Compliance requirements met645646## Risk if Not Implemented647- Vulnerability to {domain.value.replace('_', ' ')} attacks648- Compliance violations649- Potential data breach650651## Dependencies652{chr(10).join(f'- {d}' for r in reqs for d in r.dependencies) or '- None identified'}653"""654return epic655```656657## Best Practices658659### Do's660661- **Trace to threats** - Every requirement should map to threats662- **Be specific** - Vague requirements can't be tested663- **Include acceptance criteria** - Define "done"664- **Consider compliance** - Map to frameworks early665- **Review regularly** - Requirements evolve with threats666667### Don'ts668669- **Don't be generic** - "Be secure" is not a requirement670- **Don't skip rationale** - Explain why it matters671- **Don't ignore priorities** - Not all requirements are equal672- **Don't forget testability** - If you can't test it, you can't verify it673- **Don't work in isolation** - Involve stakeholders674