626927d
commit 626927d
10 files changed
+686 -0
Showing 10 changed files+686-0
▼.well-known/security.txt
+10-0
| @@ -0,0 +1,10 @@ | ||
1 | +# Security policy for JustAPI | |
2 | +# https://justapi.dev/.well-known/security.txt | |
3 | + | |
4 | +Contact: mailto:[email protected] | |
5 | +Encryption: https://justapi.dev/pgp-key.txt | |
6 | +Preferred-Languages: en | |
7 | +Canonical: https://justapi.dev/.well-known/security.txt | |
8 | +Policy: https://justapi.dev/docs/security/policy.md | |
9 | +Hiring: https://justapi.dev/careers | |
10 | +Expires: 2027-07-05T00:00:00Z | |
0 | 11 | |
▼docs/api_reference.md
+101-0
| @@ -0,0 +1,101 @@ | ||
1 | +# API Reference | |
2 | + | |
3 | +Welcome to the JustAPI API Reference. This document details the core classes and methods available in the framework. | |
4 | + | |
5 | +## `JustAPIApp` | |
6 | + | |
7 | +The `JustAPIApp` is the core of your application. It acts as the registry for all your routes, middleware, and plugins. | |
8 | + | |
9 | +### Initialization | |
10 | + | |
11 | +```python | |
12 | +from justapi import JustAPIApp | |
13 | + | |
14 | +app = JustAPIApp() | |
15 | +``` | |
16 | + | |
17 | +### Methods | |
18 | + | |
19 | +- `get(path, dependencies=None)`: Register a GET route. | |
20 | +- `post(path, body_schema=None, schema=None, dependencies=None)`: Register a POST route. | |
21 | +- `put(path, body_schema=None, schema=None, dependencies=None)`: Register a PUT route. | |
22 | +- `patch(path, body_schema=None, schema=None, dependencies=None)`: Register a PATCH route. | |
23 | +- `delete(path, dependencies=None)`: Register a DELETE route. | |
24 | +- `include_router(router, prefix="")`: Include routes from an `APIRouter`. | |
25 | +- `run(addr)`: Start the server on the given address (e.g., `"127.0.0.1:8000"`). | |
26 | +- `add_exception_handler(exc_class, handler)`: Register a custom exception handler. | |
27 | + | |
28 | +**Example: Basic Routing** | |
29 | +```python | |
30 | +@app.get("/users/{user_id}") | |
31 | +async def get_user(user_id: int): | |
32 | + return {"user_id": user_id} | |
33 | +``` | |
34 | + | |
35 | +## `APIRouter` | |
36 | + | |
37 | +`APIRouter` is used to group related routes together. It helps in building modular, large-scale applications. | |
38 | + | |
39 | +### Methods | |
40 | + | |
41 | +It supports the same routing methods as `JustAPIApp`: `get`, `post`, `put`, `patch`, and `delete`. | |
42 | + | |
43 | +**Example: Using APIRouter** | |
44 | +```python | |
45 | +from justapi import APIRouter | |
46 | + | |
47 | +user_router = APIRouter() | |
48 | + | |
49 | +@user_router.get("/") | |
50 | +async def list_users(): | |
51 | + return [{"name": "Alice"}, {"name": "Bob"}] | |
52 | + | |
53 | +app.include_router(user_router, prefix="/users") | |
54 | +``` | |
55 | + | |
56 | +## Dependency Injection (DI) & Parameters | |
57 | + | |
58 | +Extract variables directly from the request seamlessly: | |
59 | + | |
60 | +- `Path(...)`: Extract variables explicitly from the URL path. | |
61 | +- `Query(...)`: Extract values from query parameters. | |
62 | +- `Header(...)`: Extract values from HTTP headers. | |
63 | +- `Cookie(...)`: Extract from cookies. | |
64 | +- `Body(...)`: Extract from JSON body. | |
65 | +- `Depends(dependency)`: Inject a dependency function. | |
66 | + | |
67 | +**Example: Using Depends** | |
68 | +```python | |
69 | +from justapi import Depends | |
70 | + | |
71 | +def get_db_session(): | |
72 | + return "db_session" | |
73 | + | |
74 | +@app.get("/items/") | |
75 | +async def read_items(db=Depends(get_db_session)): | |
76 | + return {"db": db} | |
77 | +``` | |
78 | + | |
79 | +## File Uploads & Forms | |
80 | + | |
81 | +JustAPI provides robust parsing for multipart and url-encoded forms: | |
82 | + | |
83 | +- `File(...)`: Extract a file from `multipart/form-data`. | |
84 | +- `Form(...)`: Extract a form field. | |
85 | +- `UploadFile`: Represents an uploaded file with methods like `.read()`. | |
86 | + | |
87 | +## Responses | |
88 | + | |
89 | +JustAPI provides multiple response classes optimized for zero-copy data transfer from Rust to Python: | |
90 | + | |
91 | +- `Response(content, status_code, headers)`: Base response class. | |
92 | +- `JSONResponse(content)`: Automatically serializes a Python dictionary to JSON. | |
93 | +- `HTMLResponse(content)`: Sets the `Content-Type` header to `text/html`. | |
94 | +- `PlainTextResponse(content)`: Sets the `Content-Type` header to `text/plain`. | |
95 | +- `RedirectResponse(url, status_code=307)`: Returns an HTTP redirect. | |
96 | +- `StreamingResponse(generator)`: Emits streaming bodies (e.g., for large files or Server-Sent Events). | |
97 | + | |
98 | +## Exceptions | |
99 | + | |
100 | +- `HTTPException(status_code: int, detail: str)`: Raise this to return an HTTP error (e.g., 404 Not Found). | |
101 | +- `RequestValidationError(errors: list)`: Raised automatically when Pydantic validation fails. | |
0 | 102 | |
▼docs/getting_started.md
+92-0
| @@ -0,0 +1,92 @@ | ||
1 | +# Getting Started | |
2 | + | |
3 | +This guide will walk you through building your first web application with JustAPI. | |
4 | + | |
5 | +## Installation | |
6 | + | |
7 | +Install JustAPI using `pip`: | |
8 | + | |
9 | +```bash | |
10 | +pip install justapi | |
11 | +``` | |
12 | + | |
13 | +We also recommend installing `pydantic` for data validation: | |
14 | + | |
15 | +```bash | |
16 | +pip install pydantic | |
17 | +``` | |
18 | + | |
19 | +## Your First Application | |
20 | + | |
21 | +Create a file named `main.py` and add the following code: | |
22 | + | |
23 | +```python | |
24 | +from justapi import JustAPIApp | |
25 | +from pydantic import BaseModel | |
26 | + | |
27 | +# Initialize the application | |
28 | +app = JustAPIApp() | |
29 | + | |
30 | +# Define a Pydantic schema for validation | |
31 | +class Item(BaseModel): | |
32 | + name: str | |
33 | + price: float | |
34 | + is_offer: bool = None | |
35 | + | |
36 | +# Create a basic GET route | |
37 | +@app.get("/") | |
38 | +async def read_root(): | |
39 | + return {"Hello": "World"} | |
40 | + | |
41 | +# Create a route with path parameters | |
42 | +@app.get("/items/{item_id}") | |
43 | +async def read_item(item_id: int, q: str = None): | |
44 | + return {"item_id": item_id, "q": q} | |
45 | + | |
46 | +# Create a POST route with body validation | |
47 | +@app.post("/items/") | |
48 | +async def create_item(item: Item): | |
49 | + return {"item_name": item.name, "item_price": item.price} | |
50 | + | |
51 | +if __name__ == "__main__": | |
52 | + # Start the high-performance Rust server | |
53 | + app.run("127.0.0.1:8000") | |
54 | +``` | |
55 | + | |
56 | +## Running the Server | |
57 | + | |
58 | +Run your application from the terminal: | |
59 | + | |
60 | +```bash | |
61 | +python main.py | |
62 | +``` | |
63 | + | |
64 | +You should see output indicating that the Rust Tokio runtime has initialized and the server is listening on `127.0.0.1:8000`. | |
65 | + | |
66 | +## Testing the API | |
67 | + | |
68 | +You can test your API using tools like `curl`: | |
69 | + | |
70 | +**GET Request:** | |
71 | +```bash | |
72 | +curl http://127.0.0.1:8000/ | |
73 | +# Output: {"Hello": "World"} | |
74 | +``` | |
75 | + | |
76 | +**GET Request with parameters:** | |
77 | +```bash | |
78 | +curl "http://127.0.0.1:8000/items/5?q=somequery" | |
79 | +# Output: {"item_id": 5, "q": "somequery"} | |
80 | +``` | |
81 | + | |
82 | +**POST Request with JSON body:** | |
83 | +```bash | |
84 | +curl -X POST http://127.0.0.1:8000/items/ \ | |
85 | + -H "Content-Type: application/json" \ | |
86 | + -d '{"name": "Laptop", "price": 999.99}' | |
87 | +# Output: {"item_name": "Laptop", "item_price": 999.99} | |
88 | +``` | |
89 | + | |
90 | +## Next Steps | |
91 | + | |
92 | +Now that you have a basic application running, check out the [API Reference](api_reference.md) to explore routing, dependency injection, and advanced features. | |
0 | 93 | |
▼docs/index.md
+39-0
| @@ -0,0 +1,39 @@ | ||
1 | +# JustAPI Documentation | |
2 | + | |
3 | +Welcome to the official documentation for **JustAPI**, a high-performance Python web framework built on top of a powerful Rust core. | |
4 | + | |
5 | +JustAPI is designed to be a drop-in replacement for FastAPI but engineered to handle extreme throughput—achieving up to **700k Requests Per Second (RPS)** without breaking a sweat. | |
6 | + | |
7 | +## Why JustAPI? | |
8 | + | |
9 | +### 🚀 Rust Core Performance | |
10 | +The entire HTTP server, routing engine, and protocol parsing are written in Rust using highly optimized crates like `tokio` and `hyper`. This ensures that connection handling is as fast and secure as theoretically possible. | |
11 | + | |
12 | +### 🐍 Python Ergonomics | |
13 | +You get the raw performance of Rust with the beautiful, developer-friendly ergonomics of Python. You write standard Python using familiar concepts like `JustAPIApp`, `@app.get`, and Pydantic schemas for data validation. | |
14 | + | |
15 | +### ⚡ Zero-Copy Architecture | |
16 | +JustAPI uses a highly optimized boundary between Rust and Python (via PyO3). By implementing the Python Buffer Protocol, the framework avoids unnecessary memory allocations and copies, making it incredibly memory-efficient. | |
17 | + | |
18 | +### 🔄 100% Async | |
19 | +Built entirely on `async/await` principles. JustAPI seamlessly bridges Rust's Tokio runtime with Python's native `asyncio` event loop. | |
20 | + | |
21 | +## Performance Matrix | |
22 | + | |
23 | +JustAPI obliterates traditional frameworks under load. Measured on an Intel Core i5-13600K against the Uvicorn+FastAPI baseline: | |
24 | + | |
25 | +| Metric / Workload | Uvicorn + FastAPI | JustAPI (Native Python) | Improvement | | |
26 | +|-------------------|-------------------|-------------------------|-------------| | |
27 | +| **Hello-World (GET)** throughput | 36,189 req/sec | **324,130 req/sec** | **~9x Faster** | | |
28 | +| **Hello-World (GET)** p99 latency | 24.63 ms | **1.10 ms** | **~22x Lower** | | |
29 | +| **JSON-Echo (POST)** throughput | 26,000 req/sec | **267,846 req/sec** | **~10x Faster** | | |
30 | +| **JSON-Echo (POST)** p99 latency | 14.50 ms | **1.64 ms** | **~9x Lower** | | |
31 | + | |
32 | +*(Note: JustAPI achieves these numbers in a single process without multi-worker fan-out.)* | |
33 | + | |
34 | +## Where to go next? | |
35 | + | |
36 | +- **[Getting Started](getting_started.md):** Build your first JustAPI application in minutes. | |
37 | +- **[Migrating from FastAPI](migrating_from_fastapi.md):** See how easy it is to switch your existing FastAPI project to JustAPI. | |
38 | +- **[API Reference](api_reference.md):** Detailed information about all the classes and functions available. | |
39 | +- **[Plugins](plugins.md):** Learn how to extend JustAPI using Python or Rust. | |
0 | 40 | |
▼docs/migrating_from_fastapi.md
+41-0
| @@ -0,0 +1,41 @@ | ||
1 | +# Migrating from FastAPI | |
2 | + | |
3 | +JustAPI aims for high compatibility with FastAPI. In most cases, migration is as simple as changing imports. | |
4 | + | |
5 | +## Import Changes | |
6 | + | |
7 | +```python | |
8 | +# FastAPI | |
9 | +from fastapi import FastAPI, Depends, HTTPException | |
10 | + | |
11 | +# JustAPI | |
12 | +from justapi import JustAPIApp, Depends, HTTPException | |
13 | +``` | |
14 | + | |
15 | +## The Application Object | |
16 | + | |
17 | +Replace `FastAPI()` with `JustAPIApp()`: | |
18 | + | |
19 | +```python | |
20 | +# FastAPI | |
21 | +app = FastAPI() | |
22 | + | |
23 | +# JustAPI | |
24 | +app = JustAPIApp() | |
25 | +``` | |
26 | + | |
27 | +## Middlewares | |
28 | + | |
29 | +Middleware in JustAPI acts exactly like FastAPI middlewares using the `http` interceptor: | |
30 | + | |
31 | +```python | |
32 | +@app.middleware("http") | |
33 | +async def process_time_header(request, call_next): | |
34 | + # Your logic | |
35 | + response = await call_next(request) | |
36 | + return response | |
37 | +``` | |
38 | + | |
39 | +## Performance Differences | |
40 | + | |
41 | +Once you switch, you should immediately notice a dramatic drop in CPU overhead for routing and connection handling, translating to much higher throughput under load. | |
0 | 42 | |
▼docs/plugins.md
+105-0
| @@ -0,0 +1,105 @@ | ||
1 | +# JustAPI Plugin System | |
2 | + | |
3 | +JustAPI provides a powerful plugin system that allows you to extend the framework with custom functionality. Plugins can be written in either Rust (for maximum performance) or Python (for flexibility and ease of use). | |
4 | + | |
5 | +## Python Plugins | |
6 | + | |
7 | +Python plugins are the simplest way to extend JustAPI. A Python plugin is simply a class that implements one or more of the following hooks: | |
8 | + | |
9 | +- `build(self, app)`: Called when the plugin is registered with `app.use()`. You can use this to add routes, middleware, or modify the app configuration. | |
10 | +- `on_startup(self)`: Called asynchronously just before the server starts accepting requests. Useful for establishing database connections, starting background tasks, or warming up caches. | |
11 | +- `on_shutdown(self)`: Called asynchronously when the server is shutting down. Useful for cleaning up resources, closing connections, or saving state. | |
12 | + | |
13 | +### Example: Simple Authentication Plugin | |
14 | + | |
15 | +```python | |
16 | +from justapi import JustAPIApp | |
17 | + | |
18 | +class SimpleAuthPlugin: | |
19 | + def __init__(self, token: str): | |
20 | + self.expected_token = token | |
21 | + | |
22 | + def build(self, app: JustAPIApp): | |
23 | + print("Auth plugin registered.") | |
24 | + | |
25 | + async def on_startup(self): | |
26 | + print("Auth plugin initialized.") | |
27 | + | |
28 | + async def on_shutdown(self): | |
29 | + print("Auth plugin shutting down.") | |
30 | + | |
31 | + def authenticate(self, request): | |
32 | + token = request["headers"].get(b"authorization") | |
33 | + if token != f"Bearer {self.expected_token}".encode(): | |
34 | + return {"status": 401, "body": b'{"error":"unauthorized"}'} | |
35 | + return None | |
36 | + | |
37 | +app = JustAPIApp() | |
38 | +auth = SimpleAuthPlugin(token="secret123") | |
39 | +app.use(auth) | |
40 | + | |
41 | +# Use the plugin logic in a route | |
42 | +def secure_route(request): | |
43 | + err = auth.authenticate(request) | |
44 | + if err: | |
45 | + return err | |
46 | + return {"message": "secure data"} | |
47 | + | |
48 | +app.get("/secure", secure_route) | |
49 | +``` | |
50 | + | |
51 | +## Rust Plugins | |
52 | + | |
53 | +For performance-critical extensions (like custom protocols, low-level middleware, or custom allocators), you can write Rust plugins. Rust plugins must implement the `justapi_core::plugin::Plugin` trait and are statically registered using the `inventory` crate. | |
54 | + | |
55 | +### The `Plugin` Trait | |
56 | + | |
57 | +```rust | |
58 | +use justapi_core::plugin::Plugin; | |
59 | +use async_trait::async_trait; | |
60 | +use anyhow::Result; | |
61 | + | |
62 | +pub struct MyRustPlugin; | |
63 | + | |
64 | +#[async_trait] | |
65 | +impl Plugin for MyRustPlugin { | |
66 | + fn name(&self) -> &'static str { | |
67 | + "MyRustPlugin" | |
68 | + } | |
69 | + | |
70 | + async fn on_startup(&self) -> Result<()> { | |
71 | + println!("Rust plugin startup!"); | |
72 | + Ok(()) | |
73 | + } | |
74 | + | |
75 | + async fn on_shutdown(&self) -> Result<()> { | |
76 | + println!("Rust plugin shutdown!"); | |
77 | + Ok(()) | |
78 | + } | |
79 | +} | |
80 | +``` | |
81 | + | |
82 | +### Registration | |
83 | + | |
84 | +To register your Rust plugin, use `inventory::submit!`: | |
85 | + | |
86 | +```rust | |
87 | +use justapi_core::plugin::PluginRegistration; | |
88 | +use std::sync::Arc; | |
89 | + | |
90 | +inventory::submit! { | |
91 | + PluginRegistration::new(|| Arc::new(MyRustPlugin)) | |
92 | +} | |
93 | +``` | |
94 | + | |
95 | +When `Server::run()` is called, JustAPI will automatically discover all registered plugins and invoke their lifecycle hooks in order. | |
96 | + | |
97 | +## Plugin Marketplace | |
98 | + | |
99 | +To publish a JustAPI Python plugin to the broader community, simply publish it to PyPI with the `justapi-plugin` keyword. | |
100 | +Users can then install it via `pip install justapi-plugin-yourname` and use it as standard: | |
101 | + | |
102 | +```python | |
103 | +from justapi_plugin_yourname import YourPlugin | |
104 | +app.use(YourPlugin()) | |
105 | +``` | |
0 | 106 | |
▼docs/security/owasp-checklist.md
+86-0
| @@ -0,0 +1,86 @@ | ||
1 | +# OWASP Top 10 (2021) Compliance Checklist | |
2 | + | |
3 | +## A01:2021 – Broken Access Control | |
4 | +- [x] Route-level access via middleware chain (JwtAuth, custom auth middleware) | |
5 | +- [x] CORS middleware with configurable `allow_origin` | |
6 | +- [ ] Per-route authorization middleware | |
7 | +- [ ] Rate limiting per authenticated user (not just per-IP) | |
8 | + | |
9 | +## A02:2021 – Cryptographic Failures | |
10 | +- [x] TLS via rustls 0.23 (TLS 1.2/1.3 only, no legacy protocols) | |
11 | +- [x] HSTS header with configurable `max-age` and optional `includeSubDomains`/`preload` | |
12 | +- [x] JWT signing and verification with HS256/RS256/ES256 | |
13 | +- [x] Secrets management module (`secrets.rs`): env/file/inline with no logging of values | |
14 | +- [x] Password/secret rotation via env var or file re-read on restart | |
15 | +- [ ] Key rotation without restart (hot-reload) | |
16 | + | |
17 | +## A03:2021 – Injection | |
18 | +- [x] SQL injection prevention: parameterized queries via `sqlx` (never string interpolation) | |
19 | +- [x] JSON Schema validation rejects unexpected types | |
20 | +- [x] XSS prevention: `X-XSS-Protection: 0` (modern XSS prevention is via CSP) | |
21 | +- [x] Content-Type sniffing prevention: `X-Content-Type-Options: nosniff` | |
22 | +- [ ] HTML sanitization if rendering user content | |
23 | +- [ ] Command injection prevention (no `std::process::Command` by default) | |
24 | + | |
25 | +## A04:2021 – Insecure Design | |
26 | +- [x] Rate limiting: global (`RateLimiter`) and per-IP (`IpRateLimiter`) | |
27 | +- [x] Circuit breaker pattern for external service calls | |
28 | +- [x] Timeout middleware (504 Gateway Timeout) | |
29 | +- [x] Graceful degradation via `FallbackMiddleware` | |
30 | +- [x] Bulkhead pattern for concurrent request limiting | |
31 | +- [x] Graceful shutdown (SIGTERM → drain → stop) | |
32 | +- [ ] Request size limits (max body size middleware) | |
33 | +- [ ] Request depth limits (e.g., max JSON nesting depth) | |
34 | + | |
35 | +## A05:2021 – Security Misconfiguration | |
36 | +- [x] CORS with configurable origins, methods, headers | |
37 | +- [x] Security headers: `X-Content-Type-Options`, `X-Frame-Options`, `Strict-Transport-Security`, `Content-Security-Policy` | |
38 | +- [x] Non-root user in Docker image | |
39 | +- [x] HEALTHCHECK in Dockerfile | |
40 | +- [ ] Automated security header check in CI | |
41 | +- [ ] Default-deny CORS (not `*` in production) | |
42 | + | |
43 | +## A06:2021 – Vulnerable and Outdated Components | |
44 | +- [x] `cargo-audit` in CI (vulnerability scanning) | |
45 | +- [x] `cargo-deny` in CI (license + advisory checks) | |
46 | +- [x] Dependabot for automated dependency updates | |
47 | +- [x] Supply chain: lockfile committed, `deny.toml` configured | |
48 | +- [ ] Trivy scanning in CI for Docker image vulnerabilities | |
49 | +- [ ] SBOM generation for Docker images | |
50 | + | |
51 | +## A07:2021 – Identification and Authentication Failures | |
52 | +- [x] JWT authentication middleware with configurable validation | |
53 | +- [x] OAuth2/OIDC support via custom middleware | |
54 | +- [ ] Session management (stateless JWT only; no server-side sessions) | |
55 | +- [ ] Multi-factor authentication support | |
56 | +- [ ] Password brute-force protection (per-IP rate limiter covers this partially) | |
57 | + | |
58 | +## A08:2021 – Software and Data Integrity Failures | |
59 | +- [x] Supply chain: lockfile, `cargo-deny`, Dependabot | |
60 | +- [ ] CI/CD pipeline signing (sigstore/cosign) | |
61 | +- [ ] Package provenance (SLSA level 1+) | |
62 | +- [ ] Plugin signature verification (Phase 19) | |
63 | + | |
64 | +## A09:2021 – Security Logging and Monitoring Failures | |
65 | +- [x] Structured logging (JSON or text format) | |
66 | +- [x] Audit logging middleware (POST/PUT/DELETE/PATCH logging) | |
67 | +- [x] Prometheus metrics including status codes and latency histograms | |
68 | +- [x] Health check endpoints (`/health`, `/live`, `/ready`) | |
69 | +- [x] Alerting: Slack, PagerDuty, Generic webhook | |
70 | +- [x] OpenTelemetry tracing integration | |
71 | +- [ ] Centralized log aggregation documentation | |
72 | +- [ ] Alert on 5xx rate increase | |
73 | + | |
74 | +## A10:2021 – Server-Side Request Forgery (SSRF) | |
75 | +- [ ] URL validation middleware for outbound requests | |
76 | +- [ ] Allow-list of outbound hosts | |
77 | +- [ ] No user-controlled URL fetching by default | |
78 | + | |
79 | +## Legend | |
80 | +- [x] Implemented | |
81 | +- [ ] Planned / not yet implemented | |
82 | +- [ ] Not applicable | |
83 | + | |
84 | +--- | |
85 | + | |
86 | +_Last updated: 2026-07-05_ | |
0 | 87 | |
▼docs/security/pentest-guide.md
+143-0
| @@ -0,0 +1,143 @@ | ||
1 | +# Penetration Test Guidelines | |
2 | + | |
3 | +## Attack Surface | |
4 | + | |
5 | +JustAPI exposes the following attack surface: | |
6 | + | |
7 | +| Component | Description | Port | | |
8 | +| --------- | ----------- | ---- | | |
9 | +| HTTP/HTTPS server | Main application server | 8080 (configurable) | | |
10 | +| WebSocket endpoint | `/ws` upgrade path | Same as HTTP | | |
11 | +| SSE endpoint | `/events` streaming | Same as HTTP | | |
12 | +| Health endpoints | `/health`, `/live`, `/ready` | Same as HTTP | | |
13 | +| Metrics endpoint | `/metrics` (Prometheus) | Same as HTTP | | |
14 | +| Static file server | Configured `static/` directory | Same as HTTP | | |
15 | +| OpenAPI docs | `/docs`, `/redoc` (Phase 18) | Same as HTTP | | |
16 | +| Database | PostgreSQL/SQLite/MySQL | 5432/3306 (external) | | |
17 | +| Jaeger (dev) | Distributed tracing UI | 16686 (dev only) | | |
18 | + | |
19 | +## Test Scenarios | |
20 | + | |
21 | +### 1. Authentication & Authorization | |
22 | + | |
23 | +- **JWT forgery**: Attempt requests with malformed, expired, algorithm-confusion, and `none`-algorithm tokens | |
24 | +- **Missing auth**: Access protected routes without any Authorization header | |
25 | +- **Token replay**: Capture a valid token and replay it from a different IP | |
26 | +- **CORS bypass**: Send cross-origin requests with `Origin:` headers not in the allow list | |
27 | + | |
28 | +### 2. Input Validation | |
29 | + | |
30 | +- **JSON injection**: Send malformed JSON, deeply nested JSON (>100 levels), duplicate keys, large payloads (>10MB) | |
31 | +- **SQL injection**: Inject SQL into query parameters, path parameters, and request body fields (`' OR 1=1 --`, UNION-based, time-based blind) | |
32 | +- **NoSQL injection**: If any NoSQL paths exist, test for operator injection (`$gt`, `$ne`, `$where`) | |
33 | +- **Path traversal**: Send `../` sequences in URL paths and static file requests; URL-encoded variants (`%2e%2e%2f`, `..%252f`) | |
34 | +- **Parameter pollution**: Duplicate query parameters (`?id=1&id=2`); different types (`?id[]=1`) | |
35 | + | |
36 | +### 3. Session Management | |
37 | + | |
38 | +- **JWT weak secrets**: Attempt to crack the signing key with common wordlists | |
39 | +- **JWT claims manipulation**: Modify `sub`, `iat`, `exp`, `admin` or role claims after decoding | |
40 | +- **Token lifetime**: Verify expired tokens are rejected; tokens issued far in the future | |
41 | + | |
42 | +### 4. Rate Limiting & DoS | |
43 | + | |
44 | +- **Global rate limit**: Flood the server from a single IP to verify `RateLimiter` kicks in (429 + `Retry-After`) | |
45 | +- **Per-IP rate limit**: Use `IpRateLimiter` test — verify 429 after exceeding per-IP burst | |
46 | +- **Bulkhead saturation**: Open many concurrent connections to verify the bulkhead returns 503 | |
47 | +- **Slow loris**: Open many connections and send data slowly (low `bytes/sec`) — verify timeout middleware triggers 504 | |
48 | +- **Resource exhaustion**: Send requests that trigger large allocations (deep JSON, large file requests) | |
49 | + | |
50 | +### 5. TLS & Network | |
51 | + | |
52 | +- **Downgrade attack**: Attempt to negotiate TLS 1.1 or 1.0 (should fail – rustls supports 1.2/1.3 only) | |
53 | +- **Weak cipher suites**: Attempt connection with `NULL` cipher, `EXPORT` cipher, or `RC4` (should fail) | |
54 | +- **Certificate validation**: Present a self-signed, expired, or wrong-domain certificate (should fail) | |
55 | +- **Host header injection**: Send requests with manipulated `Host:` headers | |
56 | + | |
57 | +### 6. Information Disclosure | |
58 | + | |
59 | +- **Stack traces**: Trigger unhandled errors and verify no stack trace is leaked in responses | |
60 | +- **Debug endpoints**: Verify `/metrics`, health endpoints don't leak sensitive data | |
61 | +- **Error messages**: Verify validation errors don't reveal internal schema or implementation details | |
62 | +- **Server header**: Verify `Server` header is not present or is generic | |
63 | +- **Timing attacks**: Measure response time differences for valid vs. invalid authentication tokens | |
64 | + | |
65 | +### 7. Security Headers | |
66 | + | |
67 | +Verify all responses include: | |
68 | + | |
69 | +``` | |
70 | +X-Content-Type-Options: nosniff | |
71 | +X-Frame-Options: DENY | |
72 | +Strict-Transport-Security: max-age=31536000; includeSubDomains (optional: preload) | |
73 | +Content-Security-Policy: default-src 'self' (configurable) | |
74 | +X-XSS-Protection: 0 | |
75 | +``` | |
76 | + | |
77 | +### 8. Fuzz Testing | |
78 | + | |
79 | +Run the cargo-fuzz targets from `fuzz/`: | |
80 | + | |
81 | +```bash | |
82 | +# Install cargo-fuzz (nightly) | |
83 | +rustup toolchain install nightly | |
84 | +cargo install cargo-fuzz | |
85 | + | |
86 | +# Run fuzz targets | |
87 | +cargo fuzz run fuzz_jwt -- -max_total_time=300 | |
88 | +cargo fuzz run fuzz_headers -- -max_total_time=300 | |
89 | +cargo fuzz run fuzz_body -- -max_total_time=300 | |
90 | +cargo fuzz run fuzz_router -- -max_total_time=300 | |
91 | +cargo fuzz run fuzz_query_params -- -max_total_time=300 | |
92 | +cargo fuzz run fuzz_file_paths -- -max_total_time=300 | |
93 | +``` | |
94 | + | |
95 | +### 9. Supply Chain | |
96 | + | |
97 | +- Verify `cargo audit` passes with zero advisories | |
98 | +- Verify `cargo deny check` passes with zero violations | |
99 | +- Verify Dependabot is configured for weekly updates | |
100 | +- Review `deny.toml` for license allowlist accuracy | |
101 | +- Verify lockfile is committed and up-to-date | |
102 | + | |
103 | +## Tools | |
104 | + | |
105 | +| Tool | Purpose | Command | | |
106 | +| ---- | ------- | ------- | | |
107 | +| `cargo fuzz` | Rust fuzzing | `cargo fuzz run <target>` | | |
108 | +| `cargo audit` | Vulnerability scanning | `cargo audit` | | |
109 | +| `cargo deny` | License/advisory checks | `cargo deny check` | | |
110 | +| `curl` | Manual request testing | `curl -v http://localhost:8080/` | | |
111 | +| `oha` | Load testing | `oha -z 10s http://localhost:8080/` | | |
112 | +| `nmap` | Port/service discovery | `nmap -sV localhost` | | |
113 | +| `testssl.sh` | TLS configuration test | `testssl.sh https://localhost:8080/` | | |
114 | +| `jwt_tool` | JWT attack toolkit | `python3 jwt_tool.py <token>` | | |
115 | +| `sqlmap` | SQL injection detection | `sqlmap -u "http://localhost:8080/endpoint"` | | |
116 | +| `nikto` | Web server scanner | `nikto -h http://localhost:8080/` | | |
117 | + | |
118 | +## Scoring | |
119 | + | |
120 | +Use CVSS 3.1 for severity scoring. Report template: | |
121 | + | |
122 | +``` | |
123 | +# Vulnerability Report | |
124 | + | |
125 | +**Title**: <brief description> | |
126 | +**Severity**: CVSS 3.1 <score> (<Critical/High/Medium/Low>) | |
127 | +**Endpoint**: <method> <path> | |
128 | +**Type**: <OWASP category> | |
129 | + | |
130 | +## Description | |
131 | + | |
132 | +## Steps to Reproduce | |
133 | + | |
134 | +## Impact | |
135 | + | |
136 | +## Recommended Fix | |
137 | + | |
138 | +## References | |
139 | +``` | |
140 | + | |
141 | +--- | |
142 | + | |
143 | +_Last updated: 2026-07-05_ | |
0 | 144 | |
▼docs/security/policy.md
+55-0
| @@ -0,0 +1,55 @@ | ||
1 | +# Security Policy | |
2 | + | |
3 | +## Supported Versions | |
4 | + | |
5 | +| Version | Supported | | |
6 | +| ------- | --------- | | |
7 | +| >= 1.0 | ✅ Active | | |
8 | +| < 1.0 | ⚠️ Dev-only (report anyway) | | |
9 | + | |
10 | +## Reporting a Vulnerability | |
11 | + | |
12 | +**DO NOT file a public GitHub issue for security vulnerabilities.** | |
13 | + | |
14 | +Send details to **[email protected]** with: | |
15 | + | |
16 | +1. **Subject**: `[JustAPI Security] <brief description>` | |
17 | +2. **Affected version(s)** | |
18 | +3. **Type of vulnerability** (e.g., XSS, RCE, SQL injection, information disclosure) | |
19 | +4. **Steps to reproduce** (minimal proof of concept preferred) | |
20 | +5. **Impact assessment** | |
21 | +6. **Suggested fix** (optional but appreciated) | |
22 | + | |
23 | +### Response timeline | |
24 | + | |
25 | +- **24h**: Acknowledgment of receipt | |
26 | +- **7 days**: Triage and severity assessment | |
27 | +- **90 days**: Fix released (or extension negotiated) | |
28 | +- **Disclosure**: Coordinated public disclosure after fix is available | |
29 | + | |
30 | +## Scope | |
31 | + | |
32 | +In-scope: | |
33 | + | |
34 | +- JustAPI framework source code (all crates) | |
35 | +- Official Docker images (`ghcr.io/justapi/*`) | |
36 | +- Official Helm chart | |
37 | +- Build pipeline and CI/CD configuration | |
38 | + | |
39 | +Out-of-scope: | |
40 | + | |
41 | +- Third-party plugins | |
42 | +- Applications built _with_ JustAPI (report to the app maintainer) | |
43 | +- Infrastructure not owned by the JustAPI project | |
44 | + | |
45 | +## Bug Bounty | |
46 | + | |
47 | +This project does not currently offer a paid bug bounty program. | |
48 | +Contributors will be credited in the release notes and the | |
49 | +[SECURITY.md](./hall-of-fame.md) hall of fame (opt-out available). | |
50 | + | |
51 | +## Hall of Fame | |
52 | + | |
53 | +We thank the following researchers for their responsible disclosures: | |
54 | + | |
55 | +_None yet — be the first!_ | |
0 | 56 | |
▼mkdocs.yml
+14-0
| @@ -0,0 +1,14 @@ | ||
1 | +site_name: JustAPI | |
2 | +site_description: 700k RPS Python Web Framework backed by Rust | |
3 | +theme: | |
4 | + name: material | |
5 | + palette: | |
6 | + scheme: default | |
7 | + primary: deep purple | |
8 | + accent: deep purple | |
9 | +nav: | |
10 | + - Home: index.md | |
11 | + - Getting Started: getting_started.md | |
12 | + - Migrating from FastAPI: migrating_from_fastapi.md | |
13 | + - API Reference: api_reference.md | |
14 | + - Plugins: plugins.md | |
0 | 15 | |