diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index af3c432..4ef74fd 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -13,7 +13,7 @@ "name": "codeguard-security", "source": "./", "description": "Comprehensive security rules for AI coding agents", - "version": "1.0.0", + "version": "1.0.1", "repository": "https://github.com/project-codeguard/rules.git", "tags": [ "security", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index d0b13b4..21f1021 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "codeguard-security", "description": "Security code review skill based on Project CodeGuard's comprehensive security rules. Helps AI coding agents write secure code and prevent common vulnerabilities.", - "version": "1.0.0", + "version": "1.0.1", "author": { "name": "Project CodeGuard", "url": "https://project-codeguard.org" diff --git a/.github/ISSUE_TEMPLATE/new-rule.yml b/.github/ISSUE_TEMPLATE/new-rule.yml index c9ed8bc..939eee6 100644 --- a/.github/ISSUE_TEMPLATE/new-rule.yml +++ b/.github/ISSUE_TEMPLATE/new-rule.yml @@ -6,7 +6,7 @@ body: - type: markdown attributes: value: | - Thank you for your new rule request! Please provide as much detail as possible. Use any of the existing rules as a reference. You only have to provide the rule contents (markdown), not the rule metadata. We will handle the rest. In other words, convert your rule into all the formats (Cursor, Windsurf, Copilot). + Thank you for your new rule request! Please provide as much detail as possible. Use any of the existing rules as a reference. You only have to provide the rule contents (markdown), not the rule metadata. We will handle the rest. In other words, convert your rule into all the formats (Cursor, Windsurf, Copilot, Antigravity). - type: textarea id: description diff --git a/.github/ISSUE_TEMPLATE/rule-feedback.yml b/.github/ISSUE_TEMPLATE/rule-feedback.yml index 7abbc2c..ad24a97 100644 --- a/.github/ISSUE_TEMPLATE/rule-feedback.yml +++ b/.github/ISSUE_TEMPLATE/rule-feedback.yml @@ -26,6 +26,7 @@ body: - Cursor - GitHub Copilot - Windsurf + - Antigravity - Codex - Augment Code - Sourcegraph diff --git a/.github/workflows/build-ide-bundles.yml b/.github/workflows/build-ide-bundles.yml index f832a55..610bebe 100644 --- a/.github/workflows/build-ide-bundles.yml +++ b/.github/workflows/build-ide-bundles.yml @@ -54,6 +54,7 @@ jobs: zip -r ../ide-rules-cursor.zip .cursor/ zip -r ../ide-rules-windsurf.zip .windsurf/ zip -r ../ide-rules-copilot.zip .github/ + zip -r ../ide-rules-antigravity.zip .agent/ cd .. zip -r ide-rules-all.zip dist/ ls -lh ide-rules-*.zip @@ -67,5 +68,6 @@ jobs: ide-rules-cursor.zip \ ide-rules-windsurf.zip \ ide-rules-copilot.zip \ + ide-rules-antigravity.zip \ --clobber diff --git a/.github/workflows/validate-rules.yml b/.github/workflows/validate-rules.yml index 3e6f903..1ddfefe 100644 --- a/.github/workflows/validate-rules.yml +++ b/.github/workflows/validate-rules.yml @@ -51,7 +51,6 @@ jobs: "sources/core/codeguard-1-hardcoded-credentials.md" "sources/core/codeguard-1-crypto-algorithms.md" "sources/core/codeguard-1-digital-certificates.md" - "sources/core/codeguard-1-safe-c-functions.md" "sources/core/codeguard-SKILLS.md.template" ) @@ -90,6 +89,11 @@ jobs: exit 1 fi + if [ ! -d "test-output/.agent" ]; then + echo "❌ Antigravity rules not generated" + exit 1 + fi + echo "✅ All IDE formats generated successfully" - name: Check skills/ directory is up-to-date diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73d9568..155a453 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -160,7 +160,7 @@ git push origin main **Note**: The conversion script automatically syncs the version from `pyproject.toml` to: - `.claude-plugin/plugin.json` and `marketplace.json` (Claude Code plugin metadata) -- All generated IDE rule files (Cursor `.mdc`, Windsurf `.md`, Copilot `.instructions.md`, Claude Code `.md`) +- All generated IDE rule files (Cursor `.mdc`, Windsurf `.md`, Copilot `.instructions.md`, Claude Code `.md`, Antigravity `.md`) This ensures version consistency across all artifacts. @@ -174,7 +174,7 @@ This ensures version consistency across all artifacts. GitHub Actions will automatically: - ✅ Validate versions match the tag -- ✅ Build IDE bundles (Cursor, Windsurf, Copilot) +- ✅ Build IDE bundles (Cursor, Windsurf, Copilot, Antigravity) - ✅ Upload ZIP artifacts to the release ## Testing Your Changes diff --git a/README.md b/README.md index 69c48a2..e30bc60 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,12 @@ This project is an AI model-agnostic security framework and ruleset (internally 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. @@ -31,14 +31,14 @@ Project CodeGuard is designed to integrate seamlessly across the entire AI codin 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 @@ -54,7 +54,7 @@ Get started in minutes: ## How It Works 1. **Security rules** are written in unified markdown format (`sources/` directory) -2. **Conversion tools** translate rules to IDE-specific formats (Cursor, Windsurf, Copilot, Claude Code) +2. **Conversion tools** translate rules to IDE-specific formats (Cursor, Windsurf, Copilot, Agent Skills, Antigravity) 3. **Release automation** packages rules into downloadable ZIP files 4. **AI assistants** reference these rules when generating or reviewing code 5. **Secure code** is produced automatically without developer intervention @@ -63,7 +63,7 @@ Get started in minutes: ``` sources/ # Source rules -skills/ # Claude Code plugin (generated, committed) +skills/ # Agent Skills format (generated, committed) src/ # Conversion and validation tools dist/ # Other IDE bundles (generated, not committed) ``` @@ -97,4 +97,4 @@ This project uses dual licensing: This licensing approach ensures the security rules remain freely accessible and reusable while providing appropriate terms for software components. -Copyright © 2025 Cisco Systems, Inc. \ No newline at end of file +Copyright © 2025 Cisco Systems, Inc. diff --git a/docs/claude-code-skill-plugin.md b/docs/claude-code-skill-plugin.md index f7888c2..e739cbb 100644 --- a/docs/claude-code-skill-plugin.md +++ b/docs/claude-code-skill-plugin.md @@ -70,14 +70,13 @@ When generating or reviewing code, Claude follows this 3-step workflow: ### Rule Categories -**Always-Apply Rules** (4 critical rules checked on every code operation): +**Always-Apply Rules** (3 critical rules checked on every code operation): - `codeguard-1-hardcoded-credentials` - Never hardcode secrets or credentials - `codeguard-1-crypto-algorithms` - Use modern cryptographic algorithms - `codeguard-1-digital-certificates` - Validate certificate security -- `codeguard-1-safe-c-functions` - Replace unsafe C/C++ functions -**Context-Specific Rules** (18 rules applied based on technology and features): -- Input validation, authentication, authorization, APIs, data storage, privacy, logging, cryptography, file handling, serialization, supply chain, DevOps, cloud, Kubernetes, IaC, frameworks, and mobile security +**Context-Specific Rules** (19 rules applied based on technology and features): +- Input validation, authentication, authorization, APIs, data storage, privacy, logging, cryptography, file handling, serialization, supply chain, DevOps, cloud, Kubernetes, IaC, frameworks, mobile security, and memory safety (C/C++) ## Usage Examples @@ -155,7 +154,7 @@ For organizations, deploy CodeGuard to all developers automatically: The plugin includes 22 comprehensive security rules organized into two categories: -### Always-Apply Rules (4 rules) +### Always-Apply Rules (3 rules) These critical rules are checked on **every** code operation: @@ -164,9 +163,8 @@ These critical rules are checked on **every** code operation: | `codeguard-1-hardcoded-credentials` | Prevent secrets, passwords, API keys, tokens in source code | | `codeguard-1-crypto-algorithms` | Ban weak algorithms (MD5, SHA-1, DES); use modern alternatives | | `codeguard-1-digital-certificates` | Validate certificate expiration, key strength, signature algorithms | -| `codeguard-1-safe-c-functions` | Replace unsafe C/C++ functions (gets, strcpy, strcat, sprintf) | -### Context-Specific Rules (18 rules) +### Context-Specific Rules (19 rules) These rules apply based on the programming language, framework, or feature being implemented. Claude automatically selects relevant rules based on context: @@ -182,6 +180,7 @@ These rules apply based on the programming language, framework, or feature being | **Files & Serialization** | `codeguard-0-file-handling-and-uploads`, `codeguard-0-xml-and-serialization` | | **Infrastructure** | `codeguard-0-supply-chain-security`, `codeguard-0-devops-ci-cd-containers`, `codeguard-0-cloud-orchestration-kubernetes`, `codeguard-0-iac-security` | | **Platforms** | `codeguard-0-framework-and-languages`, `codeguard-0-mobile-apps` | +| **Memory Safety (C/C++)** | `codeguard-0-safe-c-functions` | > **Note:** Each rule file contains detailed guidance, checklists, and examples. Claude references these automatically based on the code context. @@ -291,7 +290,7 @@ uv run python src/convert_to_ide_formats.py This command: - Converts unified rules from `sources/` to IDE-specific formats - Generates `skills/` directory with the 22 core security rules (Claude Code plugin) -- Creates `dist/` with IDE-specific formats (Cursor, Windsurf, Copilot) +- Creates `dist/` with IDE-specific formats (Cursor, Windsurf, Copilot, Antigravity) **Note:** The Claude Code plugin (`skills/`) always contains only the 22 curated core rules. To build bundles with OWASP supplementary rules for other IDEs, use `--source core owasp`, but this only affects `dist/`, not `skills/`. @@ -385,6 +384,11 @@ Found an issue with the plugin or want to improve it? ## Version History +### Version 1.0.1 +- Changed `codeguard-1-safe-c-functions` from always-apply to `codeguard-0-safe-c-functions` context-specific rule (C/C++ only) +- Updated rule counts: 3 always-apply rules, 19 context-specific rules +- Fixed GitHub Copilot instructions to use `description` field instead of `title` + ### Version 1.0.0 - Initial release - 22 comprehensive security rules diff --git a/docs/faq.md b/docs/faq.md index 648a4dc..21a57d6 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -26,7 +26,20 @@ This FAQ document provides clear, concise answers to help developers seamlessly --- ## Q: Will these rules consume a lot of the AI agent's **context window**? -**A:** No. The always-on rules are designed to be lightweight and efficient, and should not consume a lot of the AI agent's context window. The "glob" rules are designed to be applied only to the related file types specified in the rule. +**A:** The always‑on rules are lightweight and have minimal impact on the AI agent’s context window. Glob‑scoped rules only apply to their matching file types. Below are Cursor examples: left, no rules; right, three always‑on rules enabled. + +

+ Cursor AI agent context window usage without Project CodeGuard rules + Cursor AI agent context window usage with Project CodeGuard rules enabled +

+ +
+ + 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" },