Security Hardening
Proactive security improvement suggestions. Unlike vulnerability scanners
that find what is broken, this skill identifies what could be better --
defense-in-depth measures, missing security headers, insufficient input
validation, absent rate limiting, and other hardening opportunities that
reduce the blast radius of future vulnerabilities.
Supported Flags
Read
../../shared/schemas/flags.md
for the full flag specification.
| Flag | Hardening Behavior |
|---|
| Default . Use for comprehensive hardening review. |
| Check for missing security headers and obvious hardening gaps only. |
| Full hardening review: headers, validation, logging, error handling, configuration. |
| Standard + analyze middleware chains, review all trust boundaries, check defense layering. |
| Deep + compare against security benchmarks (CIS, OWASP ASVS), generate hardening scorecard. |
| Filter suggestions by impact level. |
| Default . Use for a hardening checklist document. |
Workflow
Step 1: Identify Technology Stack
Scan the codebase to determine:
- Web framework(s): Express, Django, Flask, Spring, Rails, Next.js, ASP.NET, FastAPI, etc.
- Deployment target: Container, serverless, VM, PaaS (from Dockerfile, serverless.yml, etc.).
- Reverse proxy/CDN: Nginx, Apache, Cloudflare, AWS ALB (from config files).
- Database(s): SQL, NoSQL, cache layers.
- Authentication mechanism: Session, JWT, OAuth, SAML.
- Existing security middleware: Helmet, django-security, Spring Security, etc.
Step 2: Check Security Headers
Verify the application sets these HTTP response headers (or that a reverse proxy / CDN handles them):
| Header | Recommended Value | Impact |
|---|
| Strict policy, no / | Mitigates XSS |
Strict-Transport-Security
| max-age=31536000; includeSubDomains; preload
| Enforces HTTPS |
| | Prevents MIME sniffing |
| or | Prevents clickjacking |
| strict-origin-when-cross-origin
or stricter | Limits referrer leakage |
| Disable unused browser features | Reduces attack surface |
Cross-Origin-Opener-Policy
| | Prevents cross-origin attacks |
Cross-Origin-Resource-Policy
| | Controls resource sharing |
| for sensitive responses | Prevents cache leaks |
Note: If a reverse proxy config (nginx.conf, etc.) is present and sets these headers, do not flag them as missing from application code.
Step 3: Review CORS Configuration
Check for overly permissive CORS settings:
Access-Control-Allow-Origin: *
on authenticated endpoints.
- Reflecting the header without validation.
Access-Control-Allow-Credentials: true
with wildcard origins.
- Overly broad allowed methods or headers.
- Missing when origin is dynamic.
Step 4: Assess Input Validation
For each entry point discovered (or in scope):
- Schema validation: Are request bodies validated against a schema (Joi, Zod, Pydantic, JSON Schema)?
- Type coercion: Are string inputs properly typed before use?
- Length limits: Are string lengths bounded? Are array sizes limited?
- Allowlist vs denylist: Is validation positive (allowlist) rather than negative (denylist)?
- Nested input: Are deeply nested objects limited to prevent DoS?
- File validation: Are uploaded files validated beyond extension (magic bytes, size limits)?
Step 5: Check Rate Limiting
Identify endpoints that should have rate limiting:
- Authentication endpoints: Login, registration, password reset, MFA verification.
- API endpoints: Especially those that are computationally expensive or return sensitive data.
- File upload endpoints: To prevent storage exhaustion.
- Search/query endpoints: To prevent enumeration and DoS.
Check if rate limiting is implemented and whether limits are reasonable.
Step 6: Review Error Handling and Information Disclosure
- Stack traces: Are stack traces exposed in production error responses?
- Verbose errors: Do error messages reveal internal paths, versions, or database details?
- Error differentiation: Do auth errors distinguish between "user not found" and "wrong password" (enables enumeration)?
- Default error pages: Are framework default error pages replaced?
- Debug mode: Is debug mode disabled in production configuration?
Step 7: Assess Security Logging
Check that these security-relevant events are logged:
- Authentication events: Login success/failure, logout, password changes.
- Authorization failures: Access denied events with user and resource context.
- Input validation failures: Rejected requests with sanitized details.
- Administrative actions: Config changes, user management, privilege changes.
- Sensitive data access: Audit trail for PII/financial data reads.
Verify logs do NOT contain: passwords, tokens, credit card numbers, SSNs, or other sensitive data.
Step 8: Check Defensive Coding Patterns
- Fail-closed defaults: Do authorization checks default to deny?
- Secure defaults: Are new configurations secure by default?
- Least privilege: Do database connections, API keys, and service accounts use minimal permissions?
- Timeout configuration: Do HTTP clients, database connections, and external calls have timeouts?
- Resource limits: Are memory/CPU-intensive operations bounded?
- Dependency security: Is / / equivalent run in CI?
Step 9: Report
Output hardening suggestions grouped by category.
Output Format
Hardening suggestions are advisory and use a lighter format than vulnerability findings.
## Security Hardening Report
### Summary
- Hardening suggestions: N
- By priority: N HIGH, N MEDIUM, N LOW
- Categories covered: headers, cors, validation, rate-limiting, logging, error-handling, config
### HIGH Priority
#### [H-001] Missing Content-Security-Policy header
**Category**: Headers | **Effort**: Low
**Location**: src/middleware/security.ts
**Current**: No CSP header set
**Recommended**: Add strict CSP via helmet
```js
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:"],
}
}));
MEDIUM Priority
...
LOW Priority
...
When hardening gaps represent actual vulnerabilities (e.g., CORS misconfiguration allowing credential theft), emit a formal finding using `../../shared/schemas/findings.md`.
Finding ID prefix: **HARD** (e.g., `HARD-001`).
- `metadata.tool`: `"harden"`
- `references.cwe`: Varies by suggestion (e.g., `CWE-693` Protection Mechanism Failure, `CWE-16` Configuration)
## Pragmatism Notes
- Hardening is contextual. An internal admin tool has different requirements than a public API.
- Do not recommend CSP for a CLI tool or rate limiting for a batch job.
- If a CDN or reverse proxy handles headers, note that rather than flagging missing headers in app code.
- Prioritize suggestions that are easy to implement with high security impact.
- Acknowledge when existing security measures are already good. Not every review needs findings.
- Some frameworks (Next.js, Rails) include secure defaults. Credit what is already done well.