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("