feat: refresh shared skills catalog
This commit is contained in:
1 parent
98bb35e6fb
commit
418792d1ec
49 files changed
+2273
-2390
No files matched your search
@@ -1,98 +1,38 @@
|
||||
---
|
||||
name: app-security
|
||||
description: >
|
||||
Full-stack application and API security hardening: Four-Pillar upload defense,
|
||||
SSRF prevention, input boundary clamping, IDOR elimination, and secret masking.
|
||||
Use when creating or auditing API routes, handling uploads, making outbound requests,
|
||||
or preparing pre-release security verification.
|
||||
concerns: [security]
|
||||
Harden affected application boundaries when implementing or auditing authorization, uploads, user-influenced outbound requests, or sensitive data handling.
|
||||
scope: global
|
||||
---
|
||||
|
||||
# Application Security Hardening
|
||||
# Application security
|
||||
|
||||
Enforces defensive boundaries across the API membrane, eliminating exploit vectors, path traversals, SSRF risks, IDOR vulnerabilities, and payload exhaustion.
|
||||
Inspect the affected boundary and existing controls. Apply the protections relevant
|
||||
to the task; a small fix does not require a full application audit.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["Inbound Request"] --> B["1. Membrane Clamping<br/>(Schema & Bound Validation)"]
|
||||
B --> C["2. Four-Pillar Uploads<br/>(Size, Ext, Magic, Path)"]
|
||||
C --> D["3. Outbound SSRF Guard<br/>(Loopback/Metadata Block)"]
|
||||
D --> E["4. Secret Masking<br/>(Zero Token Sediment)"]
|
||||
```
|
||||
1. Validate untrusted payloads with runtime schemas and resource bounds derived
|
||||
from product requirements. Reject invalid data; do not silently truncate credentials.
|
||||
2. Derive identity from verified server authentication. Enforce tenant/resource
|
||||
permissions on private reads and writes, preferably within the data operation.
|
||||
Cover unauthenticated access, cross-tenant access, and relevant races.
|
||||
3. For uploads, enforce a product-specific extension/type allowlist, stream byte
|
||||
limits, and appropriate content validation. Magic headers alone do not prove
|
||||
safety. Use generated storage names and an isolated non-executable root; prevent
|
||||
traversal and symlink escapes. Serve potentially active content with appropriate
|
||||
isolation and headers. Bound archive expansion or decoding work when applicable.
|
||||
4. For user-influenced outbound destinations, allowlist known services where possible.
|
||||
Parse URLs, restrict schemes, resolve and validate all IPv4/IPv6 addresses, and
|
||||
prevent DNS changes from bypassing connection checks. Disable redirects or validate
|
||||
each destination using the same policy. Block private, loopback, link-local,
|
||||
unspecified, and metadata targets unless a specific trusted internal service is
|
||||
intentionally allowed. Apply time, response-size, and network egress limits.
|
||||
5. Redact credentials at logging/telemetry boundaries and keep public errors free
|
||||
of secrets and internal traces. Apply relevant session, CSRF, rate-limiting, and
|
||||
browser content controls using existing framework facilities.
|
||||
6. Verify the changed boundary with meaningful negative cases under
|
||||
[shared verification](../../protocols/workflow.md#verification). Report actual
|
||||
protections and gaps; do not claim the whole app is secure from a checklist.
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Setup and Protocols
|
||||
|
||||
1. Review reference playbooks:
|
||||
- [references/app-hardening-playbook.md](references/app-hardening-playbook.md) for concrete TypeScript/Python code patterns and boundary clamps.
|
||||
- [references/review-checklist.md](references/review-checklist.md) for pre-release OWASP verification checks.
|
||||
2. Invariants:
|
||||
- Every input payload must be typed and bounded.
|
||||
- Every state mutation must verify session identity and tenant ownership.
|
||||
- Outbound HTTP fetches must never touch private/loopback networks.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Ingest and Check
|
||||
|
||||
1. **Surface Identification**:
|
||||
- Inbound API routes (REST, GraphQL, RPC handlers).
|
||||
- File/document ingestion and attachment endpoints.
|
||||
- Outbound network calls (webhooks, URL unfurlers, external data scrapers).
|
||||
- Data persistence operations and logging sinks.
|
||||
2. **Access Control Check**:
|
||||
- Confirm identity is derived from verified server sessions/tokens, never trusted client parameters (`userId`, `orgId`).
|
||||
- Confirm entity queries enforce ownership: verify record exists AND belongs to the authenticated caller before mutating.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Processing (Core Logic)
|
||||
|
||||
### Step 1: Input Boundaries & Membrane Clamping
|
||||
- Never accept arbitrary, unvalidated request dictionaries. Model all payloads using strict schemas (e.g. Pydantic, Zod).
|
||||
- Enforce hard string limits:
|
||||
- Text prompts / message content: Max 50,000 characters.
|
||||
- Titles / Names: Max 100–200 characters.
|
||||
- Pagination limits: Clamped to `1 <= limit <= 50`.
|
||||
- Batch arrays: Clamped to max 100–200 items.
|
||||
- Sanitize entity and path identifiers against path traversal tokens (`../`, `..\\`).
|
||||
|
||||
### Step 2: Four-Pillar Upload Defense
|
||||
When handling file or media uploads:
|
||||
1. **Size Bounds**: Reject payloads exceeding size thresholds (e.g., 100MB for docs; 5MB for images).
|
||||
2. **Blocked Extensions**: Reject executable and script formats (`.exe`, `.bat`, `.sh`, `.svg`, `.html`, `.php`).
|
||||
3. **Magic Byte Inspection**: Inspect file headers to detect disguised binaries (PE `MZ`, ELF, Mach-O).
|
||||
4. **Path Traversal Defense**:
|
||||
- Sanitize original filenames (strip path separators and non-printable characters).
|
||||
- Write files strictly to designated, isolated upload roots with unique IDs (e.g. UUID filenames).
|
||||
|
||||
### Step 3: Outbound SSRF Guard
|
||||
Before executing outbound HTTP requests (scraping, webhooks):
|
||||
- Validate target URLs against an allowlist or safety filter.
|
||||
- Block loopback addresses (`127.0.0.1`, `localhost`, `::1`), RFC 1918 private subnets (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), and cloud metadata services (`169.254.169.254`).
|
||||
- Restrict allowed protocols strictly to `http` and `https`.
|
||||
|
||||
### Step 4: Secret Masking & Error Shielding
|
||||
- Scrub Authorization tokens (`Bearer ***`), provider API keys, and sensitive credentials from logs, database traces, and telemetry.
|
||||
- In public HTTP error responses, return clean structured error objects with opaque error codes; never leak internal filesystem paths, environment variables, or stack traces.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: The System One Balance Pass
|
||||
|
||||
- **Augment, Don't Handcuff**:
|
||||
- Do NOT break local development workflows: allow local mock endpoints and fixture testing in non-production test environments.
|
||||
- Keep security checks non-intrusive during prototyping; enforce strictly at boundaries and pre-release gates.
|
||||
- Avoid noisy confirmation warnings for routine safe operations.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Output Execution & Verification
|
||||
|
||||
1. Run verification checks from [references/review-checklist.md](references/review-checklist.md).
|
||||
2. Provide a security verification summary detailing:
|
||||
- Bound clamps applied to route schemas.
|
||||
- Upload filters active (size, extension, magic bytes, safe path).
|
||||
- SSRF protection status on outbound calls.
|
||||
- Secret scrubbing confirmation.
|
||||
Use [the playbook](references/app-hardening-playbook.md) for implementation choices
|
||||
and [the checklist](references/review-checklist.md) for an explicitly requested audit.
|
||||
Local fixtures need deliberate configuration, not an automatic security bypass.
|
||||
@@ -1,160 +1,50 @@
|
||||
# Full-Stack Application Security Hardening Playbook
|
||||
# Boundary hardening choices
|
||||
|
||||
This high-level guide provides a reusable, standardized protocol for auditing and securing full-stack applications (Next.js, Node.js, Express, etc.).
|
||||
Read the relevant section when implementing that boundary. Values and tools come
|
||||
from the product's threat model, stack, and resource budgets, not this document.
|
||||
|
||||
---
|
||||
## Identity and authorization
|
||||
|
||||
## Phase 1: Endpoint & Access Control (Preventing IDOR)
|
||||
Authenticate on the server. Bind private reads and writes to the caller's allowed
|
||||
resources and tenant. Prefer an ownership predicate in the data operation; a
|
||||
separate read-check-write sequence can race. Verify cookie-authenticated mutations
|
||||
have appropriate CSRF/origin protections and session expiry behavior.
|
||||
|
||||
### 1. The Multi-Tenant Ownership Rule
|
||||
Every state-changing API request (`POST`, `PUT`, `PATCH`, `DELETE`) and private resource read (`GET`) must establish identity via the server session—never by trusting client parameters.
|
||||
## Payloads and credentials
|
||||
|
||||
#### Never Trust Client User IDs:
|
||||
```typescript
|
||||
// ❌ Vulnerable (attacker can pass any userId in body)
|
||||
const { title, userId } = await req.json();
|
||||
await db.resource.create({ data: { title, userId } });
|
||||
Validate runtime shapes and bound request bytes, field lengths, array counts, and
|
||||
expensive processing. Reject invalid credentials without silent truncation. Hash
|
||||
passwords with the framework's supported algorithm and settings; bcrypt's 72-byte
|
||||
input limitation is bytes, not characters. Use the selected algorithm's documented
|
||||
limits and preserve long-password support when choosing the design.
|
||||
|
||||
// ✅ Secure (always bind to verified session)
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session?.user?.id) return unauthorized();
|
||||
await db.resource.create({ data: { title, userId: session.user.id } });
|
||||
```
|
||||
## Uploads
|
||||
|
||||
#### Verify Resource Ownership Before Mutation:
|
||||
```typescript
|
||||
// Verify target record exists AND belongs to the caller
|
||||
const item = await db.resource.findUnique({ where: { id } });
|
||||
if (!item) return notFound();
|
||||
if (item.userId !== session.user.id) return forbidden();
|
||||
```
|
||||
Choose an explicit extension/content allowlist and byte cap per supported format.
|
||||
Stop streaming at the cap. Inspect content with a suitable parser; signatures alone
|
||||
cannot validate the whole file. Generate storage IDs; keep the storage root isolated
|
||||
and non-executable, prevent traversal/symlink escapes, and bound archive expansion.
|
||||
Serve active content in an appropriate isolated origin or as an attachment. Apply
|
||||
malware scanning or re-encoding when the threat model warrants it.
|
||||
|
||||
#### Lock Down Sensitive Data Endpoints:
|
||||
* Strip internal data (emails, password hashes, roles, permissions) from public query endpoints.
|
||||
* Never allow query flags like `?includePrivate=true` unless the caller has verified ownership or administrative authorization for that account.
|
||||
## User-influenced outbound requests
|
||||
|
||||
---
|
||||
Prefer service allowlists. Resolve all IPv4/IPv6 addresses and validate the actual
|
||||
connection destination, including DNS changes. Disable redirects or repeat checks
|
||||
for each hop. Bound time, bytes, and egress. Trusted internal service calls use their
|
||||
own allowlist rather than a blanket private-network ban.
|
||||
See [OWASP SSRF guidance](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html).
|
||||
|
||||
## Phase 2: Input Boundaries & Payload Sanitization
|
||||
## Browser and abuse controls
|
||||
|
||||
### 1. Enforce Hard Limits on Every Field
|
||||
Unbounded input strings can cause database exhaustion, buffer overruns, or CPU denial-of-service (e.g., Bcrypt hashing huge strings).
|
||||
Use CSP, framing rules, safe content types, CSRF protection, and rate limiting for
|
||||
the relevant flow. Configure limits by actor, cost, and deployment topology. Apply
|
||||
HSTS only to intended HTTPS domains; subdomains/preload require deliberate coverage.
|
||||
Do not disable required browser capabilities through a blanket Permissions-Policy.
|
||||
|
||||
| Field Type | Recommended Hard Bound | Rationale |
|
||||
| :--- | :--- | :--- |
|
||||
| **Passwords** | Min 8 chars, Max 72–100 chars | Bcrypt truncates or burns excessive CPU beyond 72 bytes |
|
||||
| **Emails** | Max 254 chars | Standard RFC 5321 length; prevents regex DoS |
|
||||
| **Titles / Names** | Max 100–200 chars | Prevents UI overflow and DB memory bloat |
|
||||
| **Descriptions / Content** | Max 2,000–50,000 chars | Prevents payload bombing |
|
||||
| **Pagination limit** | Clamped to `1 <= limit <= 50` | Prevents querying the entire table at once |
|
||||
## Verification
|
||||
|
||||
### 2. JSON & Batch Array Clamping
|
||||
When accepting array batches (e.g., bulk updating nodes or items), enforce an explicit upper limit (e.g., max 200–500 items per request).
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Safe File & Document Upload Architecture
|
||||
|
||||
If an application accepts images, PDFs, or documents, implement the **Four-Pillar Upload Defense**:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["File Upload"] --> B["1. Size Check"]
|
||||
B --> C["2. Extension & MIME Allowlist"]
|
||||
C --> D["3. Magic Bytes Inspection"]
|
||||
D --> E["4. Filename Sanitization & Storage"]
|
||||
```
|
||||
|
||||
### 1. Size Caps:
|
||||
* Check file size before buffering: images (max 2–5MB), documents (max 10MB).
|
||||
* Terminate stream early if incoming chunks exceed the configured byte threshold.
|
||||
|
||||
### 2. Strict MIME & Extension Allowlists:
|
||||
* **Allowed:** `image/jpeg` (`.jpg`, `.jpeg`), `image/png` (`.png`), `image/webp` (`.webp`), `application/pdf` (`.pdf`), `application/json` (`.json`), `text/markdown` (`.md`).
|
||||
* **Strictly Blocked:** `.exe`, `.bat`, `.sh`, `.php`, `.js`, `.html`, `.svg` (SVGs can embed `<script>` tags and execute XSS unless explicitly sanitized).
|
||||
|
||||
### 3. Magic Bytes (Header Signature) Inspection:
|
||||
Do not trust the client `Content-Type` header or file extension alone. Inspect the initial bytes of the file buffer:
|
||||
|
||||
| Format | Magic Bytes Signature | Hex Representation |
|
||||
| :--- | :--- | :--- |
|
||||
| **JPEG** | `\xFF\xD8\xFF` | `FF D8 FF` |
|
||||
| **PNG** | `\x89PNG\r\n\x1a\n` | `89 50 4E 47` |
|
||||
| **WebP** | `RIFF....WEBP` | `52 49 46 46` ('RIFF') |
|
||||
| **PDF** | `%PDF-` | `25 50 44 46` ('%PDF') |
|
||||
|
||||
### 4. Filename Sanitization & Non-Executable Storage:
|
||||
* Strip directory traversal sequences (`../`, `..\\`) and null bytes (`\0`).
|
||||
* Store files using randomized UUIDs/CUIDs (e.g., `clx987654321.png`) rather than the original user-supplied name.
|
||||
* Serve uploaded files with `Content-Disposition: attachment` or host from dedicated static object storage (S3/GCS) where server script execution is disabled.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Rate Limiting & Abuse Prevention
|
||||
|
||||
### Protect Sensitive Action Gates:
|
||||
* **Login attempts:** Max 5–10 per 15 minutes per IP.
|
||||
* **User registrations:** Max 3–5 per hour per IP.
|
||||
* **Password resets:** Max 3 per hour per email/IP.
|
||||
* **General API read/write:** 60–120 requests per minute per authenticated user / IP.
|
||||
|
||||
### Implementation Strategy:
|
||||
* **Single Server / Microservice:** Use an in-memory sliding-window bucket with automatic timestamp cleanup.
|
||||
* **Distributed / Serverless:** Use Redis (e.g., Upstash / Redis token bucket) to share rate limits across multiple instances.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Framework Hardening & HTTP Security Headers
|
||||
|
||||
### 1. Disable Fingerprinting
|
||||
* In `next.config.ts` / `next.config.js`:
|
||||
```typescript
|
||||
const nextConfig = {
|
||||
poweredByHeader: false,
|
||||
};
|
||||
```
|
||||
* In Express:
|
||||
```typescript
|
||||
app.disable('x-powered-by');
|
||||
```
|
||||
|
||||
### 2. Standard Security Headers
|
||||
Inject these headers across all routes (via Next.js `headers()` config, middleware, or reverse proxy):
|
||||
|
||||
```http
|
||||
X-Frame-Options: SAMEORIGIN
|
||||
X-Content-Type-Options: nosniff
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
|
||||
Permissions-Policy: camera=(), microphone=(), geolocation=()
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Continuous Dependency & Build Verification
|
||||
|
||||
Establish a 4-step security check before every release:
|
||||
|
||||
### 1. Vulnerability Audit:
|
||||
```bash
|
||||
npm audit
|
||||
# Apply automated non-breaking security fixes:
|
||||
npm audit fix
|
||||
```
|
||||
|
||||
### 2. Static Code & Lint Analysis:
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### 3. Automated Security Unit Tests:
|
||||
Maintain unit tests validating that:
|
||||
* File upload allowlists reject `.exe`, `.html`, `.svg`, and mismatched magic bytes.
|
||||
* Rate limiters trigger HTTP 429 when thresholds are exceeded.
|
||||
* Boundary helpers clamp oversized numbers and truncate/reject excessive payload strings.
|
||||
* Endpoints reject unauthenticated mutations and IDOR resource manipulation.
|
||||
|
||||
### 4. Production Build Verification:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
Test relevant unauthorized and malformed cases. Audit dependencies when dependency
|
||||
risk is part of the task; inspect the result before changing versions. Do not run
|
||||
`npm audit fix` as an automatic audit step or change the user's stack by default.
|
||||
Follow [shared verification](../../../protocols/workflow.md#verification).
|
||||
@@ -1,30 +1,18 @@
|
||||
# Security Review & OWASP Verification Checklist
|
||||
# Optional security audit checklist
|
||||
|
||||
## Input Validation & Boundaries
|
||||
- [ ] Pydantic schemas enforce hard string bounds (max 50,000 for text, max 200 for titles).
|
||||
- [ ] Dynamic path/query identifiers validated via `sanitize_identifier()`.
|
||||
- [ ] Pagination limits clamped to `1 <= limit <= 50`.
|
||||
- [ ] Batch array inputs clamped to safe upper bounds (max 100–200 items).
|
||||
Select checks for the requested surface. Record observed controls and evidence;
|
||||
unchecked items do not automatically become blocking work outside the task.
|
||||
|
||||
## Four-Pillar Upload Defense
|
||||
- [ ] Uploads restricted by `DEFAULT_MAX_FILE_SIZE` (100MB; 5MB for images).
|
||||
- [ ] Blocked executable extensions rejected (`BLOCKED_EXTENSIONS`).
|
||||
- [ ] Extension checked against `ALLOWED_EXTENSIONS`.
|
||||
- [ ] Header magic bytes inspected (`check_magic_bytes`) to block disguised binaries.
|
||||
- [ ] Filenames sanitized with `sanitize_filename()` (path traversal and CLI injection stripped).
|
||||
- [ ] Disk writes resolved strictly via `safe_resolve_path()`.
|
||||
- Runtime input validation and product-specific byte/field/batch limits.
|
||||
- Verified identity and resource/tenant authorization on private reads and writes.
|
||||
- Relevant session, CSRF, and rate-limit behavior.
|
||||
- Upload allowlist, streaming cap, content validation, storage isolation, and safe serving.
|
||||
- User-influenced URL parsing, all-address DNS checks, connection enforcement,
|
||||
IPv4/IPv6 policy, redirect controls, time/byte limits, and egress restrictions.
|
||||
- Credential redaction across logs and telemetry; public errors omit internal traces.
|
||||
- Parameterized values and separately validated dynamic SQL identifiers.
|
||||
- Browser content/framing policies appropriate to the application's actual flows.
|
||||
- Meaningful negative cases for the changed controls, with remaining gaps stated.
|
||||
|
||||
## SSRF Defense
|
||||
- [ ] All outbound requests in research/web-retrieval validated with `validate_safe_url()`.
|
||||
- [ ] Loopback (`127.0.0.1`), private RFC 1918 subnets, and cloud metadata (`169.254.169.254`) blocked.
|
||||
- [ ] Scheme restricted strictly to `http` and `https`.
|
||||
|
||||
## Secrets & Data Hygiene
|
||||
- [ ] Zero API keys, bearer tokens, or password hashes written to `error_log` or logs.
|
||||
- [ ] Authorization headers masked in logging formatters (`Bearer ***`).
|
||||
- [ ] Production error responses mask internal database paths and raw tracebacks.
|
||||
|
||||
## Authorization & State Safety
|
||||
- [ ] Mutations verify that target records match the active session / conversation scope.
|
||||
- [ ] SQLite queries use parameterized SQL; no raw string concatenation.
|
||||
- [ ] Rate limits applied on expensive inference and digestion endpoints.
|
||||
Helper names and constants follow the existing project. No particular framework,
|
||||
file cap, pagination limit, or security helper is required by this checklist.
|
||||
Reference in new issue
Block a user