From d49cb5a6f9fc708d2a7e177ee046ab7bfc49da2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Botelho=20Gon=C3=A7alves?= Date: Tue, 10 Feb 2026 09:05:59 +0000 Subject: [PATCH] Revise contributing guidelines for performance and quality Expanded the contributing guidelines to emphasize performance standards, code quality, and the importance of benchmarks. Added sections on performance tiers, memory management, and common pitfalls. --- CONTRIBUTING.md | 176 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 138 insertions(+), 38 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d2078e..8affcf6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,26 +1,76 @@ -# Contributing to [RASP.Net](https://github.com/JVBotelho/RASP.Net) +# Contributing to RASP.Net -First of all, thank you for being here! RASP.Net is a project focused on the intersection of **Extreme Performance** and **Active Security**. To maintain our technical integrity, we follow a set of strict engineering standards. +Thank you for your interest in RASP.Net. This project explores the intersection of **extreme performance** and **active security** in .NET. Our goal is to prove that runtime protection doesn't require sacrificing throughput or latency. -## 🛡️ The Golden Rules +We welcome contributions from all skill levels, but we hold code to strict engineering standards. This document explains our performance philosophy and technical requirements. + +--- + +## 🎯 Why Performance Matters + +RASP.Net operates in the **request path** of high-throughput applications. In production: + +- A typical API responds in **2-5ms** +- Our total inspection budget must stay under **5% of response time** (~100-250μs) +- One poorly optimized detection can destroy SLA compliance + +We benchmark against physics, not intuition. + +### The Physics of Latency + +Understanding hardware limits is essential: + +| Operation | Latency | +|-----------|---------| +| L1 Cache Access | ~1 ns | +| L2 Cache Access | ~3-10 ns | +| Main Memory (RAM) | ~100 ns | +| Context Switch | ~1-2 μs | + +Your code operates in the **microsecond realm**. Design accordingly. + +--- + +## 📊 Performance Tiers + +We classify inspection logic into tiers based on **added latency** (p99). These align with real-world SLA requirements. + +| Tier | Latency Budget | Context | Examples | +|------|---------------|---------|----------| +| **🏎️ Tier 1 (Hot Path)** | **< 2 μs** | Header inspection, URL scanning, auth tokens | `SearchValues`, SIMD (AVX2/512), branchless logic | +| **🚀 Tier 2 (Standard)** | **< 20 μs** | JSON body inspection (<4KB), shallow parsing | `Utf8JsonReader`, zero-allocation parsers | +| **⚙️ Tier 3 (Deep)** | **< 100 μs** | Complex grammar analysis (SQL/XML), regex with backtracking | DFA regex, careful state machines | +| **❌ Rejected** | **> 200 μs** | Single-inspection overhead breaks user SLA | N/A | + +**Note:** If your PR falls into Tier 3 for hot-path code, we'll work with you during code review to identify optimizations (hidden allocations, boxing, inlining opportunities). + +--- + +## 🛡️ Code Standards ### 1. Zero Allocations on Hot Path -The **Hot Path** refers to the detection engine's core loops and interceptors where <10ns overhead is critical. Any code triggered during request inspection must not allocate memory on the managed heap. +The **Hot Path** refers to the detection engine's core loops and interceptors where low-latency is critical. Any code triggered during request inspection must not allocate memory on the managed heap. -* **Avoid:** `new`, string concatenation (`+`), LINQ, or `Task` allocations. -* **Use:** `Span`, `ReadOnlySpan`, `stackalloc`, or `ArrayPool`. +**Forbidden:** +- `new`, string concatenation (`+`), LINQ, or `Task` allocations +- `params object[]`, closures, boxing +- `async/await` state machines inside inspection loops -#### 💡 Memory Management Pattern +**Required:** +- `Span`, `ReadOnlySpan`, `stackalloc`, or `ArrayPool` -When handling variable-sized buffers, always use the hybrid approach. Use the **Stack** for small payloads and the **ArrayPool** for larger ones. This avoids heap allocations while protecting against `StackOverflowException`. +#### 💡 Memory Management Pattern +When handling variable-sized buffers, always use the hybrid approach. Use the **Stack** for small payloads and the **ArrayPool** for larger ones. This avoids heap allocations while protecting against `StackOverflowException`. ```csharp -// 1. Safety check: avoid invalid or empty allocations -if (maxSize <= 0) return; +// Safety check: avoid invalid allocations or DoS attempts +// RASP should never inspect massive payloads in-memory. +const int MaxInspectionLimit = 32 * 1024; // 32KB Hard Limit +if (maxSize <= 0 || maxSize > MaxInspectionLimit) return; // 2. Define a safe threshold for stack allocation -const int StackThreshold = 256; +const int StackThreshold = 512; Span buffer; byte[]? rented = null; @@ -43,7 +93,7 @@ try } finally { - // 3. Critical: Always return rented memory to avoid leaks + // Critical: Always return rented memory to avoid leaks if (rented is not null) { // Use clearArray: true ONLY if the buffer contains sensitive data (e.g., passwords) @@ -51,36 +101,64 @@ finally } } ``` + > **Notes:** -> - The maxSize <= 0 check is our "safety belt" against runtime exceptions and potential memory corruption triggers. -> - The 256-byte threshold is a conservative guard to avoid excessive stack usage and is not a hard rule. -> - Do not use stackalloc across async/await boundaries. -> - For maxSize <= 0, the operation is a no-op by design. +> - The `maxSize <= 0` check is our "safety belt" against runtime exceptions and potential memory corruption triggers. +> - The 512-byte threshold is a conservative guard to avoid excessive stack usage and is not a hard rule. +> - Do not use `stackalloc` across `async/await` boundaries. +> - For `maxSize <= 0`, the operation is a no-op by design. -### 2. Benchmark or it didn't happen +--- -Every detection logic change **must** include a [BenchmarkDotNet](https://benchmarkdotnet.org/) report in the Pull Request description. We prioritize **p95 and p99.9 latency**. +### 2. Benchmarks Are Mandatory -### 3. English Only +Every detection logic change **must** include a [BenchmarkDotNet](https://benchmarkdotnet.org/) report in the PR description. We prioritize **p95 and p99.9 latency**. -All code documentation (XML docs), error messages, and commit messages must be in English. This ensures that all global contributors and users can understand and audit the security logic effectively. +**Fail conditions:** +- Gen0/Gen1/Gen2 columns show anything other than `-` (zero) on hot path +- p99 latency regression > 10% vs baseline + +**Pass criteria:** +- Overhead within ±5% of baseline +- Zero allocations confirmed + +Run: `dotnet run -c Release --project src/Rasp.Benchmarks` --- -## 📊 Performance Tiers (The "Race Track") +### 3. Security Test Suite -We don't reject code simply because it doesn't hit the ideal nanoseconds on the first try. Instead, we classify contributions into **Tiers**. Our goal is to help you "tune" your code to Tier 1 through technical mentorship during Code Review. +Run the exploit suite before opening a PR: +```bash +dotnet test +``` -| Tier | Latency Overhead | Status | -| --- | --- | --- | -| **🏎️ Elite (Tier 1)** | **< 10ns** | **Hot Path Ready.** Our gold standard. Essential for the core detection engine. | -| **🚀 Optimal (Tier 2)** | **10ns - 50ns** | **Feature Ready.** Acceptable for complex inspections, nested objects, or conditional logic. | -| **🐢 Standard (Tier 3)** | **> 50ns** | **Review Required.** Requires architectural discussion or optimization (e.g., SIMD or Source Generators). | +**Requirement:** 100% block rate on known attack vectors. Security is non-negotiable. -**How it works:** +--- + +### 4. Thread Safety + +The RASP engine is a singleton. All state must be: +- Immutable (`readonly`, `init`) +- Thread-safe (use `Interlocked`, `FrozenDictionary`, or `ConcurrentDictionary`) + +--- + +### 5. English Only + +All code documentation (XML docs), error messages, and commit messages must be in English. This ensures that all global contributors and users can understand and audit the security logic effectively. + +--- + +## 🚀 Pull Request Process -* If your PR falls into **Tier 3**, we will work with you to identify bottlenecks (hidden allocations, boxing, lack of inlining). -* Every new feature should strive to move up the tiers before being merged into the `develop` branch. +1. **Branching:** Create your feature branch from `develop`. The `master` branch is reserved for stable releases. +2. **Draft PRs:** We encourage opening a **Draft PR** early in the process to discuss architectural decisions before finalizing the code. +3. **Code Quality:** Ensure [CodeQL](https://codeql.github.com/) scans pass without new security alerts. +4. **ADR Updates:** If your PR introduces structural changes, please update or create a new **ADR (Architecture Decision Record)** in the `docs/ADR` folder. + +We value **collaboration over gatekeeping**. If your PR needs optimization, we'll help during code review. --- @@ -92,14 +170,24 @@ If you found a bug or have a suggestion for improvement: 2. **Provide a minimal reproducible example** (ideally a unit test or a small console app). 3. **Include your environment details**: .NET version, OS, and hardware (especially for performance-related issues). +When reporting bugs, please provide: +- **Full stack trace** with line numbers +- **Environment:** OS, architecture (x64/ARM64), .NET version +- **Minimal repro:** Failing unit test or small console app + --- -## 🚀 Pull Request Process +## ⚠️ Common Pitfalls -1. **Branching**: Create your feature branch from `develop`. The `master` branch is reserved for stable releases. -2. **Draft PRs**: We encourage opening a **Draft PR** early in the process to discuss architectural decisions before finalizing the code. -3. **Code Quality**: Ensure [CodeQL](https://codeql.github.com/) scans pass without new security alerts. -4. **ADR Updates**: If your PR introduces structural changes, please update or create a new **ADR (Architecture Decision Record)** in the `docs/ADR` folder. +These patterns will require revision before merge: + +| Anti-Pattern | Why It's Problematic | Better Alternative | +|--------------|---------------------|-------------------| +| `input.Contains("