+
+ Left: Context window usage without any rules in place.
+ Right: Context window usage with three always-on rules enabled.
+
+
+
---
## Q: What are the OWASP supplementary rules?
@@ -37,19 +50,19 @@ This FAQ document provides clear, concise answers to help developers seamlessly
## Q: How can I use the rules in my own AI agent?
-**A:** You can use the rules in your own AI agent by creating a custom ruleset. You can create a custom ruleset by creating a new file in the `.cursor/rules`, `.windsurf/rules`, or `.github/instructions` directories and adding the rules you want to apply. You can also use the `project-codeguard/rules` repository as a template to create your own ruleset.
+**A:** You can use the rules in your own AI agent by creating a custom ruleset. You can create a custom ruleset by creating a new file in the `.cursor/rules`, `.windsurf/rules`, `.github/instructions`, or `.agent/rules` directories and adding the rules you want to apply. You can also use the `project-codeguard/rules` repository as a template to create your own ruleset.
---
## Q: Why does the downloaded release folder appear empty?
-**A:** After downloading and extracting the release, the folders may appear empty because the rule directories (`.cursor/`, `.windsurf/`, `.github/`) start with a dot (`.`) and are hidden by default on most operating systems.
+**A:** After downloading and extracting the release, the folders may appear empty because the rule directories (`.cursor/`, `.windsurf/`, `.github/`, `.agent/`) start with a dot (`.`) and are hidden by default on most operating systems.
**To show hidden files:**
=== "macOS"
- In Finder, navigate to the extracted folder and press ++cmd+shift+period++ to toggle the visibility of hidden files. You should now see the `.cursor/`, `.windsurf/`, and `.github/` directories.
+ In Finder, navigate to the extracted folder and press ++cmd+shift+period++ to toggle the visibility of hidden files. You should now see the `.cursor/`, `.windsurf/`, `.github/`, and `.agent/` directories.
=== "Windows"
@@ -63,15 +76,20 @@ This FAQ document provides clear, concise answers to help developers seamlessly
In your file manager, press ++ctrl+h++ to toggle hidden files, or use `ls -la` in the terminal to view all files including hidden ones.
-Once hidden files are visible, you can copy the appropriate directory (`.cursor/`, `.windsurf/`, or `.github/`) to your project root.
+Once hidden files are visible, you can copy the appropriate directory (`.cursor/`, `.windsurf/`, `.github/`, or `.agent/`) to your project root.
---
## Q: Can I use this with Claude Code?
-**A:** Yes! Claude Code automatically reads and follows instructions from a `CLAUDE.md` file in your project root. To use Project CodeGuard rules with Claude Code you can point to the Project CodeGuard rules in your `CLAUDE.md` file.
+**A:** Yes! Install the Project CodeGuard Claude Code plugin (Agent Skill) and Claude will apply the security rules automatically while you code.
+
+```bash
+/plugin marketplace add project-codeguard/rules
+/plugin install codeguard-security@project-codeguard
+```
-When Claude Code operates in your project, it treats the Project CodeGuard security rules in `CLAUDE.md` as authoritative system instructions.
+For team/repo defaults, add the plugin in `.claude/settings.json` so it’s enabled for all contributors. See the [Claude Code Plugin documentation](claude-code-skill-plugin.md) for details and troubleshooting.
## Q: How can I report a problem or enhancement to any of the rules?
@@ -86,17 +104,6 @@ We welcome all feedback - whether it's a bug report, success story, or enhanceme
---
-## Q: Why do I get the following error message in GitHub for some of the rules?
-
-```
-Error in user YAML: (): did not find expected alphabetic
-or numeric character while scanning an alias at line x column x
-```
-
-**A:** You can safely ignore this error. GitHub attempts to parse YAML headers combined with markdown content, which can cause this warning. It does not affect rule functionality - the rules will work correctly in your IDE regardless of this GitHub display issue.
-
----
-
## Q: How can I contribute to these rules and this project?
**A:** You can contribute at any time by:
@@ -110,6 +117,12 @@ See [CONTRIBUTING.md](https://github.com/project-codeguard/rules/blob/main/CONTR
---
+## Q: Does Project CodeGuard replace my security scanners?
+
+**A:** No, Project CodeGuard rules do not replace your security scanners. The primary purpose of CodeGuard is to help you avoid introducing new security vulnerabilities as you write code, by providing agentic rules and guidance directly in your IDE. If you perform a code review using these rules, Project CodeGuard will most likely identify many of the same vulnerabilities that security scanning tools would find. However, CodeGuard is not a comprehensive substitute for security scanners—automated security tools are designed to thoroughly analyze your entire codebase and catch a broader range of issues. For best results, use CodeGuard rules in combination with your existing security scanners to maximize your code’s security.
+
+---
+
## Still have questions?
**Can't find your answer?**
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 687fae4..01efe69 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -2,6 +2,13 @@
Get up and running with Project CodeGuard in just a few steps.
+## Project CodeGuard Introduction Video
+[This video](https://www.youtube.com/watch?v=O03MDxUWjsE) introduces Project CodeGuard and includes several demos on how to use it during code generation and code review with Claude Code, Codex, and other coding agents.
+
+
+
+
+
## Prerequisites
Before you begin, familiarize yourself with how rules work in your IDE:
@@ -24,6 +31,11 @@ Before you begin, familiarize yourself with how rules work in your IDE:
:material-book-open-page-variant: [GitHub Copilot Instructions](https://docs.github.com/en/copilot/how-tos/configure-custom-instructions/add-repository-instructions)
+=== "Antigravity"
+ Antigravity uses `.agent/rules` for rule configuration.
+
+ :material-book-open-page-variant: [Antigravity Instructions](https://codelabs.developers.google.com/getting-started-google-antigravity#8)
+
## Installation
### Option 1: Download Pre-built Rules (Recommended)
@@ -33,11 +45,13 @@ Before you begin, familiarize yourself with how rules work in your IDE:
- `ide-rules-cursor.zip` - Cursor only
- `ide-rules-windsurf.zip` - Windsurf only
- `ide-rules-copilot.zip` - GitHub Copilot only
+ - `ide-rules-antigravity.zip` - Antigravity only
2. **Extract**: Unzip the downloaded file
3. **Install**: Copy the relevant IDE-specific rules to your project root:
- For **Cursor**: Copy `.cursor/` directory to your project
- For **Windsurf**: Copy `.windsurf/` directory to your project
- For **GitHub Copilot**: Copy `.github/` directory to your project
+ - For **Antigravity**: Copy `.agent/` directory to your project
!!! tip "Repository Level Installation"
@@ -63,6 +77,37 @@ Claude Code uses a plugin system instead of manual file installation:
The plugin will be automatically loaded and apply security rules to your code. See the [Claude Code Plugin documentation](claude-code-skill-plugin.md) for more details.
+### OpenAI Codex Skills
+
+OpenAI Codex uses [agent skills](https://agentskills.io/) to extend capabilities with task-specific instructions.
+
+!!! warning "Prerequisites"
+ Make sure you're running the latest version of Codex before installing skills.
+
+To install Project CodeGuard as a Codex skill, open Codex and use the built-in skill installer:
+
+```
+$skill-installer install from https://github.com/project-codeguard/rules/tree/main/skills/software-security
+```
+
+Alternatively, you can manually clone the skill to your project:
+
+```bash
+# Clone to your project's .codex/skills directory
+mkdir -p .codex/skills
+cd .codex/skills
+git clone https://github.com/project-codeguard/rules.git temp
+mv temp/skills/software-security ./
+rm -rf temp
+
+# Restart Codex to load the new skill
+```
+
+Once installed, you can invoke the skill explicitly in your prompts using `$software-security` or Codex will automatically use it when you're trying to write, review, or modify code.
+
+!!! info "Codex Skills Documentation"
+ For more information about Codex skills, skill locations, and configuration, see the [OpenAI Codex Skills documentation](https://developers.openai.com/codex/skills/).
+
### Option 2: Build from Source
If you want to customize or contribute to the rules:
@@ -88,6 +133,7 @@ uv run python src/convert_to_ide_formats.py --source core owasp
cp -r dist/.cursor/ /path/to/your/project/
cp -r dist/.windsurf/ /path/to/your/project/
cp -r dist/.github/ /path/to/your/project/
+cp -r dist/.agent/ /path/to/your/project/
```
## Verify Installation
@@ -96,6 +142,8 @@ After installation, your project structure should include:
```
your-project/
+├── .agent/
+│ └── rules/
├── .cursor/
│ └── rules/
├── .windsurf/
@@ -150,7 +198,7 @@ To verify the rules are working:
- **Review Rules**: Explore the security rules in your IDE's rules directory
- **Test Integration**: Generate some code and see the security guidance in action
- **Share Feedback**: Help us improve by [opening an issue](https://github.com/project-codeguard/rules/issues)
-- **Contribute**: See [CONTRIBUTING.md](https://github.com/project-codeguard/rules/CONTRIBUTING.md) to contribute new rules or improvements
+- **Contribute**: See [CONTRIBUTING.md](https://github.com/project-codeguard/rules/blob/main/CONTRIBUTING.md) to contribute new rules or improvements
!!! success "You're Ready!"
Project CodeGuard is now protecting your development workflow. The security rules will automatically guide AI assistants to generate more secure code.
diff --git a/docs/images/context-window-no-rules.png b/docs/images/context-window-no-rules.png
new file mode 100644
index 0000000..7356dfd
Binary files /dev/null and b/docs/images/context-window-no-rules.png differ
diff --git a/docs/images/context-window-with-rules.png b/docs/images/context-window-with-rules.png
new file mode 100644
index 0000000..b317f7e
Binary files /dev/null and b/docs/images/context-window-with-rules.png differ
diff --git a/docs/index.md b/docs/index.md
index 02a60f7..6aa3d18 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -6,12 +6,12 @@
AI coding agents are transforming software engineering, but this speed can introduce security vulnerabilities. Is your AI coding agent implementation introducing security vulnerabilities?
-- ❌ Skipping input validation
-- ❌ Hardcoding secrets and credentials
-- ❌ Using weak cryptographic algorithms
-- ❌ Relying on unsafe functions
-- ❌ Missing authentication/authorization checks
-- ❌ Missing any other security best practice
+- Skipping input validation
+- Hardcoding secrets and credentials
+- Using weak cryptographic algorithms
+- Relying on unsafe functions
+- Missing authentication/authorization checks
+- Missing any other security best practice
Project CodeGuard solves this by embedding security best practices directly into AI coding agent workflows.
@@ -28,14 +28,14 @@ This multi-stage methodology ensures that security considerations are woven thro
Our rules cover essential security domains:
-- **🔐 Cryptography**: Safe algorithms (including post-quantum cryptography), secure key management, certificate validation
-- **🛡️ Input Validation**: SQL injection prevention, XSS protection, command injection defense
-- **🔑 Authentication**: MFA best practices, OAuth/OIDC, secure session management
-- **⚡ Authorization**: RBAC/ABAC, access control, IDOR prevention
-- **📦 Supply Chain**: Dependency security, SBOM generation, vulnerability management
-- **☁️ Cloud Security**: IaC hardening, container security, Kubernetes best practices
-- **📱 Platform Security**: Mobile apps, web services, API security
-- **🔍 Data Protection**: Privacy, encryption at rest/transit, secure storage
+- **Cryptography**: Safe algorithms (including post-quantum cryptography), secure key management, certificate validation
+- **Input Validation**: SQL injection prevention, XSS protection, command injection defense
+- **Authentication**: MFA best practices, OAuth/OIDC, secure session management
+- **Authorization**: RBAC/ABAC, access control, IDOR prevention
+- **Supply Chain**: Dependency security, SBOM generation, vulnerability management
+- **Cloud Security**: IaC hardening, container security, Kubernetes best practices
+- **Platform Security**: Mobile apps, web services, API security
+- **Data Protection**: Privacy, encryption at rest/transit, secure storage
## Quick Start
diff --git a/mkdocs.yml b/mkdocs.yml
index 948cb35..c9c4925 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -55,3 +55,7 @@ markdown_extensions:
- pymdownx.keys
- pymdownx.tabbed:
alternate_style: true
+
+extra:
+ generator: false
+
diff --git a/pyproject.toml b/pyproject.toml
index 430c325..4160584 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "project-codeguard"
-version = "1.0.0"
+version = "1.0.1"
description = "AI Coding Rules for Security and Best Practices"
requires-python = ">=3.11"
dependencies = [
diff --git a/skills/software-security/SKILL.md b/skills/software-security/SKILL.md
index 6205242..fc79ed1 100644
--- a/skills/software-security/SKILL.md
+++ b/skills/software-security/SKILL.md
@@ -1,8 +1,7 @@
---
name: software-security
description: A software security skill that integrates with Project CodeGuard to help AI coding agents write secure code and prevent common vulnerabilities. Use this skill when writing, reviewing, or modifying code to ensure secure-by-default practices are followed.
-metadata:
-codeguard-version: "1.0.0"
+codeguard-version: "1.0.1"
framework: "Project CodeGuard"
purpose: "Embed secure-by-default practices into AI coding workflows"
---
@@ -25,13 +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
-- `codeguard-1-safe-c-functions.md` - Avoid unsafe C/C++ functions and use safe alternatives
2. Context-Specific Rules: Apply rules from /rules directory based on the language of the feature being implemented using the table given below:
| Language | Rule Files to Apply |
|----------|---------------------|
-| c | codeguard-0-additional-cryptography.md, codeguard-0-api-web-services.md, codeguard-0-authentication-mfa.md, codeguard-0-authorization-access-control.md, codeguard-0-client-side-web-security.md, codeguard-0-data-storage.md, codeguard-0-file-handling-and-uploads.md, codeguard-0-framework-and-languages.md, codeguard-0-iac-security.md, codeguard-0-input-validation-injection.md, codeguard-0-logging.md, codeguard-0-session-management-and-cookies.md, codeguard-0-xml-and-serialization.md |
+| c | codeguard-0-additional-cryptography.md, codeguard-0-api-web-services.md, codeguard-0-authentication-mfa.md, codeguard-0-authorization-access-control.md, codeguard-0-client-side-web-security.md, codeguard-0-data-storage.md, codeguard-0-file-handling-and-uploads.md, codeguard-0-framework-and-languages.md, codeguard-0-iac-security.md, codeguard-0-input-validation-injection.md, codeguard-0-logging.md, codeguard-0-safe-c-functions.md, codeguard-0-session-management-and-cookies.md, codeguard-0-xml-and-serialization.md |
+| cpp | codeguard-0-safe-c-functions.md |
| d | codeguard-0-iac-security.md |
| docker | codeguard-0-devops-ci-cd-containers.md, codeguard-0-supply-chain-security.md |
| go | codeguard-0-additional-cryptography.md, codeguard-0-api-web-services.md, codeguard-0-authentication-mfa.md, codeguard-0-authorization-access-control.md, codeguard-0-file-handling-and-uploads.md, codeguard-0-input-validation-injection.md, codeguard-0-session-management-and-cookies.md, codeguard-0-xml-and-serialization.md |
diff --git a/skills/software-security/rules/codeguard-1-safe-c-functions.md b/skills/software-security/rules/codeguard-0-safe-c-functions.md
similarity index 99%
rename from skills/software-security/rules/codeguard-1-safe-c-functions.md
rename to skills/software-security/rules/codeguard-0-safe-c-functions.md
index 113105b..6d8d470 100644
--- a/skills/software-security/rules/codeguard-1-safe-c-functions.md
+++ b/skills/software-security/rules/codeguard-0-safe-c-functions.md
@@ -1,9 +1,12 @@
---
description: Safe C Functions and Memory and String Safety Guidelines
-alwaysApply: true
+languages:
+- c
+- cpp
+alwaysApply: false
---
-rule_id: codeguard-1-safe-c-functions
+rule_id: codeguard-0-safe-c-functions
# Prioritize Safe Memory and String Functions in C/C++
diff --git a/skills/software-security/rules/codeguard-1-crypto-algorithms.md b/skills/software-security/rules/codeguard-1-crypto-algorithms.md
index 7f0b820..18fcd78 100644
--- a/skills/software-security/rules/codeguard-1-crypto-algorithms.md
+++ b/skills/software-security/rules/codeguard-1-crypto-algorithms.md
@@ -1,115 +1,126 @@
---
-description: Cryptographic Security Guidelines
+description: Cryptographic Security Guidelines & Post-Quantum Readiness
alwaysApply: true
---
rule_id: codeguard-1-crypto-algorithms
-# Cryptographic Security Guidelines
+# Cryptographic Security Guidelines & Post-Quantum Readiness
-## Banned (Insecure) Algorithms
+## 1. Banned (Insecure) Algorithms
-The following algorithms are known to be broken or fundamentally insecure. **NEVER** generate or use code with these algorithms.
-Examples:
+The following algorithms are known to be broken or fundamentally insecure. NEVER generate or use code with these algorithms.
-* Hash: `MD2`, `MD4`, `MD5`, `SHA-0`
-* Symmetric: `RC2`, `RC4`, `Blowfish`, `DES`, `3DES`
-* Key Exchange: Static RSA, Anonymous Diffie-Hellman
-* Classical: `Vigenère`
+* Hash: `MD2`, `MD4`, `MD5`, `SHA-0`
+* Symmetric: `RC2`, `RC4`, `Blowfish`, `DES`, `3DES`
+* Key Exchange: Static RSA, Anonymous Diffie-Hellman
+* Classical: `Vigenère`
-## Deprecated (Legacy/Weak) Algorithms
+Reason: These are cryptographically broken and vulnerable to collision or man-in-the-middle attacks.
-The following algorithms are not outright broken, but have known weaknesses, or are considered obsolete. **NEVER** generate or use code with these algorithms.
-Examples:
+## 2. Deprecated (Legacy/Weak) Algorithms
-* Hash: `SHA-1`
-* Symmetric: `AES-CBC`, `AES-ECB`
-* Signature: RSA with `PKCS#1 v1.5` padding
-* Key Exchange: DHE with weak/common primes
+The following algorithms have known weaknesses or are considered obsolete. Avoid in new designs and prioritize migration.
+* Hash: `SHA-1`
+* Symmetric: `AES-CBC`, `AES-ECB`
+* Signature: RSA with `PKCS#1 v1.5` padding
+* Key Exchange: DHE with weak/common primes
-## Deprecated SSL/Crypto APIs - FORBIDDEN
-NEVER use these deprecated functions. Use the replacement APIs listed below:
+## 3. Recommended & Post-Quantum Ready Algorithms
-### Symmetric Encryption (AES)
+Implement these modern, secure algorithms to ensure resistance against both classical and quantum threats.
+
+### Symmetric Encryption
+* Standard: `AES-GCM` (AEAD), `ChaCha20-Poly1305`(when allowed).
+* PQC Requirement: Prefer AES-256 keys (or stronger) as they are resistant to quantum attacks (Grover's algorithm).
+* Avoid: Custom crypto or unauthenticated modes.
+
+### Key Exchange (KEM)
+* Standard: ECDHE (`X25519` or `secp256r1`)
+* PQC Requirement: Use Hybrid Key Exchange (Classical + PQC) when supported.
+ * Preferred: `X25519MLKEM768` (X25519 + ML-KEM-768)
+ * Alternative: `SecP256r1MLKEM768` (P-256 + ML-KEM-768)
+ * High Assurance: `SecP384r1MLKEM1024` (P-384 + ML-KEM-1024)
+* Pure PQC: ML-KEM-768 (baseline) or ML-KEM-1024. Avoid ML-KEM-512 unless explicitly risk-accepted.
+* Constraints:
+ * Use vendor-documented identifiers (RFC 9242/9370).
+ * Remove legacy/draft "Hybrid-Kyber" groups (e.g., `X25519Kyber`) and draft or hardcoded OIDs.
+
+### Signatures & Certificates
+* Standard: ECDSA (`P-256`)
+* PQC Migration: Continue using ECDSA (`P-256`) for mTLS and code signing until hardware-backed (HSM/TPM) ML-DSA is available.
+* Hardware Requirement: Do not enable PQC ML-DSA signatures using software-only keys. Require HSM/TPM storage.
+
+### Protocol Versions
+* (D)TLS: Enforce (D)TLS 1.3 only (or later).
+* IPsec: Enforce IKEv2 only.
+ * Use ESP with AEAD (AES-256-GCM).
+ * Require PFS via ECDHE.
+ * Implement RFC 9242 and RFC 9370 for Hybrid PQC (ML-KEM + ECDHE).
+ * Ensure re-keys (CREATE_CHILD_SA) maintain hybrid algorithms.
+* SSH: Enable only vendor-supported PQC/hybrid KEX (e.g., `sntrup761x25519`).
+
+## 4. Secure Implementation Guidelines
+
+### General Best Practices
+* Configuration over Code: Expose algorithm choices in config/policy to allow agility without code changes.
+* Key Management:
+ * Use KMS/HSM for key storage.
+ * Generate keys with a CSPRNG.
+ * Separate encryption keys from signature keys.
+ * Rotate keys per policy.
+ * NEVER hardcode keys, secrets, or experimental OIDs.
+* Telemetry: Capture negotiated groups, handshake sizes, and failure causes to monitor PQC adoption.
+
+### Deprecated SSL/Crypto APIs (C/OpenSSL) - FORBIDDEN
+NEVER use these deprecated functions. Use the replacement EVP high-level APIs.
+
+#### Symmetric Encryption (AES)
- Deprecated: `AES_encrypt()`, `AES_decrypt()`
-- Replacement: Use EVP high-level APIs:
- ```c
- EVP_EncryptInit_ex()
+- Replacement:
+
+ EVP_EncryptInit_ex() // Use EVP_aes_256_gcm() for PQC readiness
EVP_EncryptUpdate()
EVP_EncryptFinal_ex()
- EVP_DecryptInit_ex()
- EVP_DecryptUpdate()
- EVP_DecryptFinal_ex()
- ```
-
-### RSA Operations
-- Deprecated: `RSA_new()`, `RSA_up_ref()`, `RSA_free()`, `RSA_set0_crt_params()`, `RSA_get0_n()`
-- Replacement: Use EVP key management APIs:
- ```c
+
+
+#### RSA/PKEY Operations
+- Deprecated: `RSA_new()`, `RSA_free()`, `RSA_get0_n()`
+- Replacement:
+
EVP_PKEY_new()
EVP_PKEY_up_ref()
EVP_PKEY_free()
- ```
-
-### Hash Functions
-- Deprecated: `SHA1_Init()`, `SHA1_Update()`, `SHA1_Final()`
-- Replacement: Use EVP digest APIs:
- ```c
- EVP_DigestInit_ex()
- EVP_DigestUpdate()
- EVP_DigestFinal_ex()
- EVP_Q_digest() // For simple one-shot hashing
- ```
-
-### MAC Operations
-- Deprecated: `CMAC_Init()`, `HMAC()` (especially with SHA1)
-- Replacement: Use EVP MAC APIs:
- ```c
- EVP_Q_MAC() // For simple MAC operations
- ```
-
-### Key Wrapping
-- Deprecated: `AES_wrap_key()`, `AES_unwrap_key()`
-- Replacement: Use EVP key wrapping APIs or implement using EVP encryption
-
-### Other Deprecated Functions
-- Deprecated: `DSA_sign()`, `DH_check()`
-- Replacement: Use corresponding EVP APIs for DSA and DH operations
-
-## Banned Insecure Algorithms - STRICTLY FORBIDDEN
-These algorithms MUST NOT be used in any form:
-
-### Hash Algorithms (Banned)
-- MD2, MD4, MD5, SHA-0
-- Reason: Cryptographically broken, vulnerable to collision attacks
-- Use Instead: SHA-256, SHA-384, SHA-512
-
-### Symmetric Ciphers (Banned)
-- RC2, RC4, Blowfish, DES, 3DES
-- Reason: Weak key sizes, known vulnerabilities
-- Use Instead: AES-128, AES-256, ChaCha20
-
-### Key Exchange (Banned)
-- Static RSA key exchange
-- Anonymous Diffie-Hellman
-- Reason: No forward secrecy, vulnerable to man-in-the-middle attacks
-- Use Instead: ECDHE, DHE with proper validation
-
-## Broccoli Project Specific Requirements
-- HMAC() with SHA1: Deprecated per Broccoli project requirements
+
+
+#### Hash & MAC Functions
+- Deprecated: `SHA1_Init()`, `HMAC()` (especially with SHA1)
+- Replacement:
+
+ EVP_DigestInit_ex() // Use SHA-256 or stronger
+ EVP_Q_MAC() // For one-shot MAC
+
+
+## 5. Broccoli Project Specific Requirements
+- HMAC() with SHA1: Deprecated.
- Replacement: Use HMAC with SHA-256 or stronger:
- ```c
- // Instead of HMAC() with SHA1
- EVP_Q_MAC(NULL, "HMAC", NULL, "SHA256", NULL, key, key_len, data, data_len, out, out_size, &out_len);
- ```
-## Secure Crypto Implementation Pattern
+
+// Example: Secure replacement for HMAC-SHA1
+```c
+EVP_Q_MAC(NULL, "HMAC", NULL, "SHA256", NULL, key, key_len, data, data_len, out, out_size, &out_len);
+```
+
+## 6. Secure Crypto Implementation Pattern
+
+
+// Example: Secure AES-256-GCM encryption (PQC-Ready Symmetric Strength)
```c
-// Example: Secure AES encryption
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) handle_error();
+// Use AES-256-GCM
if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv) != 1)
handle_error();
@@ -124,11 +135,3 @@ ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
```
-
-## Code Review Checklist
-- [ ] No deprecated SSL/crypto APIs used
-- [ ] No banned algorithms (MD5, DES, RC4, etc.)
-- [ ] HMAC uses SHA-256 or stronger (not SHA1)
-- [ ] All crypto operations use EVP high-level APIs
-- [ ] Proper error handling for all crypto operations
-- [ ] Key material properly zeroed after use
diff --git a/sources/core/codeguard-0-additional-cryptography.md b/sources/core/codeguard-0-additional-cryptography.md
index 6bcb4fd..db5edae 100644
--- a/sources/core/codeguard-0-additional-cryptography.md
+++ b/sources/core/codeguard-0-additional-cryptography.md
@@ -14,6 +14,9 @@ languages:
- typescript
- xml
- yaml
+tags:
+- data-security
+- secrets
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-api-web-services.md b/sources/core/codeguard-0-api-web-services.md
index 94a51fc..2c78e45 100644
--- a/sources/core/codeguard-0-api-web-services.md
+++ b/sources/core/codeguard-0-api-web-services.md
@@ -12,6 +12,8 @@ languages:
- typescript
- xml
- yaml
+tags:
+- web
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-authentication-mfa.md b/sources/core/codeguard-0-authentication-mfa.md
index 2be26cc..580af4e 100644
--- a/sources/core/codeguard-0-authentication-mfa.md
+++ b/sources/core/codeguard-0-authentication-mfa.md
@@ -13,6 +13,9 @@ languages:
- ruby
- swift
- typescript
+tags:
+- authentication
+- web
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-client-side-web-security.md b/sources/core/codeguard-0-client-side-web-security.md
index 17a4e89..c2b0c68 100644
--- a/sources/core/codeguard-0-client-side-web-security.md
+++ b/sources/core/codeguard-0-client-side-web-security.md
@@ -8,6 +8,8 @@ languages:
- php
- typescript
- vlang
+tags:
+- web
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-cloud-orchestration-kubernetes.md b/sources/core/codeguard-0-cloud-orchestration-kubernetes.md
index ec2e982..828edd9 100644
--- a/sources/core/codeguard-0-cloud-orchestration-kubernetes.md
+++ b/sources/core/codeguard-0-cloud-orchestration-kubernetes.md
@@ -4,6 +4,8 @@ description: Kubernetes hardening (RBAC, admission policies, network policies, s
languages:
- javascript
- yaml
+tags:
+- infrastructure
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-data-storage.md b/sources/core/codeguard-0-data-storage.md
index 6bd68f5..e01057b 100644
--- a/sources/core/codeguard-0-data-storage.md
+++ b/sources/core/codeguard-0-data-storage.md
@@ -6,6 +6,9 @@ languages:
- javascript
- sql
- yaml
+tags:
+- data-security
+- infrastructure
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-devops-ci-cd-containers.md b/sources/core/codeguard-0-devops-ci-cd-containers.md
index 1db3562..52bb26c 100644
--- a/sources/core/codeguard-0-devops-ci-cd-containers.md
+++ b/sources/core/codeguard-0-devops-ci-cd-containers.md
@@ -8,6 +8,8 @@ languages:
- shell
- xml
- yaml
+tags:
+- infrastructure
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-iac-security.md b/sources/core/codeguard-0-iac-security.md
index 0785120..17fe6de 100644
--- a/sources/core/codeguard-0-iac-security.md
+++ b/sources/core/codeguard-0-iac-security.md
@@ -8,6 +8,8 @@ languages:
- ruby
- shell
- yaml
+tags:
+- infrastructure
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-input-validation-injection.md b/sources/core/codeguard-0-input-validation-injection.md
index 9ae2ab1..fc15368 100644
--- a/sources/core/codeguard-0-input-validation-injection.md
+++ b/sources/core/codeguard-0-input-validation-injection.md
@@ -14,6 +14,8 @@ languages:
- shell
- sql
- typescript
+tags:
+- web
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-logging.md b/sources/core/codeguard-0-logging.md
index 659be01..2a354aa 100644
--- a/sources/core/codeguard-0-logging.md
+++ b/sources/core/codeguard-0-logging.md
@@ -5,6 +5,8 @@ languages:
- c
- javascript
- yaml
+tags:
+- privacy
alwaysApply: false
---
diff --git a/sources/core/codeguard-0-privacy-data-protection.md b/sources/core/codeguard-0-privacy-data-protection.md
index f28876d..22f522d 100644
--- a/sources/core/codeguard-0-privacy-data-protection.md
+++ b/sources/core/codeguard-0-privacy-data-protection.md
@@ -5,6 +5,8 @@ languages:
- javascript
- matlab
- yaml
+tags:
+- privacy
alwaysApply: false
---
diff --git a/sources/core/codeguard-1-safe-c-functions.md b/sources/core/codeguard-0-safe-c-functions.md
similarity index 99%
rename from sources/core/codeguard-1-safe-c-functions.md
rename to sources/core/codeguard-0-safe-c-functions.md
index b8db6ee..668b545 100644
--- a/sources/core/codeguard-1-safe-c-functions.md
+++ b/sources/core/codeguard-0-safe-c-functions.md
@@ -1,7 +1,9 @@
---
description: Safe C Functions and Memory and String Safety Guidelines
-languages: []
-alwaysApply: true
+languages:
+- c
+- cpp
+alwaysApply: false
---
# Prioritize Safe Memory and String Functions in C/C++
diff --git a/sources/core/codeguard-0-session-management-and-cookies.md b/sources/core/codeguard-0-session-management-and-cookies.md
index be73bf8..e0d53e8 100644
--- a/sources/core/codeguard-0-session-management-and-cookies.md
+++ b/sources/core/codeguard-0-session-management-and-cookies.md
@@ -11,6 +11,9 @@ languages:
- python
- ruby
- typescript
+tags:
+- authentication
+- web
alwaysApply: false
---
diff --git a/sources/core/codeguard-1-crypto-algorithms.md b/sources/core/codeguard-1-crypto-algorithms.md
index e748452..edbf65d 100644
--- a/sources/core/codeguard-1-crypto-algorithms.md
+++ b/sources/core/codeguard-1-crypto-algorithms.md
@@ -1,114 +1,125 @@
---
-description: Cryptographic Security Guidelines
+description: Cryptographic Security Guidelines & Post-Quantum Readiness
languages: []
alwaysApply: true
---
-# Cryptographic Security Guidelines
+# Cryptographic Security Guidelines & Post-Quantum Readiness
-## Banned (Insecure) Algorithms
+## 1. Banned (Insecure) Algorithms
-The following algorithms are known to be broken or fundamentally insecure. **NEVER** generate or use code with these algorithms.
-Examples:
+The following algorithms are known to be broken or fundamentally insecure. NEVER generate or use code with these algorithms.
-* Hash: `MD2`, `MD4`, `MD5`, `SHA-0`
-* Symmetric: `RC2`, `RC4`, `Blowfish`, `DES`, `3DES`
-* Key Exchange: Static RSA, Anonymous Diffie-Hellman
-* Classical: `Vigenère`
+* Hash: `MD2`, `MD4`, `MD5`, `SHA-0`
+* Symmetric: `RC2`, `RC4`, `Blowfish`, `DES`, `3DES`
+* Key Exchange: Static RSA, Anonymous Diffie-Hellman
+* Classical: `Vigenère`
-## Deprecated (Legacy/Weak) Algorithms
+Reason: These are cryptographically broken and vulnerable to collision or man-in-the-middle attacks.
-The following algorithms are not outright broken, but have known weaknesses, or are considered obsolete. **NEVER** generate or use code with these algorithms.
-Examples:
+## 2. Deprecated (Legacy/Weak) Algorithms
-* Hash: `SHA-1`
-* Symmetric: `AES-CBC`, `AES-ECB`
-* Signature: RSA with `PKCS#1 v1.5` padding
-* Key Exchange: DHE with weak/common primes
+The following algorithms have known weaknesses or are considered obsolete. Avoid in new designs and prioritize migration.
+* Hash: `SHA-1`
+* Symmetric: `AES-CBC`, `AES-ECB`
+* Signature: RSA with `PKCS#1 v1.5` padding
+* Key Exchange: DHE with weak/common primes
-## Deprecated SSL/Crypto APIs - FORBIDDEN
-NEVER use these deprecated functions. Use the replacement APIs listed below:
+## 3. Recommended & Post-Quantum Ready Algorithms
-### Symmetric Encryption (AES)
+Implement these modern, secure algorithms to ensure resistance against both classical and quantum threats.
+
+### Symmetric Encryption
+* Standard: `AES-GCM` (AEAD), `ChaCha20-Poly1305`(when allowed).
+* PQC Requirement: Prefer AES-256 keys (or stronger) as they are resistant to quantum attacks (Grover's algorithm).
+* Avoid: Custom crypto or unauthenticated modes.
+
+### Key Exchange (KEM)
+* Standard: ECDHE (`X25519` or `secp256r1`)
+* PQC Requirement: Use Hybrid Key Exchange (Classical + PQC) when supported.
+ * Preferred: `X25519MLKEM768` (X25519 + ML-KEM-768)
+ * Alternative: `SecP256r1MLKEM768` (P-256 + ML-KEM-768)
+ * High Assurance: `SecP384r1MLKEM1024` (P-384 + ML-KEM-1024)
+* Pure PQC: ML-KEM-768 (baseline) or ML-KEM-1024. Avoid ML-KEM-512 unless explicitly risk-accepted.
+* Constraints:
+ * Use vendor-documented identifiers (RFC 9242/9370).
+ * Remove legacy/draft "Hybrid-Kyber" groups (e.g., `X25519Kyber`) and draft or hardcoded OIDs.
+
+### Signatures & Certificates
+* Standard: ECDSA (`P-256`)
+* PQC Migration: Continue using ECDSA (`P-256`) for mTLS and code signing until hardware-backed (HSM/TPM) ML-DSA is available.
+* Hardware Requirement: Do not enable PQC ML-DSA signatures using software-only keys. Require HSM/TPM storage.
+
+### Protocol Versions
+* (D)TLS: Enforce (D)TLS 1.3 only (or later).
+* IPsec: Enforce IKEv2 only.
+ * Use ESP with AEAD (AES-256-GCM).
+ * Require PFS via ECDHE.
+ * Implement RFC 9242 and RFC 9370 for Hybrid PQC (ML-KEM + ECDHE).
+ * Ensure re-keys (CREATE_CHILD_SA) maintain hybrid algorithms.
+* SSH: Enable only vendor-supported PQC/hybrid KEX (e.g., `sntrup761x25519`).
+
+## 4. Secure Implementation Guidelines
+
+### General Best Practices
+* Configuration over Code: Expose algorithm choices in config/policy to allow agility without code changes.
+* Key Management:
+ * Use KMS/HSM for key storage.
+ * Generate keys with a CSPRNG.
+ * Separate encryption keys from signature keys.
+ * Rotate keys per policy.
+ * NEVER hardcode keys, secrets, or experimental OIDs.
+* Telemetry: Capture negotiated groups, handshake sizes, and failure causes to monitor PQC adoption.
+
+### Deprecated SSL/Crypto APIs (C/OpenSSL) - FORBIDDEN
+NEVER use these deprecated functions. Use the replacement EVP high-level APIs.
+
+#### Symmetric Encryption (AES)
- Deprecated: `AES_encrypt()`, `AES_decrypt()`
-- Replacement: Use EVP high-level APIs:
- ```c
- EVP_EncryptInit_ex()
+- Replacement:
+
+ EVP_EncryptInit_ex() // Use EVP_aes_256_gcm() for PQC readiness
EVP_EncryptUpdate()
EVP_EncryptFinal_ex()
- EVP_DecryptInit_ex()
- EVP_DecryptUpdate()
- EVP_DecryptFinal_ex()
- ```
-
-### RSA Operations
-- Deprecated: `RSA_new()`, `RSA_up_ref()`, `RSA_free()`, `RSA_set0_crt_params()`, `RSA_get0_n()`
-- Replacement: Use EVP key management APIs:
- ```c
+
+
+#### RSA/PKEY Operations
+- Deprecated: `RSA_new()`, `RSA_free()`, `RSA_get0_n()`
+- Replacement:
+
EVP_PKEY_new()
EVP_PKEY_up_ref()
EVP_PKEY_free()
- ```
-
-### Hash Functions
-- Deprecated: `SHA1_Init()`, `SHA1_Update()`, `SHA1_Final()`
-- Replacement: Use EVP digest APIs:
- ```c
- EVP_DigestInit_ex()
- EVP_DigestUpdate()
- EVP_DigestFinal_ex()
- EVP_Q_digest() // For simple one-shot hashing
- ```
-
-### MAC Operations
-- Deprecated: `CMAC_Init()`, `HMAC()` (especially with SHA1)
-- Replacement: Use EVP MAC APIs:
- ```c
- EVP_Q_MAC() // For simple MAC operations
- ```
-
-### Key Wrapping
-- Deprecated: `AES_wrap_key()`, `AES_unwrap_key()`
-- Replacement: Use EVP key wrapping APIs or implement using EVP encryption
-
-### Other Deprecated Functions
-- Deprecated: `DSA_sign()`, `DH_check()`
-- Replacement: Use corresponding EVP APIs for DSA and DH operations
-
-## Banned Insecure Algorithms - STRICTLY FORBIDDEN
-These algorithms MUST NOT be used in any form:
-
-### Hash Algorithms (Banned)
-- MD2, MD4, MD5, SHA-0
-- Reason: Cryptographically broken, vulnerable to collision attacks
-- Use Instead: SHA-256, SHA-384, SHA-512
-
-### Symmetric Ciphers (Banned)
-- RC2, RC4, Blowfish, DES, 3DES
-- Reason: Weak key sizes, known vulnerabilities
-- Use Instead: AES-128, AES-256, ChaCha20
-
-### Key Exchange (Banned)
-- Static RSA key exchange
-- Anonymous Diffie-Hellman
-- Reason: No forward secrecy, vulnerable to man-in-the-middle attacks
-- Use Instead: ECDHE, DHE with proper validation
-
-## Broccoli Project Specific Requirements
-- HMAC() with SHA1: Deprecated per Broccoli project requirements
+
+
+#### Hash & MAC Functions
+- Deprecated: `SHA1_Init()`, `HMAC()` (especially with SHA1)
+- Replacement:
+
+ EVP_DigestInit_ex() // Use SHA-256 or stronger
+ EVP_Q_MAC() // For one-shot MAC
+
+
+## 5. Broccoli Project Specific Requirements
+- HMAC() with SHA1: Deprecated.
- Replacement: Use HMAC with SHA-256 or stronger:
- ```c
- // Instead of HMAC() with SHA1
- EVP_Q_MAC(NULL, "HMAC", NULL, "SHA256", NULL, key, key_len, data, data_len, out, out_size, &out_len);
- ```
-## Secure Crypto Implementation Pattern
+
+// Example: Secure replacement for HMAC-SHA1
+```c
+EVP_Q_MAC(NULL, "HMAC", NULL, "SHA256", NULL, key, key_len, data, data_len, out, out_size, &out_len);
+```
+
+## 6. Secure Crypto Implementation Pattern
+
+
+// Example: Secure AES-256-GCM encryption (PQC-Ready Symmetric Strength)
```c
-// Example: Secure AES encryption
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
if (!ctx) handle_error();
+// Use AES-256-GCM
if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, key, iv) != 1)
handle_error();
@@ -123,11 +134,3 @@ ciphertext_len += len;
EVP_CIPHER_CTX_free(ctx);
```
-
-## Code Review Checklist
-- [ ] No deprecated SSL/crypto APIs used
-- [ ] No banned algorithms (MD5, DES, RC4, etc.)
-- [ ] HMAC uses SHA-256 or stronger (not SHA1)
-- [ ] All crypto operations use EVP high-level APIs
-- [ ] Proper error handling for all crypto operations
-- [ ] Key material properly zeroed after use
diff --git a/sources/core/codeguard-1-digital-certificates.md b/sources/core/codeguard-1-digital-certificates.md
index 3d73c70..c333fa2 100644
--- a/sources/core/codeguard-1-digital-certificates.md
+++ b/sources/core/codeguard-1-digital-certificates.md
@@ -1,6 +1,8 @@
---
description: Certificate Best Practices
languages: []
+tags:
+- secrets
alwaysApply: true
---
diff --git a/sources/core/codeguard-1-hardcoded-credentials.md b/sources/core/codeguard-1-hardcoded-credentials.md
index 5f885ec..978d48a 100644
--- a/sources/core/codeguard-1-hardcoded-credentials.md
+++ b/sources/core/codeguard-1-hardcoded-credentials.md
@@ -1,6 +1,8 @@
---
description: No Hardcoded Credentials
languages: []
+tags:
+- secrets
alwaysApply: true
---
diff --git a/sources/core/codeguard-SKILLS.md.template b/sources/core/codeguard-SKILLS.md.template
index c856023..ff7420b 100644
--- a/sources/core/codeguard-SKILLS.md.template
+++ b/sources/core/codeguard-SKILLS.md.template
@@ -1,8 +1,7 @@
---
name: software-security
description: A software security skill that integrates with Project CodeGuard to help AI coding agents write secure code and prevent common vulnerabilities. Use this skill when writing, reviewing, or modifying code to ensure secure-by-default practices are followed.
-metadata:
-codeguard-version: "1.0.0"
+codeguard-version: "x.x.x"
framework: "Project CodeGuard"
purpose: "Embed secure-by-default practices into AI coding workflows"
---
@@ -25,7 +24,6 @@ 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
-- `codeguard-1-safe-c-functions.md` - Avoid unsafe C/C++ functions and use safe alternatives
2. Context-Specific Rules: Apply rules from /rules directory based on the language of the feature being implemented using the table given below:
diff --git a/src/convert_to_ide_formats.py b/src/convert_to_ide_formats.py
index 1d4f5fb..0a1e2d0 100644
--- a/src/convert_to_ide_formats.py
+++ b/src/convert_to_ide_formats.py
@@ -6,8 +6,8 @@
Convert Unified Rules to IDE Formats
Transforms the unified markdown sources into IDE-specific bundles (Cursor,
-Windsurf, Copilot, Claude Code). This script is the main entry point for producing
-distributable rule packs from the sources/ directory.
+Windsurf, Copilot, Agent Skills, Antigravity). This script is the main entry point
+for producing distributable rule packs from the sources/ directory.
"""
import re
@@ -16,7 +16,13 @@
from collections import defaultdict
from converter import RuleConverter
-from formats import CursorFormat, WindsurfFormat, CopilotFormat, ClaudeCodeFormat
+from formats import (
+ CursorFormat,
+ WindsurfFormat,
+ CopilotFormat,
+ AgentSkillsFormat,
+ AntigravityFormat,
+)
from utils import get_version_from_pyproject
from validate_versions import set_plugin_version, set_marketplace_version
@@ -26,7 +32,7 @@
def sync_plugin_metadata(version: str) -> None:
"""
- Sync version from pyproject.toml to Claude Code plugin metadata files.
+ Sync version from pyproject.toml to Agent Skills metadata files.
Args:
version: Version string from pyproject.toml
@@ -36,6 +42,23 @@ def sync_plugin_metadata(version: str) -> None:
print(f"✅ Synced plugin metadata to {version}")
+def matches_tag_filter(rule_tags: list[str], filter_tags: list[str]) -> bool:
+ """
+ Check if rule has all required tags (AND logic).
+
+ Args:
+ rule_tags: List of tags from the rule (already normalized to lowercase)
+ filter_tags: List of tags to filter by (already normalized to lowercase)
+
+ Returns:
+ True if rule has all filter tags (or no filter), False otherwise
+ """
+ if not filter_tags:
+ return True # No filter means all pass
+
+ return all(tag in rule_tags for tag in filter_tags)
+
+
def update_skill_md(language_to_rules: dict[str, list[str]], skill_path: str) -> None:
"""
Update SKILL.md with language-to-rules mapping table.
@@ -81,15 +104,22 @@ def update_skill_md(language_to_rules: dict[str, list[str]], skill_path: str) ->
print(f"Updated SKILL.md with language mappings")
-def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode: bool = True, version: str = None) -> dict[str, list[str]]:
+def convert_rules(
+ input_path: str,
+ output_dir: str = "dist",
+ include_agentskills: bool = True,
+ version: str = None,
+ filter_tags: list[str] = None,
+) -> dict[str, list[str]]:
"""
Convert rule file(s) to all supported IDE formats using RuleConverter.
Args:
input_path: Path to a single .md file or folder containing .md files
output_dir: Output directory (default: 'dist/')
- include_claudecode: Whether to generate Claude Code plugin (default: True, only for core rules)
+ include_agentskills: Whether to generate Agent Skills format (default: True, only for core rules)
version: Version string to use (default: read from pyproject.toml)
+ filter_tags: Optional list of tags to filter by (AND logic, case-insensitive)
Returns:
Dictionary with 'success' and 'errors' lists:
@@ -99,7 +129,7 @@ def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode:
}
Example:
- results = convert_rules("sources/core", "dist", include_claudecode=True)
+ results = convert_rules("sources/core", "dist", include_agentskills=True)
print(f"Converted {len(results['success'])} rules")
"""
if version is None:
@@ -110,11 +140,12 @@ def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode:
CursorFormat(version),
WindsurfFormat(version),
CopilotFormat(version),
+ AntigravityFormat(version),
]
-
- # Only include Claude Code for core rules (committed plugin)
- if include_claudecode:
- all_formats.append(ClaudeCodeFormat(version))
+
+ # Only include Agent Skills format for core rules (committed as skills)
+ if include_agentskills:
+ all_formats.append(AgentSkillsFormat(version))
converter = RuleConverter(formats=all_formats)
path = Path(input_path)
@@ -132,13 +163,13 @@ def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode:
md_files = sorted(list(path.rglob("*.md")))
if not md_files:
raise ValueError(f"No .md files found in {input_path}")
-
+
print(f"Converting {len(md_files)} files from: {path}")
# Setup output directory
output_base = Path(output_dir)
- results = {"success": [], "errors": []}
+ results = {"success": [], "errors": [], "skipped": []}
language_to_rules = defaultdict(list)
# Process each file
@@ -147,21 +178,24 @@ def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode:
# Convert the file (raises exceptions on error)
result = converter.convert(md_file)
+ # Apply tag filter if specified
+ if filter_tags and not matches_tag_filter(result.tags, filter_tags):
+ results["skipped"].append(result.filename)
+ continue
+
# Write each format
output_files = []
for format_name, output in result.outputs.items():
# Construct output path
- # Claude Code goes to project root ./skills/
+ # Agent Skills goes to project root ./skills/
# Other formats go to dist/ (or specified output_dir)
- if format_name == "claudecode":
+ if format_name == "agentskills":
base_dir = PROJECT_ROOT
else:
base_dir = output_base
-
+
output_file = (
- base_dir
- / output.subpath
- / f"{result.basename}{output.extension}"
+ base_dir / output.subpath / f"{result.basename}{output.extension}"
)
# Create directory if it doesn't exist and write file
@@ -192,34 +226,41 @@ def convert_rules(input_path: str, output_dir: str = "dist", include_claudecode:
results["errors"].append(error_msg)
# Summary
- print(
- f"\nResults: {len(results['success'])} success, {len(results['errors'])} errors"
- )
+ if filter_tags:
+ print(
+ f"\nResults: {len(results['success'])} success, {len(results['skipped'])} skipped (tag filter), {len(results['errors'])} errors"
+ )
+ else:
+ print(
+ f"\nResults: {len(results['success'])} success, {len(results['errors'])} errors"
+ )
+
+ # Generate SKILL.md with language mappings (only if Agent Skills is included)
+ if include_agentskills and language_to_rules:
+ template_path = (
+ PROJECT_ROOT / "sources" / "core" / "codeguard-SKILLS.md.template"
+ )
- # Generate SKILL.md with language mappings (only if Claude Code is included)
- if include_claudecode and language_to_rules:
- template_path = PROJECT_ROOT / "sources" / "core" / "codeguard-SKILLS.md.template"
-
if not template_path.exists():
raise FileNotFoundError(
f"SKILL.md template not found at {template_path}. "
- "This file is required for Claude Code plugin generation."
+ "This file is required for Agent Skills generation."
)
-
+
output_skill_dir = PROJECT_ROOT / "skills" / "software-security"
output_skill_dir.mkdir(parents=True, exist_ok=True)
output_skill_path = output_skill_dir / "SKILL.md"
-
+
# Read template and inject current version from pyproject.toml
template_content = template_path.read_text(encoding="utf-8")
# Replace the hardcoded version with actual version
template_content = re.sub(
r'codeguard-version:\s*"[^"]*"',
f'codeguard-version: "{version}"',
- template_content
+ template_content,
)
output_skill_path.write_text(template_content, encoding="utf-8")
-
+
update_skill_md(language_to_rules, str(output_skill_path))
return results
@@ -233,7 +274,7 @@ def _resolve_source_paths(args) -> list[Path]:
# If --source flags provided, resolve under sources/
if args.source:
return [Path("sources") / src for src in args.source]
-
+
# Default: core rules only
return [Path("sources/core")]
@@ -241,7 +282,7 @@ def _resolve_source_paths(args) -> list[Path]:
if __name__ == "__main__":
import sys
from argparse import ArgumentParser
-
+
parser = ArgumentParser(
description="Convert unified rule markdown into IDE-specific bundles."
)
@@ -256,7 +297,13 @@ def _resolve_source_paths(args) -> list[Path]:
default="dist",
help="Output directory for generated bundles (default: dist).",
)
-
+ parser.add_argument(
+ "--tag",
+ "--tags",
+ dest="tags",
+ help="Filter rules by tags (comma-separated, case-insensitive, AND logic). Example: --tag api,web-security",
+ )
+
cli_args = parser.parse_args()
source_paths = _resolve_source_paths(cli_args)
@@ -272,27 +319,31 @@ def _resolve_source_paths(args) -> list[Path]:
for source_path in source_paths:
for md_file in source_path.rglob("*.md"):
filename_to_sources[md_file.name].append(source_path.name)
-
- duplicates = {name: srcs for name, srcs in filename_to_sources.items() if len(srcs) > 1}
+
+ duplicates = {
+ name: srcs for name, srcs in filename_to_sources.items() if len(srcs) > 1
+ }
if duplicates:
print(f"❌ Found {len(duplicates)} duplicate filename(s) across sources:")
for filename, sources in duplicates.items():
print(f" - {filename} in: {', '.join(sources)}")
print("\nPlease rename files to have unique names across all sources.")
sys.exit(1)
-
+
# Get version once and sync to metadata files
version = get_version_from_pyproject()
sync_plugin_metadata(version)
- # Check if core is in the sources for Claude Code plugin generation
+ # Check if core is in the sources for Agent Skills generation
has_core = Path("sources/core") in source_paths
if has_core:
# Validate template exists early
- template_path = PROJECT_ROOT / "sources" / "core" / "codeguard-SKILLS.md.template"
+ template_path = (
+ PROJECT_ROOT / "sources" / "core" / "codeguard-SKILLS.md.template"
+ )
if not template_path.exists():
print(f"❌ SKILL.md template not found at {template_path}")
- print("This file is required for Claude Code plugin generation.")
+ print("This file is required for Agent Skills generation.")
sys.exit(1)
# Clean output directories once before processing
@@ -306,34 +357,50 @@ def _resolve_source_paths(args) -> list[Path]:
if skills_rules_dir.exists():
shutil.rmtree(skills_rules_dir)
print(f"✅ Cleaned skills/ directory")
-
+
# Print processing summary
if len(source_paths) > 1:
- sources_list = ', '.join(p.name for p in source_paths)
+ sources_list = ", ".join(p.name for p in source_paths)
print(f"\nConverting {len(source_paths)} sources: {sources_list}")
if has_core:
- print("(Claude Code plugin will include only core rules)")
+ print("(Agent Skills will include only core rules)")
print()
-
+
# Convert all sources
- aggregated = {"success": [], "errors": []}
+ aggregated = {"success": [], "errors": [], "skipped": []}
+ # Parse comma-separated tags and normalize to lowercase
+ filter_tags = None
+ if cli_args.tags:
+ filter_tags = [
+ tag.strip().lower() for tag in cli_args.tags.split(",") if tag.strip()
+ ]
+
+ # Print tag filter info if active
+ if filter_tags:
+ print(
+ f"Tag filter active: {', '.join(filter_tags)} (AND logic - rules must have all tags)\n"
+ )
+
for source_path in source_paths:
is_core = source_path == Path("sources/core")
-
+
print(f"Processing: {source_path}")
results = convert_rules(
- str(source_path),
- cli_args.output_dir,
- include_claudecode=is_core,
- version=version
+ str(source_path),
+ cli_args.output_dir,
+ include_agentskills=is_core,
+ version=version,
+ filter_tags=filter_tags,
)
-
+
aggregated["success"].extend(results["success"])
aggregated["errors"].extend(results["errors"])
+ if "skipped" in results:
+ aggregated["skipped"].extend(results["skipped"])
print("")
-
+
if aggregated["errors"]:
print("❌ Some conversions failed")
sys.exit(1)
-
+
print("✅ All conversions successful")
diff --git a/src/converter.py b/src/converter.py
index 39f4fce..4a71a94 100644
--- a/src/converter.py
+++ b/src/converter.py
@@ -12,7 +12,7 @@
from pathlib import Path
from language_mappings import languages_to_globs
-from utils import parse_frontmatter_and_content
+from utils import parse_frontmatter_and_content, validate_tags
from formats import (
BaseFormat,
ProcessedRule,
@@ -45,6 +45,7 @@ class ConversionResult:
basename: Filename without extension (e.g., 'my-rule')
outputs: Dictionary mapping format names to their outputs
languages: List of programming languages the rule applies to, empty list if always applies
+ tags: List of tags for categorizing and filtering rules
Example:
result = ConversionResult(
filename="my-rule.md",
@@ -56,7 +57,8 @@ class ConversionResult:
subpath=".cursor/rules"
)
},
- languages=["python", "javascript"]
+ languages=["python", "javascript"],
+ tags=["authentication", "web-security"]
)
"""
@@ -64,6 +66,7 @@ class ConversionResult:
basename: str
outputs: dict[str, FormatOutput]
languages: list[str]
+ tags: list[str]
class RuleConverter:
@@ -159,6 +162,11 @@ def parse_rule(self, content: str, filename: str) -> ProcessedRule:
f"'languages' must be a non-empty list in {filename} when alwaysApply is false"
)
+ # Parse and validate tags (optional field)
+ tags = []
+ if "tags" in frontmatter:
+ tags = validate_tags(frontmatter["tags"], filename)
+
# Adding rule_id to the beginning of the content
rule_id = Path(filename).stem
markdown_content = f"rule_id: {rule_id}\n\n{markdown_content}"
@@ -169,6 +177,7 @@ def parse_rule(self, content: str, filename: str) -> ProcessedRule:
always_apply=always_apply,
content=markdown_content,
filename=filename,
+ tags=tags,
)
def generate_globs(self, languages: list[str]) -> str:
@@ -242,4 +251,5 @@ def convert(self, filepath: str) -> ConversionResult:
basename=basename,
outputs=outputs,
languages=rule.languages,
+ tags=rule.tags,
)
diff --git a/src/formats/__init__.py b/src/formats/__init__.py
index 4a2a7db..e1a48a3 100644
--- a/src/formats/__init__.py
+++ b/src/formats/__init__.py
@@ -11,7 +11,8 @@
- CursorFormat: Generates .mdc files for Cursor IDE
- WindsurfFormat: Generates .md files for Windsurf IDE
- CopilotFormat: Generates .instructions.md files for GitHub Copilot
-- ClaudeCodeFormat: Generates .md files for Claude Code plugins
+- AgentSkillsFormat: Generates .md files for Agent Skills (OpenAI Codex, Claude Code, other AI coding tools)
+- AntigravityFormat: Generates .md files for Google Antigravity
Usage:
from formats import BaseFormat, ProcessedRule, CursorFormat, WindsurfFormat, CopilotFormat, ClaudeCodeFormat
@@ -21,7 +22,8 @@
CursorFormat(version),
WindsurfFormat(version),
CopilotFormat(version),
- ClaudeCodeFormat(version),
+ AgentSkillsFormat(version),
+ AntigravityFormat(version),
]
"""
@@ -29,7 +31,8 @@
from formats.cursor import CursorFormat
from formats.windsurf import WindsurfFormat
from formats.copilot import CopilotFormat
-from formats.claudecode import ClaudeCodeFormat
+from formats.agentskills import AgentSkillsFormat
+from formats.antigravity import AntigravityFormat
__all__ = [
"BaseFormat",
@@ -37,5 +40,6 @@
"CursorFormat",
"WindsurfFormat",
"CopilotFormat",
- "ClaudeCodeFormat",
+ "AgentSkillsFormat",
+ "AntigravityFormat",
]
diff --git a/src/formats/claudecode.py b/src/formats/agentskills.py
similarity index 52%
rename from src/formats/claudecode.py
rename to src/formats/agentskills.py
index 4c3b152..798b2db 100644
--- a/src/formats/claudecode.py
+++ b/src/formats/agentskills.py
@@ -3,72 +3,75 @@
# SPDX-License-Identifier: Apache-2.0
"""
-Claude Code Format Implementation
+Agent Skills Format Implementation
-Generates .md files for Claude Code Skills/Plugins.
+Generates .md files for the Agent Skills standard (agentskills.io).
+This format is used by OpenAI Codex, Claude Code, and other AI coding tools.
"""
from formats.base import BaseFormat, ProcessedRule
-class ClaudeCodeFormat(BaseFormat):
+class AgentSkillsFormat(BaseFormat):
"""
- Claude Code plugin format implementation (.md files).
-
- Claude Code Skills use standard markdown files without
- special frontmatter. The original rule content is preserved
- and placed in the skills/software-security/rules/ directory
- for plugin distribution.
-
- Unlike other IDE formats, Claude Code doesn't require special
- frontmatter transformations - it uses the rules as-is for
- plugin-based Skills.
+ Agent Skills format implementation (.md files).
+
+ Agent Skills (https://agentskills.io/) is an open standard for extending
+ AI coding agents with task-specific capabilities. It uses standard markdown
+ files with YAML frontmatter to define rules and instructions.
+
+ This format is adopted by:
+ - OpenAI Codex (skills)
+ - Claude Code (plugins)
+ - Other AI coding tools
+
+ The original rule content is preserved and placed in the
+ skills/software-security/rules/ directory for distribution.
"""
def get_format_name(self) -> str:
- """Return Claude Code format identifier."""
- return "claudecode"
+ """Return Agent Skills format identifier."""
+ return "agentskills"
def get_file_extension(self) -> str:
- """Return Claude Code format file extension."""
+ """Return Agent Skills format file extension."""
return ".md"
def get_output_subpath(self) -> str:
- """Return Claude Code output subdirectory."""
+ """Return Agent Skills output subdirectory."""
return "skills/software-security/rules"
def generate(self, rule: ProcessedRule, globs: str) -> str:
"""
- Generate Claude Code .md format.
-
- Claude Code Skills should preserve the original YAML frontmatter
+ 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.
-
+ and can be referenced properly by AI coding agents.
+
Args:
rule: The processed rule to format
- globs: Glob patterns (not used for Claude Code format)
-
+ globs: Glob patterns (not used for Agent Skills format)
+
Returns:
Complete markdown with original YAML frontmatter preserved
"""
# Build YAML frontmatter
yaml_lines = []
-
+
# Add description
desc = self._format_yaml_field("description", rule.description)
if desc:
yaml_lines.append(desc)
-
+
# Add languages if present
if rule.languages:
# Format as YAML list
yaml_lines.append("languages:")
for lang in rule.languages:
yaml_lines.append(f"- {lang}")
-
+
# Add alwaysApply
yaml_lines.append(f"alwaysApply: {str(rule.always_apply).lower()}")
-
- return self._build_yaml_frontmatter(yaml_lines, rule.content)
+ return self._build_yaml_frontmatter(yaml_lines, rule.content)
diff --git a/src/formats/antigravity.py b/src/formats/antigravity.py
new file mode 100644
index 0000000..a77ecbd
--- /dev/null
+++ b/src/formats/antigravity.py
@@ -0,0 +1,74 @@
+# Copyright 2025 Cisco Systems, Inc. and its affiliates
+#
+# SPDX-License-Identifier: Apache-2.0
+
+"""
+Antigravity Format Implementation
+
+Generates .md rule files for Antigravity with YAML frontmatter.
+"""
+
+from formats.base import BaseFormat, ProcessedRule
+
+
+class AntigravityFormat(BaseFormat):
+ """
+ Antigravity format implementation (.md rule files).
+
+ Antigravity uses .md files with YAML frontmatter containing:
+ - trigger: 'always_on' or 'glob' (activation type)
+ - globs: (if trigger is 'glob') File matching patterns
+ - description: Rule description
+ - version: Rule version
+
+ Rules use activation types (Always On or Glob) to determine when
+ they apply, similar to Windsurf's implementation.
+ See: https://antigravity.google/docs/rules-workflows
+ """
+
+ def get_format_name(self) -> str:
+ """Return Antigravity format identifier."""
+ return "antigravity"
+
+ def get_file_extension(self) -> str:
+ """Return Antigravity format file extension."""
+ return ".md"
+
+ def get_output_subpath(self) -> str:
+ """Return Antigravity output subdirectory."""
+ return ".agent/rules"
+
+ def generate(self, rule: ProcessedRule, globs: str) -> str:
+ """
+ Generate Antigravity .md format with YAML frontmatter.
+
+ Args:
+ rule: The processed rule to format
+ globs: Glob patterns for file matching
+
+ Returns:
+ Formatted .md content with trigger, globs, description, and version
+
+ Note:
+ Antigravity rules use activation types:
+ - 'always_on': Rule applies to all files (when alwaysApply is true)
+ - 'glob': Rule applies to files matching glob patterns (language-specific)
+ """
+ yaml_lines = []
+
+ # Use trigger: always_on for rules that should always apply
+ if rule.always_apply:
+ yaml_lines.append("trigger: always_on")
+ else:
+ yaml_lines.append("trigger: glob")
+ yaml_lines.append(f"globs: {globs}")
+
+ # Add description (required by Antigravity spec)
+ desc = self._format_yaml_field("description", rule.description)
+ if desc:
+ yaml_lines.append(desc)
+
+ # Add version
+ yaml_lines.append(f"version: {self.version}")
+
+ return self._build_yaml_frontmatter(yaml_lines, rule.content)
diff --git a/src/formats/base.py b/src/formats/base.py
index 5af8732..65c75e5 100644
--- a/src/formats/base.py
+++ b/src/formats/base.py
@@ -25,6 +25,7 @@ class ProcessedRule:
always_apply: Whether this rule should apply to all files
content: The actual rule content in markdown format
filename: Original filename of the rule
+ tags: List of tags for categorizing and filtering rules
"""
description: str
@@ -32,6 +33,7 @@ class ProcessedRule:
always_apply: bool
content: str
filename: str
+ tags: list[str]
class BaseFormat(ABC):
diff --git a/src/tag_mappings.py b/src/tag_mappings.py
new file mode 100644
index 0000000..304992b
--- /dev/null
+++ b/src/tag_mappings.py
@@ -0,0 +1,21 @@
+# Copyright 2025 Cisco Systems, Inc. and its affiliates
+#
+# SPDX-License-Identifier: Apache-2.0
+
+"""
+Tag Mappings
+
+Centralized list of known tags for categorizing security rules.
+"""
+
+# Known tags used in rules
+# Add new tags here as they are introduced in rules
+KNOWN_TAGS = {
+ "authentication",
+ "data-security",
+ "infrastructure",
+ "privacy",
+ "secrets",
+ "web",
+}
+
diff --git a/src/utils.py b/src/utils.py
index fb0fed6..a360e74 100644
--- a/src/utils.py
+++ b/src/utils.py
@@ -57,6 +57,51 @@ def parse_frontmatter_and_content(content: str) -> tuple[dict | None, str]:
return frontmatter, markdown_content.strip()
+def validate_tags(tags, filename=None) -> list[str]:
+ """
+ Validate tags list and return normalized (lowercase) tags.
+
+ Args:
+ tags: The tags value to validate (should be a non-empty list)
+ filename: Optional filename for better error messages
+
+ Returns:
+ List of normalized (lowercase) tags with duplicates removed.
+ Original order is preserved.
+
+ Raises:
+ ValueError: If tags are invalid (wrong type, empty list, contain whitespace, etc.)
+
+ Note:
+ - An empty tags list (tags: []) is considered invalid. If you have no tags,
+ omit the 'tags' field entirely from the frontmatter.
+ - Duplicate tags (after normalization) are automatically removed while
+ preserving the order of first occurrence.
+ """
+ context = f" in {filename}" if filename else ""
+
+ if not isinstance(tags, list):
+ raise ValueError(f"'tags' must be a list{context}")
+
+ if not tags:
+ raise ValueError(f"'tags' list cannot be empty{context}. Omit the field if you have no tags.")
+
+ normalized = []
+ for tag in tags:
+ if not isinstance(tag, str):
+ raise ValueError(f"All tags must be strings{context}, found: {type(tag).__name__}")
+
+ if any(c.isspace() for c in tag):
+ raise ValueError(f"Tags cannot contain whitespace: '{tag}'{context}")
+
+ if not tag:
+ raise ValueError(f"Empty tag found{context}")
+
+ normalized.append(tag.lower())
+
+ return list(dict.fromkeys(normalized))
+
+
def get_version_from_pyproject() -> str:
"""
Read version from pyproject.toml using Python's built-in TOML parser.
diff --git a/src/validate_unified_rules.py b/src/validate_unified_rules.py
index bd509bc..8fd454c 100755
--- a/src/validate_unified_rules.py
+++ b/src/validate_unified_rules.py
@@ -12,7 +12,8 @@
from pathlib import Path
from language_mappings import LANGUAGE_TO_EXTENSIONS
-from utils import parse_frontmatter_and_content
+from tag_mappings import KNOWN_TAGS
+from utils import parse_frontmatter_and_content, validate_tags
def validate_rule(file_path: Path) -> dict[str, list[str]]:
@@ -54,6 +55,17 @@ def validate_rule(file_path: Path) -> dict[str, list[str]]:
if unknown:
warnings.append(f"Unknown languages: {', '.join(unknown)}")
+ # Validate tags if present
+ if "tags" in frontmatter:
+ try:
+ normalized_tags = validate_tags(frontmatter["tags"], file_path.name)
+ # Error on tags not in known list
+ unknown_tags = [tag for tag in normalized_tags if tag not in KNOWN_TAGS]
+ if unknown_tags:
+ errors.append(f"Unknown tags (add to KNOWN_TAGS): {', '.join(sorted(unknown_tags))}")
+ except ValueError as e:
+ errors.append(str(e))
+
# Check content exists
if not markdown_content.strip():
errors.append("Rule content cannot be empty")
diff --git a/uv.lock b/uv.lock
index e9143af..876f078 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1,5 +1,5 @@
version = 1
-revision = 3
+revision = 2
requires-python = ">=3.11"
[[package]]
@@ -340,7 +340,7 @@ wheels = [
[[package]]
name = "project-codeguard"
-version = "1.0.0"
+version = "1.0.1"
source = { virtual = "." }
dependencies = [
{ name = "mkdocs" },