Skip to content
Report library
Purpose / Other

Security Requirement Extraction Skill Security Audit

What the author says it does (original text)

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.

Independent security check

Security risks found

Files checked
2
Risks found
4
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.No risks found
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.No risks found
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.No risks found
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 3
Medium risk

Compliance controls are treated as covered solely from a security-domain match

Source references: 4
What we found

The mapper treats every requirement in a related security domain as matching the associated control IDs; it does not inspect requirement substance, control version, implementation evidence, or test results. Its own method describes the matches as requirements that “satisfy a compliance control.”

Why this matters

A user could incorrectly conclude that PCI DSS, HIPAA, GDPR, or OWASP controls are satisfied, leading to release approval, reduced audit scope, or missed control gaps.

The example returns preset control IDs solely from a requirement's security domain and describes same-domain requirements as satisfying the control; it does not inspect the requirement text, framework version, implementation, or test evidence. Using its matrix for compliance decisions could overstate coverage. This is template code, not proof of execution; users can require control-by-control review, applicable versions, and implementation evidence.

references/details.md:426In the instructionsOpen original file
    def map_requirement_to_compliance(        self,        requirement: SecurityRequirement,        frameworks: List[ComplianceFramework]    ) -> Dict[str, List[str]]:        """Map a requirement to compliance controls."""        mapping = {}        for framework in frameworks:            controls = self.FRAMEWORK_CONTROLS.get(framework, {})            domain_controls = controls.get(requirement.domain, [])            if domain_controls:                mapping[framework.value] = domain_controls        return mapping
Show 3 other places
references/details.md:440In the instructionsOpen original file
    def get_requirements_for_control(        self,        requirement_set: RequirementSet,        framework: ComplianceFramework,        control_id: str    ) -> List[SecurityRequirement]:        """Find requirements that satisfy a compliance control."""        matching = []        framework_controls = self.FRAMEWORK_CONTROLS.get(framework, {})        for domain, controls in framework_controls.items():            if control_id in controls:                matching.extend(requirement_set.get_by_domain(domain))        return matching
references/details.md:493In the instructionsOpen original file
                )                if not matching:                    gaps["missing_controls"].append(f"{framework.value}:{control}")                elif len(matching) < 2:                    gaps["weak_coverage"].append(f"{framework.value}:{control}")
references/details.md:468In the instructionsOpen original file
            for domain, controls in framework_controls.items():                for control in controls:                    reqs = self.get_requirements_for_control(                        requirement_set, framework, control                    )                    if reqs:                        matrix[framework.value][control] = [r.id for r in reqs]
Medium risk

Unknown or differently cased threat categories are silently dropped

Source references: 6
What we found

Category lookup uses exact, case-sensitive keys. A missing key yields an empty pattern list, after which the conversion returns no requirements without an error, warning, or review marker. Acceptance-criteria and test-case lookups use the same exact matching.

Why this matters

A typo, lowercase input, or unsupported threat type can disappear completely from the requirement set, making users think the threat was processed when no control or test was produced.

The STRIDE keys are uppercase, while lookup uses the category as supplied. An unrecognized category yields no patterns, so the loop produces no requirements; acceptance criteria and tests also use exact-key lookups with empty-list defaults. Lowercase, misspelled, or new categories could therefore produce no requirements without notice. This is reference template code, not evidence of actual processing; users can require normalization, validation, and an error or human review for unknown values.

references/details.md:262In the instructionsOpen original file
        """Convert a single threat to requirements."""        requirements = []        mapping = self.STRIDE_MAPPINGS.get(threat.category, {})        domains = mapping.get("domains", [])        patterns = mapping.get("patterns", [])        priority = self._calculate_priority(threat.impact, threat.likelihood)        for i, (title_pattern, desc_pattern) in enumerate(patterns):            req = SecurityRequirement(
Show 5 other places
references/details.md:269In the instructionsOpen original file
        for i, (title_pattern, desc_pattern) in enumerate(patterns):            req = SecurityRequirement(                id=f"SR-{start_id + i:03d}",                title=title_pattern.format(target=threat.target),                description=desc_pattern.format(target=threat.target),                req_type=RequirementType.FUNCTIONAL,                domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,                priority=priority,                rationale=f"Mitigates threat: {threat.title}",                threat_refs=[threat.id],                acceptance_criteria=self._generate_acceptance_criteria(                    threat.category, threat.target                ),                test_cases=self._generate_test_cases(                    threat.category, threat.target                )            )            requirements.append(req)        return requirements
references/details.md:343In the instructionsOpen original file
            ],        }        return criteria_templates.get(category, [])
