diff --git a/skills/software-security/SKILL.md b/skills/software-security/SKILL.md index 66ade94..7405455 100644 --- a/skills/software-security/SKILL.md +++ b/skills/software-security/SKILL.md @@ -24,7 +24,20 @@ When writing or reviewing code: - `codeguard-1-hardcoded-credentials.md` - Never hardcode secrets, passwords, API keys, or tokens - `codeguard-1-crypto-algorithms.md` - Use only modern, secure cryptographic algorithms - `codeguard-1-digital-certificates.md` - Validate and manage digital certificates securely -2. Context-Specific Rules: Apply rules from /rules directory based on the language of the feature being implemented using the table given below: +2. Tag-Based Rules: When you identify any of these security contexts in the code, apply ALL rules with the matching tag: + + +| Security Context (Tag) | Rule Files to Apply | +|------------------------|---------------------| +| authentication | codeguard-0-authentication-mfa.md, codeguard-0-session-management-and-cookies.md | +| data-security | codeguard-0-additional-cryptography.md, codeguard-0-data-storage.md | +| infrastructure | codeguard-0-cloud-orchestration-kubernetes.md, codeguard-0-data-storage.md, codeguard-0-devops-ci-cd-containers.md, codeguard-0-iac-security.md | +| privacy | codeguard-0-logging.md, codeguard-0-privacy-data-protection.md | +| secrets | codeguard-0-additional-cryptography.md, codeguard-1-digital-certificates.md, codeguard-1-hardcoded-credentials.md | +| web | codeguard-0-api-web-services.md, codeguard-0-authentication-mfa.md, codeguard-0-client-side-web-security.md, codeguard-0-input-validation-injection.md, codeguard-0-session-management-and-cookies.md | + + +3. Language-Specific Rules: Apply rules from /rules directory based on the programming language of the feature being implemented using the table given below: | Language | Rule Files to Apply | @@ -55,7 +68,7 @@ When writing or reviewing code: | yaml | codeguard-0-additional-cryptography.md, codeguard-0-api-web-services.md, codeguard-0-authorization-access-control.md, codeguard-0-cloud-orchestration-kubernetes.md, codeguard-0-data-storage.md, codeguard-0-devops-ci-cd-containers.md, codeguard-0-framework-and-languages.md, codeguard-0-iac-security.md, codeguard-0-logging.md, codeguard-0-privacy-data-protection.md, codeguard-0-supply-chain-security.md | -3. Proactive Security: Don't just avoid vulnerabilities-actively implement secure patterns: +4. Proactive Security: Don't just avoid vulnerabilities-actively implement secure patterns: - Use parameterized queries for database access - Validate and sanitize all user input - Apply least-privilege principles @@ -71,8 +84,8 @@ When generating or reviewing code, follow this workflow: ### 1. Initial Security Check Before writing any code: - Check: Will this handle credentials? → Apply codeguard-1-hardcoded-credentials +- Check: What security tags apply? → Load all rules with matching tags (e.g., "authentication", "web", "secrets") - Check: What language am I using? → Identify applicable language-specific rules -- Check: What security domains are involved? → Load relevant rule files ### 2. Code Generation While writing code: diff --git a/skills/software-security/rules/codeguard-0-additional-cryptography.md b/skills/software-security/rules/codeguard-0-additional-cryptography.md index 1969747..f9639f4 100644 --- a/skills/software-security/rules/codeguard-0-additional-cryptography.md +++ b/skills/software-security/rules/codeguard-0-additional-cryptography.md @@ -15,6 +15,9 @@ languages: - xml - yaml alwaysApply: false +tags: +- data-security +- secrets --- rule_id: codeguard-0-additional-cryptography diff --git a/skills/software-security/rules/codeguard-0-api-web-services.md b/skills/software-security/rules/codeguard-0-api-web-services.md index 73ed291..87e1ead 100644 --- a/skills/software-security/rules/codeguard-0-api-web-services.md +++ b/skills/software-security/rules/codeguard-0-api-web-services.md @@ -12,6 +12,8 @@ languages: - xml - yaml alwaysApply: false +tags: +- web --- rule_id: codeguard-0-api-web-services diff --git a/skills/software-security/rules/codeguard-0-authentication-mfa.md b/skills/software-security/rules/codeguard-0-authentication-mfa.md index 9be5d6c..5eca622 100644 --- a/skills/software-security/rules/codeguard-0-authentication-mfa.md +++ b/skills/software-security/rules/codeguard-0-authentication-mfa.md @@ -13,6 +13,9 @@ languages: - swift - typescript alwaysApply: false +tags: +- authentication +- web --- rule_id: codeguard-0-authentication-mfa diff --git a/skills/software-security/rules/codeguard-0-client-side-web-security.md b/skills/software-security/rules/codeguard-0-client-side-web-security.md index 207566f..ec08812 100644 --- a/skills/software-security/rules/codeguard-0-client-side-web-security.md +++ b/skills/software-security/rules/codeguard-0-client-side-web-security.md @@ -8,6 +8,8 @@ languages: - typescript - vlang alwaysApply: false +tags: +- web --- rule_id: codeguard-0-client-side-web-security diff --git a/skills/software-security/rules/codeguard-0-cloud-orchestration-kubernetes.md b/skills/software-security/rules/codeguard-0-cloud-orchestration-kubernetes.md index 4e45e1b..2d73963 100644 --- a/skills/software-security/rules/codeguard-0-cloud-orchestration-kubernetes.md +++ b/skills/software-security/rules/codeguard-0-cloud-orchestration-kubernetes.md @@ -4,6 +4,8 @@ languages: - javascript - yaml alwaysApply: false +tags: +- infrastructure --- rule_id: codeguard-0-cloud-orchestration-kubernetes diff --git a/skills/software-security/rules/codeguard-0-data-storage.md b/skills/software-security/rules/codeguard-0-data-storage.md index 24bcb24..cb2c99c 100644 --- a/skills/software-security/rules/codeguard-0-data-storage.md +++ b/skills/software-security/rules/codeguard-0-data-storage.md @@ -6,6 +6,9 @@ languages: - sql - yaml alwaysApply: false +tags: +- data-security +- infrastructure --- rule_id: codeguard-0-data-storage diff --git a/skills/software-security/rules/codeguard-0-devops-ci-cd-containers.md b/skills/software-security/rules/codeguard-0-devops-ci-cd-containers.md index 205dcff..06045ef 100644 --- a/skills/software-security/rules/codeguard-0-devops-ci-cd-containers.md +++ b/skills/software-security/rules/codeguard-0-devops-ci-cd-containers.md @@ -8,6 +8,8 @@ languages: - xml - yaml alwaysApply: false +tags: +- infrastructure --- rule_id: codeguard-0-devops-ci-cd-containers diff --git a/skills/software-security/rules/codeguard-0-iac-security.md b/skills/software-security/rules/codeguard-0-iac-security.md index 20e243c..98a9646 100644 --- a/skills/software-security/rules/codeguard-0-iac-security.md +++ b/skills/software-security/rules/codeguard-0-iac-security.md @@ -9,6 +9,8 @@ languages: - shell - yaml alwaysApply: false +tags: +- infrastructure --- rule_id: codeguard-0-iac-security diff --git a/skills/software-security/rules/codeguard-0-input-validation-injection.md b/skills/software-security/rules/codeguard-0-input-validation-injection.md index 0966f2e..0e64ba8 100644 --- a/skills/software-security/rules/codeguard-0-input-validation-injection.md +++ b/skills/software-security/rules/codeguard-0-input-validation-injection.md @@ -15,6 +15,8 @@ languages: - sql - typescript alwaysApply: false +tags: +- web --- rule_id: codeguard-0-input-validation-injection diff --git a/skills/software-security/rules/codeguard-0-logging.md b/skills/software-security/rules/codeguard-0-logging.md index aca7ccf..32b82bb 100644 --- a/skills/software-security/rules/codeguard-0-logging.md +++ b/skills/software-security/rules/codeguard-0-logging.md @@ -5,6 +5,8 @@ languages: - javascript - yaml alwaysApply: false +tags: +- privacy --- rule_id: codeguard-0-logging diff --git a/skills/software-security/rules/codeguard-0-privacy-data-protection.md b/skills/software-security/rules/codeguard-0-privacy-data-protection.md index fc9a18b..8ebe752 100644 --- a/skills/software-security/rules/codeguard-0-privacy-data-protection.md +++ b/skills/software-security/rules/codeguard-0-privacy-data-protection.md @@ -5,6 +5,8 @@ languages: - matlab - yaml alwaysApply: false +tags: +- privacy --- rule_id: codeguard-0-privacy-data-protection diff --git a/skills/software-security/rules/codeguard-0-session-management-and-cookies.md b/skills/software-security/rules/codeguard-0-session-management-and-cookies.md index aee07ec..5805b19 100644 --- a/skills/software-security/rules/codeguard-0-session-management-and-cookies.md +++ b/skills/software-security/rules/codeguard-0-session-management-and-cookies.md @@ -11,6 +11,9 @@ languages: - ruby - typescript alwaysApply: false +tags: +- authentication +- web --- rule_id: codeguard-0-session-management-and-cookies diff --git a/skills/software-security/rules/codeguard-1-digital-certificates.md b/skills/software-security/rules/codeguard-1-digital-certificates.md index f08d10f..9e35de3 100644 --- a/skills/software-security/rules/codeguard-1-digital-certificates.md +++ b/skills/software-security/rules/codeguard-1-digital-certificates.md @@ -1,6 +1,8 @@ --- description: Certificate Best Practices alwaysApply: true +tags: +- secrets --- rule_id: codeguard-1-digital-certificates diff --git a/skills/software-security/rules/codeguard-1-hardcoded-credentials.md b/skills/software-security/rules/codeguard-1-hardcoded-credentials.md index 95295eb..007f57a 100644 --- a/skills/software-security/rules/codeguard-1-hardcoded-credentials.md +++ b/skills/software-security/rules/codeguard-1-hardcoded-credentials.md @@ -1,6 +1,8 @@ --- description: No Hardcoded Credentials alwaysApply: true +tags: +- secrets --- rule_id: codeguard-1-hardcoded-credentials diff --git a/sources/rules/core/codeguard-SKILLS.md.template b/sources/rules/core/codeguard-SKILLS.md.template index ff7420b..ad09a57 100644 --- a/sources/rules/core/codeguard-SKILLS.md.template +++ b/sources/rules/core/codeguard-SKILLS.md.template @@ -24,10 +24,13 @@ When writing or reviewing code: - `codeguard-1-hardcoded-credentials.md` - Never hardcode secrets, passwords, API keys, or tokens - `codeguard-1-crypto-algorithms.md` - Use only modern, secure cryptographic algorithms - `codeguard-1-digital-certificates.md` - Validate and manage digital certificates securely -2. Context-Specific Rules: Apply rules from /rules directory based on the language of the feature being implemented using the table given below: +2. Tag-Based Rules: When you identify any of these security contexts in the code, apply ALL rules with the matching tag: + + +3. Language-Specific Rules: Apply rules from /rules directory based on the programming language of the feature being implemented using the table given below: -3. Proactive Security: Don't just avoid vulnerabilities-actively implement secure patterns: +4. Proactive Security: Don't just avoid vulnerabilities-actively implement secure patterns: - Use parameterized queries for database access - Validate and sanitize all user input - Apply least-privilege principles @@ -43,8 +46,8 @@ When generating or reviewing code, follow this workflow: ### 1. Initial Security Check Before writing any code: - Check: Will this handle credentials? → Apply codeguard-1-hardcoded-credentials +- Check: What security tags apply? → Load all rules with matching tags (e.g., "authentication", "web", "secrets") - Check: What language am I using? → Identify applicable language-specific rules -- Check: What security domains are involved? → Load relevant rule files ### 2. Code Generation While writing code: diff --git a/src/convert_to_ide_formats.py b/src/convert_to_ide_formats.py index 15e8b1c..9f7b2e9 100644 --- a/src/convert_to_ide_formats.py +++ b/src/convert_to_ide_formats.py @@ -65,43 +65,35 @@ def matches_tag_filter(rule_tags: list[str], filter_tags: list[str]) -> bool: return all(tag in rule_tags for tag in filter_tags) -def update_skill_md(language_to_rules: dict[str, list[str]], skill_path: Path) -> None: - """ - Update SKILL.md with language-to-rules mapping table. - - Args: - language_to_rules: Dictionary mapping languages to rule files - skill_path: Path to SKILL.md file - """ - table_lines = [ - "| Language | Rule Files to Apply |", - "|----------|---------------------|", - ] - - for language in sorted(language_to_rules.keys()): - rules = sorted(language_to_rules[language]) - rules_str = ", ".join(rules) - table_lines.append(f"| {language} | {rules_str} |") - +def _inject_mapping_table( + skill_path: Path, + mapping: dict[str, list[str]], + *, + key_header: str, + marker_name: str, +) -> None: + """Replace ```` in SKILL.md with a sorted + two-column markdown table built from ``mapping``. Missing markers raise.""" + rules_col = "Rule Files to Apply" + sep = f"|{'-' * (len(key_header) + 2)}|{'-' * (len(rules_col) + 2)}|" + table_lines = [f"| {key_header} | {rules_col} |", sep] + for key in sorted(mapping): + table_lines.append(f"| {key} | {', '.join(sorted(mapping[key]))} |") table = "\n".join(table_lines) - start_marker = "" - end_marker = "" - + start_marker = f"" + end_marker = f"" content = skill_path.read_text(encoding="utf-8") - if start_marker not in content or end_marker not in content: raise RuntimeError( - f"Invalid SKILL.md: language mappings section markers not found in {skill_path}" + f"Invalid SKILL.md: {marker_name} section markers not found in {skill_path}" ) start_idx = content.index(start_marker) end_idx = content.index(end_marker) + len(end_marker) - new_section = f"\n\n{table}\n\n" - updated_content = content[:start_idx] + new_section + content[end_idx:] - - skill_path.write_text(updated_content, encoding="utf-8") - print(f"Updated SKILL.md with language mappings") + updated = content[:start_idx] + f"\n\n{table}\n\n" + content[end_idx:] + skill_path.write_text(updated, encoding="utf-8") + print(f"Updated SKILL.md with {marker_name} table") def convert_rules( @@ -182,6 +174,7 @@ def convert_rules( results = {"success": [], "errors": [], "skipped": []} language_to_rules = defaultdict(list) + tag_to_rules = defaultdict(list) # Process each file for md_file in md_files: @@ -220,6 +213,9 @@ def convert_rules( for language in result.languages: language_to_rules[language].append(result.filename) + for tag in result.tags: + tag_to_rules[tag].append(result.filename) + except FileNotFoundError as e: error_msg = f"{md_file.name}: File not found - {e}" print(f"Error: {error_msg}") @@ -267,7 +263,18 @@ def convert_rules( ) output_skill_path.write_text(template_content, encoding="utf-8") - update_skill_md(language_to_rules, output_skill_path) + _inject_mapping_table( + output_skill_path, + language_to_rules, + key_header="Language", + marker_name="LANGUAGE_MAPPINGS", + ) + _inject_mapping_table( + output_skill_path, + tag_to_rules, + key_header="Security Context (Tag)", + marker_name="TAG_MAPPINGS", + ) for host_dir in SKILL_COPY_HOSTS: host_skill_dir = Path(output_dir) / host_dir / "skills" / "software-security" diff --git a/src/formats/agentskills.py b/src/formats/agentskills.py index e582990..7bc30cc 100644 --- a/src/formats/agentskills.py +++ b/src/formats/agentskills.py @@ -41,9 +41,9 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: """ Generate Agent Skills .md format. - Agent Skills should preserve the original YAML frontmatter - (description, languages, alwaysApply) so the rules remain complete - and can be referenced properly by AI coding agents. + Agent Skills preserves the original YAML frontmatter (description, + languages, alwaysApply, tags) so the rules remain complete and can + be referenced properly by AI coding agents. Args: rule: The processed rule to format @@ -70,4 +70,10 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: # Add alwaysApply yaml_lines.append(f"alwaysApply: {str(rule.always_apply).lower()}") + # Add tags as expanded YAML list (preserves the source format) + if rule.tags: + yaml_lines.append("tags:") + for tag in rule.tags: + yaml_lines.append(f"- {tag}") + return self._build_yaml_frontmatter(yaml_lines, rule.content) diff --git a/src/formats/antigravity.py b/src/formats/antigravity.py index 6361d14..2995a78 100644 --- a/src/formats/antigravity.py +++ b/src/formats/antigravity.py @@ -16,6 +16,7 @@ class AntigravityFormat(BaseFormat): - globs: (if trigger is 'glob') File matching patterns - description: Rule description - version: Rule version + - tags: (optional) List of categorization tags Rules use activation types (Always On or Glob) to determine when they apply, similar to Windsurf's implementation. @@ -70,4 +71,8 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: # Add version yaml_lines.append(f"version: {self.version}") + if rule.tags: + tags_str = ", ".join(rule.tags) + yaml_lines.append(f"tags: [{tags_str}]") + return self._build_yaml_frontmatter(yaml_lines, rule.content) diff --git a/src/formats/copilot.py b/src/formats/copilot.py index 9604320..aaf2dfe 100644 --- a/src/formats/copilot.py +++ b/src/formats/copilot.py @@ -13,8 +13,9 @@ class CopilotFormat(BaseFormat): Copilot uses .instructions.md files with YAML frontmatter containing: - applyTo: File matching patterns - - title: Rule title/description + - description: Rule description - version: Rule version + - tags: (optional) List of categorization tags """ def get_format_name(self) -> str: @@ -53,4 +54,8 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: # Add version yaml_lines.append(f"version: {self.version}") + if rule.tags: + tags_str = ", ".join(rule.tags) + yaml_lines.append(f"tags: [{tags_str}]") + return self._build_yaml_frontmatter(yaml_lines, rule.content) diff --git a/src/formats/cursor.py b/src/formats/cursor.py index 04f8dd9..30a76c5 100644 --- a/src/formats/cursor.py +++ b/src/formats/cursor.py @@ -16,6 +16,7 @@ class CursorFormat(BaseFormat): - globs: File matching patterns - version: Rule version - alwaysApply: (optional) Whether to apply to all files + - tags: (optional) List of categorization tags """ def get_format_name(self) -> str: @@ -56,4 +57,8 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: if rule.always_apply: yaml_lines.append("alwaysApply: true") + if rule.tags: + tags_str = ", ".join(rule.tags) + yaml_lines.append(f"tags: [{tags_str}]") + return self._build_yaml_frontmatter(yaml_lines, rule.content) diff --git a/src/formats/windsurf.py b/src/formats/windsurf.py index 786019d..ab5938c 100644 --- a/src/formats/windsurf.py +++ b/src/formats/windsurf.py @@ -16,6 +16,7 @@ class WindsurfFormat(BaseFormat): - globs: (if trigger is 'glob') File matching patterns - title: Rule title/description - version: Rule version + - tags: (optional) List of categorization tags """ def get_format_name(self) -> str: @@ -58,4 +59,8 @@ def generate(self, rule: ProcessedRule, globs: str) -> str: # Add version yaml_lines.append(f"version: {self.version}") + if rule.tags: + tags_str = ", ".join(rule.tags) + yaml_lines.append(f"tags: [{tags_str}]") + return self._build_yaml_frontmatter(yaml_lines, rule.content)