# Hakal Team Skills Vulnerability Remediation Patterns

> Vulnerability Remediation Patterns

- Skill: `tomevault-io/hakal-team-skills-vulnerability-remediation-patterns` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/hakal-team-skills-vulnerability-remediation-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/hakal-team-skills-vulnerability-remediation-patterns/raw
- Safety review: pending (external: skill-scanner WARNING, skillspector CAUTION)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/hakal-team-skills-vulnerability-remediation-patterns

---


# Vulnerability Remediation Patterns

## Injection Remediation

### SQL Injection
- **Parameterized queries ALWAYS**. No exceptions. No string concatenation for SQL.
- ORM usage preferred -- but verify the ORM parameterizes under the hood (raw queries in ORMs are still vulnerable).
- Stored procedures: use parameters, not dynamic SQL inside the procedure.
- If building dynamic column/table names: strict allowlist validation, never user input directly.

### Command Injection
- **Avoid shell execution entirely.** Rewrite with language-native libraries (file ops, HTTP clients, etc.).
- If shell is unavoidable: `subprocess` with array args (`['cmd', 'arg1', 'arg2']`), NEVER `shell=True`.
- Allowlist commands and arguments. Reject anything not on the list.
- Never pass user input to `eval()`, `exec()`, `os.system()`, or backtick execution.

### XSS (Cross-Site Scripting)
- **Output encoding by context** -- these are ALL different:
  - HTML body: HTML entity encode (`<` becomes `&lt;`)
  - HTML attribute: attribute encode, always quote attribute values
  - JavaScript context: JavaScript encode (hex escape)
  - URL parameter: URL encode
  - CSS value: CSS hex encode
- CSP headers as defense in depth: `default-src 'self'`, avoid `unsafe-inline`/`unsafe-eval`.
- DOM manipulation: use `textContent`, NEVER `innerHTML` with user data.
- Frameworks with auto-escaping (React, Angular) help but do not prevent `dangerouslySetInnerHTML` or `[innerHTML]` bypasses.

### Template Injection (SSTI)
- Never pass user input as the template source. User input goes into template *variables*, not the template itself.
- Use logic-less templates (Mustache, Handlebars) where possible.
- Sandbox template engines. Restrict available functions/objects in template context.

### Path Traversal
- Canonicalize the path first (`os.path.realpath`, `Path.resolve()`), THEN verify it starts with the allowed prefix.
- Never trust user-supplied filenames. Generate filenames server-side, store original name as metadata.
- Reject paths containing `..`, null bytes, or encoded variants.

## Authentication Fixes

### Password Storage
- **bcrypt or argon2id** with appropriate work factor. Target 250ms+ hash time.
- NEVER MD5, SHA-1, or SHA-256 for passwords (fast hashes enable brute force).
- Use the library's built-in salt generation -- do not roll your own.

### Session Management
- Session IDs: cryptographically random, minimum 128 bits of entropy.
- Cookie flags: `HttpOnly` (no JS access), `Secure` (HTTPS only), `SameSite=Lax` or `Strict`.
- Server-side session expiry. Do not rely only on cookie expiry.
- Regenerate session ID on login (prevents session fixation).

### Token Handling
- Short-lived access tokens (15 min or less) + refresh token rotation.
- Store the hash of refresh tokens, not plaintext.
- Invalidate all tokens on password change.
- JWTs: validate signature, issuer, audience, and expiry. Reject `alg: none`.

### MFA Implementation
- TOTP preferred over SMS (SIM swap risk).
- Backup codes: hash them like passwords. Single-use. Show only once.
- Rate limit verification attempts (5 attempts, then lockout with backoff).
- Do not reveal whether MFA is enabled during login flow (information leakage).

### Password Reset
- Constant-time email lookup -- same response time whether account exists or not (prevents enumeration).
- Time-limited tokens (15-30 min). Single-use.
- Hash the stored token (if DB is compromised, tokens are useless).
- Invalidate all existing reset tokens when a new one is issued.

## Authorization Fixes

### BOLA (Broken Object Level Authorization)
- Verify ownership **at the data layer**, not just the route/middleware.
- Every query that fetches by ID must also filter by the authenticated user's scope.
- Pattern: `SELECT * FROM orders WHERE id = ? AND user_id = ?` -- never just `WHERE id = ?`.

### Privilege Escalation
- Role checks at the **function/action level**, not just the UI.
- Server-side enforcement is mandatory. Hiding a button is not access control.
- Verify role on every request. Do not trust a role claim from the client.
- Principle of least privilege: default deny, explicitly grant.