references/details.md:383In the instructionsOpen original file
            ],        }        return test_templates.get(category, [])```
references/details.md:163In the instructionsOpen original file
class RequirementExtractor:    """Extract security requirements from threats."""    # Mapping of STRIDE categories to security domains and requirement patterns    STRIDE_MAPPINGS = {        "SPOOFING": {            "domains": [SecurityDomain.AUTHENTICATION, SecurityDomain.SESSION_MANAGEMENT],
references/details.md:286In the instructionsOpen original file
            )            requirements.append(req)        return requirements
Medium risk

Invalid risk values silently default to MEDIUM and can distort priorities

Source references: 2
What we found

Impact and likelihood are unrestricted strings, and every unrecognized value receives score 2. The code gives no warning for missing values, typos, or an incompatible scoring scale.

Why this matters

Bad input can raise or lower assessed risk. An unknown value receives the same weight as MEDIUM, affecting which requirements are marked critical or implemented first and potentially influencing security-resourcing and release decisions.

ThreatInput defines impact and likelihood as unrestricted strings. The scoring function assigns any unrecognized value the default score 2, equivalent to MEDIUM, without a warning; missing constraints or typos could alter the resulting priority and the user's remediation order. This is template logic, not evidence it ran. Users can require enums, explicit validation, and failure or human-review flags for unknown ratings.

references/details.md:290In the instructionsOpen original file
    def _calculate_priority(self, impact: str, likelihood: str) -> Priority:        """Calculate requirement priority from threat attributes."""        score_map = {"LOW": 1, "MEDIUM": 2, "HIGH": 3, "CRITICAL": 4}        impact_score = score_map.get(impact.upper(), 2)        likelihood_score = score_map.get(likelihood.upper(), 2)        combined = impact_score * likelihood_score        if combined >= 12:            return Priority.CRITICAL        elif combined >= 6:            return Priority.HIGH        elif combined >= 3:            return Priority.MEDIUM        return Priority.LOW
Show 1 other places
references/details.md:152In the instructionsOpen original file
@dataclassclass ThreatInput:    id: str    category: str  # STRIDE category    title: str    description: str    target: str    impact: str    likelihood: str
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.Risks found: 1
Low risk

Unescaped threat text is embedded into downstream Markdown documents

Source references: 4
What we found

Threat target, title, and ID values are formatted directly into requirement titles, rationale, and traceability fields, then inserted directly into Markdown user stories. Markdown, forged checkboxes, or instructions aimed at a downstream AI are neither escaped nor marked as untrusted.

Why this matters

Malicious or accidentally crafted threat text can alter the document’s visual structure, forge approval-like status, or be mistaken for instructions when another AI processes it, influencing human security decisions or downstream automation.

The template formats threat.target into titles and descriptions, inserts threat.title into rationale, and retains threat.id; those fields are then placed directly into Markdown stories and traceability lists. If threat data is untrusted, Markdown, fake task items, or prompt-like text could appear in documents read by people or later AI and influence decisions, although the source does not show automatic execution of that text. Users can require escaping or clear untrusted-data labels and restrict downstream automation from treating generated content as instructions.

references/details.md:270In the instructionsOpen original file
        for i, (title_pattern, desc_pattern) in enumerate(patterns):            req = SecurityRequirement(                id=f"SR-{start_id + i:03d}",                title=title_pattern.format(target=threat.target),                description=desc_pattern.format(target=threat.target),                req_type=RequirementType.FUNCTIONAL,                domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,                priority=priority,                rationale=f"Mitigates threat: {threat.title}",                threat_refs=[threat.id],                acceptance_criteria=self._generate_acceptance_criteria(
Show 3 other places
references/details.md:537In the instructionsOpen original file
        story = f"""## {requirement.id}: {requirement.title}**User Story:**As a {template['as_a']},I want the system to {requirement.description.lower()},So that {template['so_that']}.**Priority:** {requirement.priority.name}**Type:** {requirement.req_type.value}**Domain:** {requirement.domain.value}**Acceptance Criteria:**{self._format_acceptance_criteria(requirement.acceptance_criteria)}**Definition of Done:**- [ ] Implementation complete- [ ] Security tests pass- [ ] Code review complete- [ ] Security review approved- [ ] Documentation updated**Security Test Cases:**{self._format_test_cases(requirement.test_cases)}**Traceability:**- Threats: {', '.join(requirement.threat_refs) or 'N/A'}- Compliance: {', '.join(requirement.compliance_refs) or 'N/A'}"""
references/details.md:269In the instructionsOpen original file
        for i, (title_pattern, desc_pattern) in enumerate(patterns):            req = SecurityRequirement(                id=f"SR-{start_id + i:03d}",                title=title_pattern.format(target=threat.target),                description=desc_pattern.format(target=threat.target),                req_type=RequirementType.FUNCTIONAL,                domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,                priority=priority,                rationale=f"Mitigates threat: {threat.title}",                threat_refs=[threat.id],                acceptance_criteria=self._generate_acceptance_criteria(                    threat.category, threat.target                ),                test_cases=self._generate_test_cases(                    threat.category, threat.target                )            )
references/details.md:69In the instructionsOpen original file
        """Convert to user story format."""        return f"""**{self.id}: {self.title}**As a security-conscious system,I need to {self.description.lower()},So that {self.rationale.lower()}.**Acceptance Criteria:**{chr(10).join(f'- [ ] {ac}' for ac in self.acceptance_criteria)}**Priority:** {self.priority.name}**Domain:** {self.domain.value}**Threat References:** {', '.join(self.threat_refs)}"""
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.No risks found

Inside this skill

4 instruction sections

The Skill is intended to convert threat models into security requirements, user stories, acceptance criteria, and test cases, with emphasis on traceability, testability, priority, and risk level.

View source
SKILL.md:8In the instructionsOpen original file
Transform threat analysis into actionable security requirements.
SKILL.md:40In the instructionsOpen original file
| Attribute        | Description                 || ---------------- | --------------------------- || **Traceability** | Links to threats/compliance || **Testability**  | Can be verified             || **Priority**     | Business importance         || **Risk Level**   | Impact if not met           |

The reference implementation applies fixed security domains and requirement text based on STRIDE category; each input threat can produce multiple requirements carrying the threat ID as a traceability reference.

View source
references/details.md:166In the instructionsOpen original file
    # Mapping of STRIDE categories to security domains and requirement patterns    STRIDE_MAPPINGS = {        "SPOOFING": {            "domains": [SecurityDomain.AUTHENTICATION, SecurityDomain.SESSION_MANAGEMENT],            "patterns": [                ("Implement strong authentication for {target}",
references/details.md:269In the instructionsOpen original file
        for i, (title_pattern, desc_pattern) in enumerate(patterns):            req = SecurityRequirement(                id=f"SR-{start_id + i:03d}",                title=title_pattern.format(target=threat.target),                description=desc_pattern.format(target=threat.target),                req_type=RequirementType.FUNCTIONAL,                domain=domains[i % len(domains)] if domains else SecurityDomain.DATA_PROTECTION,                priority=priority,                rationale=f"Mitigates threat: {threat.title}",                threat_refs=[threat.id],                acceptance_criteria=self._generate_acceptance_criteria(                    threat.category, threat.target                ),                test_cases=self._generate_test_cases(                    threat.category, threat.target                )            )

The supplied material consists of Python templates embedded in Markdown; the visible code constructs and returns strings and in-memory objects, without showing network requests, command execution, credential access, or direct writes to user files.

View source
references/details.md:121In the instructionsOpen original file
    def export_markdown(self) -> str:        """Export all requirements as markdown."""        lines = [f"# Security Requirements: {self.name}\n"]        lines.append(f"Version: {self.version}\n")        for domain in SecurityDomain:            domain_reqs = self.get_by_domain(domain)            if domain_reqs:                lines.append(f"\n## {domain.value.replace('_', ' ').title()}\n")                for req in domain_reqs:                    lines.append(req.to_user_story())        return "\n".join(lines)
Start here · InstructionsSKILL.md
security-requirement-extraction
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.

File reference map

References: 1
Files making referencesReferenced content
Lines show actual file references, not execution order. Select a node to highlight its connections and inspect the files and source locations. Dashed lines include files that still need locating.
Files and check records2 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included
  • references/details.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions
  • references/details.mdSupporting file

Operations mentioned in code and instructions

Read files
SKILL.md:49In the instructionsOpen original file
Full template library lives in `references/details.md`. Read that file when you need concrete templates for this skill.
Read keys or account settings
references/details.md:355In the instructionsOpen original file
                f"Test: Unauthenticated access to {target} is denied",                "Test: Invalid credentials are rejected",                "Test: Session tokens cannot be forged",
Lines read
680
File checksum (to compare versions)
ca4391937d88a932a5023d4b0f309d99682a9be111ed9547a957053a80910402