Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 23 additions & 24 deletions .github/workflows/validate-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,29 @@ jobs:
exit 1
fi

- name: Check skills/software-security/ directory is up-to-date
run: |
echo "Checking if committed skills/software-security/ is up-to-date..."

# Save the generated skill directory only
cp -r skills/software-security skills-committed

# Regenerate (core rules only, matching default)
uv run python src/convert_to_ide_formats.py

# Compare only the software-security subtree
if ! diff -r skills/software-security/ skills-committed/ > /dev/null 2>&1; then
echo "❌ skills/software-security/ is out of date!"
echo "Please regenerate by running: python src/convert_to_ide_formats.py"
echo "Then: git add skills/software-security/"
diff -r skills/software-security/ skills-committed/ || true
rm -rf skills-committed
exit 1
fi

rm -rf skills-committed
echo "✅ skills/software-security/ is up-to-date"

- name: Test conversion to IDE formats
run: |
echo "Testing IDE format conversion..."
Expand Down Expand Up @@ -116,30 +139,6 @@ jobs:

echo "✅ All IDE formats generated successfully"

- name: Check skills/ directory is up-to-date
run: |
echo "Checking if committed skills/ directory is up-to-date..."

# Save current skills
mv skills skills-committed

# Regenerate skills (core rules only, matching default)
uv run python src/convert_to_ide_formats.py

# Compare
if ! diff -r skills/ skills-committed/ > /dev/null 2>&1; then
echo "❌ The skills/ directory is out of date!"
echo "Please regenerate by running: python src/convert_to_ide_formats.py"
echo "Then: git add skills/"
mv skills-committed skills
exit 1
fi

# Restore original
rm -rf skills
mv skills-committed skills
echo "✅ Committed skills/ directory is up-to-date"

- name: Summary
if: success()
run: |
Expand Down
5 changes: 3 additions & 2 deletions docs/claude-code-skill-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ This command:
- Generates `skills/` directory with the 23 core security rules (Claude Code plugin)
- Creates `dist/` with all supported agent-specific formats

**Note:** The Claude Code plugin (`skills/`) always contains only the 23 curated core rules. To build bundles with OWASP supplementary rules for other IDEs, use `--source core owasp`, but this only affects `dist/`, not `skills/`.
**Note:** The Claude Code plugin (`skills/`) always contains only the 23 curated core rules. To build bundles with OWASP supplementary rules for other IDEs, use `--source core additional-skills/owasp`, but this only affects `dist/`, not `skills/`.

## Advanced Usage

Expand Down Expand Up @@ -338,7 +338,8 @@ cosai-oasis/project-codeguard/
├── sources/ # Source rules (version controlled)
│ ├── core/ # Core security rules
│ └── owasp/ # OWASP supplementary rules
│ └── additional-skills/
│ └── owasp/ # OWASP supplementary rules
├── skills/ # Claude Code plugin (version controlled)
│ └── software-security/
Expand Down
9 changes: 5 additions & 4 deletions docs/custom-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ Create custom rules to enforce your own policies, compliance requirements, or co
1. **Create a source folder** under `sources/`:

sources/
core/ # Project CodeGuard rules
owasp/ # OWASP supplementary rules
my-rules/ # Your custom rules
core/ # Project CodeGuard rules
additional-skills/
owasp/ # OWASP supplementary rules
my-rules/ # Your custom rules

2. **Copy the template** from `sources/templates/custom-rule-template.md.example` and customize it

Expand Down Expand Up @@ -45,7 +46,7 @@ Converts source rules to IDE-specific formats.
uv run python src/convert_to_ide_formats.py

# Include multiple sources
uv run python src/convert_to_ide_formats.py --source core owasp my-rules
uv run python src/convert_to_ide_formats.py --source core additional-skills/owasp my-rules

# Custom output directory
uv run python src/convert_to_ide_formats.py --source core my-rules -o build
Expand Down
4 changes: 2 additions & 2 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ This FAQ document provides clear, concise answers to help developers seamlessly

## Q: What are the OWASP supplementary rules?

**A:** The `sources/owasp/` folder contains supplementary rules based on OWASP guidance that informed the original rule development. These rules are optional, not enabled by default, and are intended primarily for reference and deeper security review use cases.
**A:** The `sources/additional-skills/owasp/` folder contains supplementary rules based on OWASP guidance that informed the original rule development. These rules are optional, not enabled by default, and are intended primarily for reference and deeper security review use cases.