### Mass Assignment
- Explicit allowlists for assignable fields. Never pass raw request body to model update.
- Example: `user.update(request.body)` is vulnerable. Use `user.update(pick(request.body, ['name', 'email']))`.
- Separate DTOs for create vs update if different fields are assignable.

### CORS
- Explicit origin allowlist. **Never** `Access-Control-Allow-Origin: *` with credentials.
- Validate the `Origin` header server-side against the allowlist.
- Do not reflect the request origin back as the allowed origin without checking.
- Restrict allowed methods and headers to what is actually needed.

## Data Exposure Fixes

### Error Handling
- Generic messages to users: "Something went wrong. Please try again."
- Detailed errors server-side only (structured logging with request ID for correlation).
- Never expose: stack traces, SQL errors, internal file paths, dependency versions.
- Custom error pages for 4xx/5xx. Framework defaults often leak info.

### API Response Shaping
- Explicit serialization: return only the fields the client needs.
- Never dump model/ORM objects directly to JSON response.
- Different serializers for different roles (admin sees more fields than regular user).
- Paginate list endpoints. Never return unbounded result sets.

### Logging Hygiene
- Scrub before logging: PII, tokens, passwords, credit card numbers.
- Structured logging with sensitivity tags so automated scrubbing can catch what you miss.
- Log access events (who accessed what, when) for audit trail.
- Do not log full request bodies -- they may contain secrets.

### Security Headers
- `Strict-Transport-Security: max-age=31536000; includeSubDomains` (HSTS)
- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY` (or `SAMEORIGIN` if you need iframes)
- `Content-Security-Policy`: lock down script/style/image sources
- Remove `Server`, `X-Powered-By`, and other version-disclosing headers.

## Cryptography Fixes

### Core Rules
- Use standard libraries (libsodium, OpenSSL, Web Crypto API). Never roll your own.
- **AES-256-GCM** for symmetric encryption (authenticated encryption -- integrity + confidentiality).
- **RSA-OAEP** (2048+ bit) or **ECDH** (P-256+) for key exchange.
- **TLS 1.2+ only**. Disable TLS 1.0, 1.1, SSLv3.

### Key Management
- Build in key rotation from day one. Hardcoded keys are a ticking time bomb.
- Secrets in environment variables or a vault (HashiCorp Vault, AWS Secrets Manager).
- Never commit secrets to version control. Use `.gitignore` and pre-commit hooks to prevent it.
- Rotate keys immediately if any suspected compromise.

### Common Mistakes
- Using ECB mode (patterns visible in ciphertext). Use GCM or CBC with HMAC.
- Reusing IVs/nonces. Every encryption operation needs a unique IV.
- Comparing hashes with `==` instead of constant-time comparison (timing attacks).
- Storing encryption keys next to the encrypted data.

## Fix Verification Patterns

How to confirm a fix actually works:

### Write the Exploit Test
- Create a test that reproduces the original vulnerability. It should fail before the fix and pass after.
- Example: a test that sends `' OR 1=1 --` to the search endpoint and verifies it returns 0 results, not all results.

### Test the Bypass
- Can the fix be circumvented with encoding changes? (`%27` instead of `'`, double encoding, Unicode normalization)
- Can it be bypassed with case changes, null bytes, or alternate representations?
- Try the fix with the attacker mindset: "How would I get around this?"

### Test Adjacent Functionality
- Did the fix break legitimate use cases? (Overly aggressive validation rejecting valid input)
- Test with international characters, long strings, and edge-case valid inputs.

### Check for Variants
- If you found SQLi in `/search`, check `/filter`, `/export`, `/report` -- same pattern, different endpoint.
- Grep the codebase for the vulnerable pattern: `grep -r "query.*+.*request"` or equivalent.
- Fix the pattern, not just the instance.

### Regression Protection
- Add the exploit test to CI. It must run on every build.
- If the test suite does not cover this attack vector, the fix WILL regress.

## Remediation Anti-Patterns

Patterns that feel like fixes but are not:

- **Blocklist over allowlist**: blocking known-bad input (`DROP`, `<script>`) instead of allowlisting known-good. Always bypassable with encoding, casing, or novel payloads.
- **Client-side only validation**: the server must validate independently. Client validation is UX, not security.
- **Security through obscurity**: hiding the admin endpoint at `/x7f3admin` does not fix missing auth. Assume the attacker knows the URL.
- **Partial fix**: fixing the reported instance but not the pattern. If one endpoint was vulnerable, grep for the same pattern everywhere.
- **Over-patching**: adding so many validation layers that legitimate usage breaks. Fix precisely -- one correct check at the right boundary.
- **Fix and forget**: no regression test means the vulnerability returns in the next refactor. If there is no test, the fix is incomplete.

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/hakal) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-13 -->

