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.
references/details.md
1# security-requirement-extraction — templates and worked examples23## Templates45### Template 1: Security Requirement Model67```python8from dataclasses import dataclass, field9from enum import Enum10from typing import List, Dict, Optional, Set11from datetime import datetime1213class RequirementType(Enum):14FUNCTIONAL = "functional"15NON_FUNCTIONAL = "non_functional"16CONSTRAINT = "constraint"171819class Priority(Enum):20CRITICAL = 121HIGH = 222MEDIUM = 323LOW = 4242526class SecurityDomain(Enum):27AUTHENTICATION = "authentication"28AUTHORIZATION = "authorization"29DATA_PROTECTION = "data_protection"30AUDIT_LOGGING = "audit_logging"31INPUT_VALIDATION = "input_validation"32ERROR_HANDLING = "error_handling"33SESSION_MANAGEMENT = "session_management"34CRYPTOGRAPHY = "cryptography"35NETWORK_SECURITY = "network_security"36AVAILABILITY = "availability"373839class ComplianceFramework(Enum):40PCI_DSS = "pci_dss"41HIPAA = "hipaa"42GDPR = "gdpr"43SOC2 = "soc2"44NIST_CSF = "nist_csf"45ISO_27001 = "iso_27001"46OWASP = "owasp"474849@dataclass50class SecurityRequirement:51id: str52title: str53description: str54req_type: RequirementType55domain: SecurityDomain56priority: Priority57rationale: str = ""58acceptance_criteria: List[str] = field(default_factory=list)59test_cases: List[str] = field(default_factory=list)60threat_refs: List[str] = field(default_factory=list)61compliance_refs: List[str] = field(default_factory=list)62dependencies: List[str] = field(default_factory=list)63status: str = "draft"64owner: str = ""65created_date: datetime = field(default_factory=datetime.now)6667def to_user_story(self) -> str:68"""Convert to user story format."""69return f"""70**{self.id}: {self.title}**7172As a security-conscious system,73I need to {self.description.lower()},74So that {self.rationale.lower()}.7576**Acceptance Criteria:**77{chr(10).join(f'- [ ] {ac}' for ac in self.acceptance_criteria)}7879**Priority:** {self.priority.name}80**Domain:** {self.domain.value}81**Threat References:** {', '.join(self.threat_refs)}82"""8384def to_test_spec(self) -> str:85"""Convert to test specification."""86return f"""87## Test Specification: {self.id}8889### Requirement90{self.description}9192### Test Cases93{chr(10).join(f'{i+1}. {tc}' for i, tc in enumerate(self.test_cases))}9495### Acceptance Criteria Verification96{chr(10).join(f'- {ac}' for ac in self.acceptance_criteria)}97"""9899100@dataclass101class RequirementSet:102name: str103version: str104requirements: List[SecurityRequirement] = field(default_factory=list)105106def add(self, req: SecurityRequirement) -> None:107self.requirements.append(req)108109def get_by_domain(self, domain: SecurityDomain) -> List[SecurityRequirement]:110return [r for r in self.requirements if r.domain == domain]111112def get_by_priority(self, priority: Priority) -> List[SecurityRequirement]:113return [r for r in self.requirements if r.priority == priority]114115def get_by_threat(self, threat_id: str) -> List[SecurityRequirement]:116return [r for r in self.requirements if threat_id in r.threat_refs]117118def get_critical_requirements(self) -> List[SecurityRequirement]:119return [r for r in self.requirements if r.priority == Priority.CRITICAL]120121def export_markdown(self) -> str:122"""Export all requirements as markdown."""123lines = [f"# Security Requirements: {self.name}\n"]124lines.append(f"Version: {self.version}\n")125126for domain in SecurityDomain:127domain_reqs = self.get_by_domain(domain)128if domain_reqs:129lines.append(f"\n## {domain.value.replace('_', ' ').title()}\n")130for req in domain_reqs:131lines.append(req.to_user_story())132133return "\n".join(lines)134135def traceability_matrix(self) -> Dict[str, List[str]]:136"""Generate threat-to-requirement traceability."""137matrix = {}138for req in self.requirements:139for threat_id in req.threat_refs:140if threat_id not in matrix:141matrix[threat_id] = []142matrix[threat_id].append(req.id)143return matrix144```145146### Template 2: Threat-to-Requirement Extractor147148```python149from dataclasses import dataclass150from typing import List, Dict, Tuple151152@dataclass153class ThreatInput:154id: str155category: str # STRIDE category156title: str157description: str158target: str159impact: str160likelihood: str161162163class RequirementExtractor:164"""Extract security requirements from threats."""165166# Mapping of STRIDE categories to security domains and requirement patterns167STRIDE_MAPPINGS = {168"SPOOFING": {169"domains": [SecurityDomain.AUTHENTICATION, SecurityDomain.SESSION_MANAGEMENT],170"patterns": [171("Implement strong authentication for {target}",172"Ensure {target} authenticates all users before granting access"),173("Validate identity tokens for {target}",174"All authentication tokens must be cryptographically verified"),175("Implement session management for {target}",176"Sessions must be securely managed with proper expiration"),177]178},179"TAMPERING": {180"domains": [SecurityDomain.INPUT_VALIDATION, SecurityDomain.DATA_PROTECTION],181"patterns": [182("Validate all input to {target}",183"All input must be validated against expected formats"),184("Implement integrity checks for {target}",185"Data integrity must be verified using cryptographic signatures"),186("Protect {target} from modification",187"Implement controls to prevent unauthorized data modification"),188]189},190"REPUDIATION": {191"domains": [SecurityDomain.AUDIT_LOGGING],192"patterns": [193("Log all security events for {target}",194"Security-relevant events must be logged for audit purposes"),195("Implement non-repudiation for {target}",196"Critical actions must have cryptographic proof of origin"),197("Protect audit logs for {target}",198"Audit logs must be tamper-evident and protected"),199]200},201"INFORMATION_DISCLOSURE": {202"domains": [SecurityDomain.DATA_PROTECTION, SecurityDomain.CRYPTOGRAPHY],203"patterns": [204("Encrypt sensitive data in {target}",205"Sensitive data must be encrypted at rest and in transit"),206("Implement access controls for {target}",207"Data access must be restricted based on need-to-know"),208("Prevent information leakage from {target}",209"Error messages and logs must not expose sensitive information"),210]211},212"DENIAL_OF_SERVICE": {213"domains": [SecurityDomain.AVAILABILITY, SecurityDomain.INPUT_VALIDATION],214"patterns": [215("Implement rate limiting for {target}",216"Requests must be rate-limited to prevent resource exhaustion"),217("Ensure availability of {target}",218"System must remain available under high load conditions"),219("Implement resource quotas for {target}",220"Resource consumption must be bounded and monitored"),221]222},223"ELEVATION_OF_PRIVILEGE": {224"domains": [SecurityDomain.AUTHORIZATION],225"patterns": [226("Enforce authorization for {target}",227"All actions must be authorized based on user permissions"),228("Implement least privilege for {target}",229"Users must only have minimum necessary permissions"),230("Validate permissions for {target}",231"Permission checks must be performed server-side"),232]233},234}235236def extract_requirements(237self,238threats: List[ThreatInput],239project_name: str240) -> RequirementSet:241"""Extract security requirements from threats."""242req_set = RequirementSet(243name=f"{project_name} Security Requirements",244version="1.0"245)246247req_counter = 1248for threat in threats:249reqs = self._threat_to_requirements(threat, req_counter)250for req in reqs:251req_set.add(req)252req_counter += len(reqs)253254return req_set255256def _threat_to_requirements(257self,258threat: ThreatInput,259start_id: int260) -> List[SecurityRequirement]:261"""Convert a single threat to requirements."""262requirements = []263mapping = self.STRIDE_MAPPINGS.get(threat.category, {})264domains = mapping.get("domains", [])265patterns = mapping.get("patterns", [])266267priority = self._calculate_priority(threat.impact, threat.likelihood)268269for i, (title_pattern, desc_pattern) in enumerate(patterns):270req = SecurityRequirement(271id=f"SR-{start_id + i:03d}",272title=title_pattern.format(target=threat.target),273description=desc_pattern.format(target=threat.target),274req_type=RequirementType.FUNCTIONAL,275domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,276priority=priority,277rationale=f"Mitigates threat: {threat.title}",278threat_refs=[threat.id],279acceptance_criteria=self._generate_acceptance_criteria(280threat.category, threat.target281),282test_cases=self._generate_test_cases(283threat.category, threat.target284)285)286requirements.append(req)287288return requirements289290def _calculate_priority(self, impact: str, likelihood: str) -> Priority:291"""Calculate requirement priority from threat attributes."""292score_map = {"LOW": 1, "MEDIUM": 2, "HIGH": 3, "CRITICAL": 4}293impact_score = score_map.get(impact.upper(), 2)294likelihood_score = score_map.get(likelihood.upper(), 2)295296combined = impact_score * likelihood_score297298if combined >= 12:299return Priority.CRITICAL300elif combined >= 6:301return Priority.HIGH302elif combined >= 3:303return Priority.MEDIUM304return Priority.LOW305306def _generate_acceptance_criteria(307self,308category: str,309target: str310) -> List[str]:311"""Generate acceptance criteria for requirement."""312criteria_templates = {313"SPOOFING": [314f"Users must authenticate before accessing {target}",315"Authentication failures are logged and monitored",316"Multi-factor authentication is available for sensitive operations",317],318"TAMPERING": [319f"All input to {target} is validated",320"Data integrity is verified before processing",321"Modification attempts trigger alerts",322],323"REPUDIATION": [324f"All actions on {target} are logged with user identity",325"Logs cannot be modified by regular users",326"Log retention meets compliance requirements",327],328"INFORMATION_DISCLOSURE": [329f"Sensitive data in {target} is encrypted",330"Access to sensitive data is logged",331"Error messages do not reveal sensitive information",332],333"DENIAL_OF_SERVICE": [334f"Rate limiting is enforced on {target}",335"System degrades gracefully under load",336"Resource exhaustion triggers alerts",337],338"ELEVATION_OF_PRIVILEGE": [339f"Authorization is checked for all {target} operations",340"Users cannot access resources beyond their permissions",341"Privilege changes are logged and monitored",342],343}344return criteria_templates.get(category, [])345346def _generate_test_cases(347self,348category: str,349target: str350) -> List[str]:351"""Generate test cases for requirement."""352test_templates = {353"SPOOFING": [354f"Test: Unauthenticated access to {target} is denied",355"Test: Invalid credentials are rejected",356"Test: Session tokens cannot be forged",357],358"TAMPERING": [359f"Test: Invalid input to {target} is rejected",360"Test: Tampered data is detected and rejected",361"Test: SQL injection attempts are blocked",362],363"REPUDIATION": [364"Test: Security events are logged",365"Test: Logs include sufficient detail for forensics",366"Test: Log integrity is protected",367],368"INFORMATION_DISCLOSURE": [369f"Test: {target} data is encrypted in transit",370f"Test: {target} data is encrypted at rest",371"Test: Error messages are sanitized",372],373"DENIAL_OF_SERVICE": [374f"Test: Rate limiting on {target} works correctly",375"Test: System handles burst traffic gracefully",376"Test: Resource limits are enforced",377],378"ELEVATION_OF_PRIVILEGE": [379f"Test: Unauthorized access to {target} is denied",380"Test: Privilege escalation attempts are blocked",381"Test: IDOR vulnerabilities are not present",382],383}384return test_templates.get(category, [])385```386387### Template 3: Compliance Mapping388389```python390from typing import Dict, List, Set391392class ComplianceMapper:393"""Map security requirements to compliance frameworks."""394395FRAMEWORK_CONTROLS = {396ComplianceFramework.PCI_DSS: {397SecurityDomain.AUTHENTICATION: ["8.1", "8.2", "8.3"],398SecurityDomain.AUTHORIZATION: ["7.1", "7.2"],399SecurityDomain.DATA_PROTECTION: ["3.4", "3.5", "4.1"],400SecurityDomain.AUDIT_LOGGING: ["10.1", "10.2", "10.3"],401SecurityDomain.NETWORK_SECURITY: ["1.1", "1.2", "1.3"],402SecurityDomain.CRYPTOGRAPHY: ["3.5", "3.6", "4.1"],403},404ComplianceFramework.HIPAA: {405SecurityDomain.AUTHENTICATION: ["164.312(d)"],406SecurityDomain.AUTHORIZATION: ["164.312(a)(1)"],407SecurityDomain.DATA_PROTECTION: ["164.312(a)(2)(iv)", "164.312(e)(2)(ii)"],408SecurityDomain.AUDIT_LOGGING: ["164.312(b)"],409},410ComplianceFramework.GDPR: {411SecurityDomain.DATA_PROTECTION: ["Art. 32", "Art. 25"],412SecurityDomain.AUDIT_LOGGING: ["Art. 30"],413SecurityDomain.AUTHORIZATION: ["Art. 25"],414},415ComplianceFramework.OWASP: {416SecurityDomain.AUTHENTICATION: ["V2.1", "V2.2", "V2.3"],417SecurityDomain.SESSION_MANAGEMENT: ["V3.1", "V3.2", "V3.3"],418SecurityDomain.INPUT_VALIDATION: ["V5.1", "V5.2", "V5.3"],419SecurityDomain.CRYPTOGRAPHY: ["V6.1", "V6.2"],420SecurityDomain.ERROR_HANDLING: ["V7.1", "V7.2"],421SecurityDomain.DATA_PROTECTION: ["V8.1", "V8.2", "V8.3"],422SecurityDomain.AUDIT_LOGGING: ["V7.1", "V7.2"],423},424}425426def map_requirement_to_compliance(427self,428requirement: SecurityRequirement,429frameworks: List[ComplianceFramework]430) -> Dict[str, List[str]]:431"""Map a requirement to compliance controls."""432mapping = {}433for framework in frameworks:434controls = self.FRAMEWORK_CONTROLS.get(framework, {})435domain_controls = controls.get(requirement.domain, [])436if domain_controls:437mapping[framework.value] = domain_controls438return mapping439440def get_requirements_for_control(441self,442requirement_set: RequirementSet,443framework: ComplianceFramework,444control_id: str445) -> List[SecurityRequirement]:446"""Find requirements that satisfy a compliance control."""447matching = []448framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})449450for domain, controls in framework_controls.items():451if control_id in controls:452matching.extend(requirement_set.get_by_domain(domain))453454return matching455456def generate_compliance_matrix(457self,458requirement_set: RequirementSet,459frameworks: List[ComplianceFramework]460) -> Dict[str, Dict[str, List[str]]]:461"""Generate compliance traceability matrix."""462matrix = {}463464for framework in frameworks:465matrix[framework.value] = {}466framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})467468for domain, controls in framework_controls.items():469for control in controls:470reqs = self.get_requirements_for_control(471requirement_set, framework, control472)473if reqs:474matrix[framework.value][control] = [r.id for r in reqs]475476return matrix477478def gap_analysis(479self,480requirement_set: RequirementSet,481framework: ComplianceFramework482) -> Dict[str, List[str]]:483"""Identify compliance gaps."""484gaps = {"missing_controls": [], "weak_coverage": []}485framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})486487for domain, controls in framework_controls.items():488domain_reqs = requirement_set.get_by_domain(domain)489for control in controls:490matching = self.get_requirements_for_control(491requirement_set, framework, control492)493if not matching:494gaps["missing_controls"].append(f"{framework.value}:{control}")495elif len(matching) < 2:496gaps["weak_coverage"].append(f"{framework.value}:{control}")497498return gaps499```500501### Template 4: Security User Story Generator502503```python504class SecurityUserStoryGenerator:505"""Generate security-focused user stories."""506507STORY_TEMPLATES = {508SecurityDomain.AUTHENTICATION: {509"as_a": "security-conscious user",510"so_that": "my identity is protected from impersonation",511},512SecurityDomain.AUTHORIZATION: {513"as_a": "system administrator",514"so_that": "users can only access resources appropriate to their role",515},516SecurityDomain.DATA_PROTECTION: {517"as_a": "data owner",518"so_that": "my sensitive information remains confidential",519},520SecurityDomain.AUDIT_LOGGING: {521"as_a": "security analyst",522"so_that": "I can investigate security incidents",523},524SecurityDomain.INPUT_VALIDATION: {525"as_a": "application developer",526"so_that": "the system is protected from malicious input",527},528}529530def generate_story(self, requirement: SecurityRequirement) -> str:531"""Generate a user story from requirement."""532template = self.STORY_TEMPLATES.get(533requirement.domain,534{"as_a": "user", "so_that": "the system is secure"}535)536537story = f"""538## {requirement.id}: {requirement.title}539540**User Story:**541As a {template['as_a']},542I want the system to {requirement.description.lower()},543So that {template['so_that']}.544545**Priority:** {requirement.priority.name}546**Type:** {requirement.req_type.value}547**Domain:** {requirement.domain.value}548549**Acceptance Criteria:**550{self._format_acceptance_criteria(requirement.acceptance_criteria)}551552**Definition of Done:**553- [ ] Implementation complete554- [ ] Security tests pass555- [ ] Code review complete556- [ ] Security review approved557- [ ] Documentation updated558559**Security Test Cases:**560{self._format_test_cases(requirement.test_cases)}561562**Traceability:**563- Threats: {', '.join(requirement.threat_refs) or 'N/A'}564- Compliance: {', '.join(requirement.compliance_refs) or 'N/A'}565"""566return story567568def _format_acceptance_criteria(self, criteria: List[str]) -> str:569return "\n".join(f"- [ ] {c}" for c in criteria) if criteria else "- [ ] TBD"570571def _format_test_cases(self, tests: List[str]) -> str:572return "\n".join(f"- {t}" for t in tests) if tests else "- TBD"573574def generate_epic(575self,576requirement_set: RequirementSet,577domain: SecurityDomain578) -> str:579"""Generate an epic for a security domain."""580reqs = requirement_set.get_by_domain(domain)581582epic = f"""583# Security Epic: {domain.value.replace('_', ' ').title()}584585## Overview586This epic covers all security requirements related to {domain.value.replace('_', ' ')}.587588## Business Value589- Protect against {domain.value.replace('_', ' ')} related threats590- Meet compliance requirements591- Reduce security risk592593## Stories in this Epic594{chr(10).join(f'- [{r.id}] {r.title}' for r in reqs)}595596## Acceptance Criteria597- All stories complete598- Security tests passing599- Security review approved600- Compliance requirements met601602## Risk if Not Implemented603- Vulnerability to {domain.value.replace('_', ' ')} attacks604- Compliance violations605- Potential data breach606607## Dependencies608{chr(10).join(f'- {d}' for r in reqs for d in r.dependencies) or '- None identified'}609"""610return epic611```612