The official release bundles package the main `sources/core/` rules. If you [build from source](getting-started.md#option-2-build-from-source) and want the OWASP supplementary set too, include it explicitly:

```bash
uv run python src/convert_to_ide_formats.py --source core owasp
uv run python src/convert_to_ide_formats.py --source core additional-skills/owasp
```

---
Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ uv run python src/validate_unified_rules.py sources/
uv run python src/convert_to_ide_formats.py

# Or include all rules (core + owasp supplementary)
uv run python src/convert_to_ide_formats.py --source core owasp
uv run python src/convert_to_ide_formats.py --source core additional-skills/owasp

# Copy the generated rules to your project
cp -r dist/.cursor/ /path/to/your/project/
Expand All @@ -287,7 +287,7 @@ cp -r dist/.hermes/ /path/to/your/project/
Project CodeGuard has two source rule sets:

- `sources/core/`: Official Project CodeGuard rules. These are the main rules packaged in releases and enabled by default.
- `sources/owasp/`: Supplementary rules originally derived from OWASP guidance. These are optional and are not enabled by default.
- `sources/additional-skills/owasp/`: Supplementary rules originally derived from OWASP guidance. These are optional and are not enabled by default.

Use OWASP supplementary rules when you explicitly want broader coverage, such as deeper security reviews or reference-driven review workflows.

Expand Down
131 changes: 131 additions & 0 deletions sources/additional-skills/memory-safe-migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
name: memory-safe-migration
description: >-
Guide secure migration of code from memory-unsafe languages (C, C++, Assembly)
to memory-safe languages (Rust, Go, Java, C#, Swift). Use when migrating or
rewriting legacy C/C++ code, designing FFI boundaries between safe and unsafe
code, writing new modules in existing C/C++ codebases, reviewing mixed-language
projects, planning memory safety roadmaps, or when an AI agent is about to
generate new C/C++ code that could be written in a memory-safe language instead.
Also triggers on CISA/NSA memory safety compliance discussions.
license: CC-BY-4.0
metadata:
author: codeguard-community
version: "1.0"
category: memory-safety
---

# Memory-safe language migration

## When this skill activates

- User asks to migrate, port, or rewrite C/C++ code to Rust, Go, Java, C#, or Swift
- User asks to add a new module or feature to an existing C/C++ project
- User asks to design an FFI boundary between safe and unsafe code
- User asks about memory safety roadmaps or CISA/NSA compliance
- User asks to review mixed-language code for safety issues
- AI agent is about to generate new C/C++ code — check if an MSL alternative is viable

## Decision: new code language selection

Before writing any new code, ask:

1. Is there an explicit constraint requiring C/C++? (bare-metal with no MSL runtime,
hard real-time below 1μs, existing codebase policy)
2. If no constraint exists, default to a memory-safe language
3. Select the target language using the guide in [references/language-selection.md](references/language-selection.md)

If the project is predominantly C/C++, write the new module in an MSL and integrate
via FFI. See [references/ffi-security.md](references/ffi-security.md) for boundary rules.

## Migration workflow

Follow these steps for every migration task:

### Step 1: Assess the component

Run the assessment script to evaluate migration priority and feasibility:

```bash
python scripts/assess-migration.py --file <source_file>
```

Or manually evaluate using the checklist in [references/assessment-checklist.md](references/assessment-checklist.md).

Priority order for migration:
1. Network-facing code (parsers, protocol handlers, TLS)
2. Code handling untrusted input (file parsers, deserialization)
3. Cryptographic implementations
4. Privilege boundary code (auth enforcement)
5. Code with a history of memory-related CVEs
6. Internal utility code

### Step 2: Write tests first

Never migrate a component without test coverage. If no tests exist, write them
against the C/C++ implementation before touching anything. These tests become the
correctness oracle for the new implementation.

### Step 3: Migrate incrementally

One function or module at a time. Never rewrite an entire codebase in one pass.
Follow the Android model: new code in MSL, existing stable code stays in place,
proportion of unsafe code decreases over time.

For common migration patterns (buffers, strings, concurrency, error handling),
see [references/migration-patterns.md](references/migration-patterns.md).

### Step 4: Secure the FFI boundary

Every interface between safe and unsafe code is a security boundary. Follow all
rules in [references/ffi-security.md](references/ffi-security.md). Key rules:

- Validate all inputs from the unsafe side (null checks, bounds checks, type checks)
- Minimize `unsafe` blocks — wrap only the minimum necessary operation
- Document every `unsafe` block with a `// SAFETY:` comment
- The allocator that created memory must free it — never mix allocators
- Never panic across FFI boundaries
- Catch all panics with `std::panic::catch_unwind` at FFI entry points

### Step 5: Validate

After every migration unit, verify:

- All existing tests pass against the new implementation
- No new `unsafe` surface without documented safety invariants
- FFI boundaries fuzzed with malformed inputs, null pointers, extreme lengths
- Memory safety tools run clean (Miri for Rust, race detector for Go, ASan for C side)
- Performance benchmarked against the original — no unacceptable regression
- All new MSL dependencies audited for trustworthiness and active maintenance

### Step 6: Update build and CI

- Integrate the MSL toolchain (cargo, go build, etc.) into the existing build system
- Add MSL-specific linting (`clippy` for Rust, `go vet` for Go)
- Add formatting checks (`rustfmt`, `gofmt`)
- Add safety-specific CI checks (deny `unsafe` without annotation, dependency audit)

## Anti-patterns to prevent

Never do these during migration:

- **Wrapping unsafe C in a "safe" API without actual safety guarantees** — if the
wrapper just passes through without validation, it provides false confidence
- **Using `unsafe` to replicate C-style patterns in Rust** — if extensive `unsafe`
is needed, the approach should be redesigned or the code should remain in C
- **Migrating without tests** — write tests for C/C++ first, then validate MSL version
- **Ignoring error handling differences** — C uses return codes, Rust uses `Result`,
Go uses multiple returns. Every error path must be explicitly mapped
- **Assuming GC languages need no resource discipline** — they prevent memory corruption
but can still leak file handles, sockets, and connections. Use `defer`, `try-with-resources`,
`using`, or `with` patterns
- **Migrating performance-critical loops without benchmarking** — verify first

## References

For detailed guidance on specific topics:

- [Language selection guide](references/language-selection.md)
- [FFI boundary security rules](references/ffi-security.md)
- [Common migration patterns](references/migration-patterns.md)
- [Assessment checklist](references/assessment-checklist.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Migration assessment checklist

Use this checklist to evaluate whether a component should be migrated, its priority,
and its feasibility. Score each category and sum for an overall migration priority.

## Priority scoring

### Vulnerability history (0-10 points)

- [ ] Count of memory-related CVEs in this component
- 0 CVEs: 0 points
- 1-2 CVEs: 3 points
- 3-5 CVEs: 6 points
- 6+ CVEs: 10 points
- [ ] Severity of past CVEs
- Mostly Low/Medium: no adjustment
- Any Critical/High: +2 points
- [ ] Recurrence of same bug class (e.g., buffer overflow fixed, then reappears): +2 points

### Exposure surface (0-10 points)

- [ ] Network-facing (accepts data from network): +4 points
- [ ] Processes untrusted input (user files, external APIs, deserialization): +3 points
- [ ] Handles cryptographic material (keys, certificates, random): +2 points
- [ ] Runs with elevated privileges (root, SYSTEM, kernel): +2 points
- [ ] Internal-only utility with no external input: 0 points

### Risk acceleration from AI (0-5 points)

- [ ] Component uses patterns known to be easily discoverable by AI fuzzing
(simple parsers, flat buffer handling): +3 points
- [ ] Component has limited exploit mitigations (no ASLR, no stack canaries,
no CFI): +2 points

### Total priority score

- **20+**: Critical — migrate immediately
- **15-19**: High — schedule for next development cycle
- **8-14**: Medium — plan for migration within the roadmap period
- **0-7**: Low — migrate opportunistically or when component is modified

## Feasibility evaluation

### Blockers (any of these may prevent migration)

- [ ] Inline assembly that cannot be replaced
- [ ] Hard real-time constraint below 1μs with no MSL equivalent
- [ ] Platform with no MSL compiler support (rare embedded targets)
- [ ] Regulatory or certification requirement mandating specific language
- [ ] Component is scheduled for end-of-life/replacement — migration not worthwhile

### Complexity factors (affect timeline, not feasibility)

- [ ] Lines of code in the component
- Under 1,000: Small — days to weeks
- 1,000-10,000: Medium — weeks to months
- 10,000-100,000: Large — months; consider incremental approach
- 100,000+: Very large — must be incremental; full rewrite not recommended
- [ ] Number of external C/C++ library dependencies
- Each dependency must have an MSL equivalent or be accessed via FFI
- List each dependency and its MSL alternative status
- [ ] Platform-specific system call usage
- List syscalls used; verify MSL support on all target platforms
- [ ] Existing test coverage
- No tests: must write tests first (add to timeline)
- Partial coverage: identify untested paths
- Comprehensive coverage: ready for migration validation

### Team readiness

- [ ] Team expertise in target MSL
- Expert: no training needed
- Intermediate: minor ramp-up
- Beginner: budget training time (2-4 weeks for productive Rust, 1-2 weeks for Go)
- None: consider hiring or partnering; do not migrate without expertise
- [ ] Availability of code review expertise in target MSL
- [ ] CI/CD pipeline supports target MSL toolchain

## Output

After assessment, produce a migration recommendation:

```
Component: [name]
Priority score: [X] / 25
Feasibility: [Go / Go with caveats / Blocked]
Blockers: [list any]
Recommended target language: [language + rationale]
Estimated effort: [T-shirt size + calendar estimate]
Dependencies requiring FFI: [list]
Test coverage gap: [description]
Recommended migration order: [which functions/modules first]
```
Loading
Loading