Secure Coding
Config Resolution
Projects can customize this skill's standards. Resolution order:
- Read
.lattice/config.yamlin the repo root. - If found, check
paths.secure_codingfor a custom document path. - If a custom document exists at that path, read it and check its YAML frontmatter for
mode:mode: override: the custom document has full precedence. Use it instead of the embedded defaults. It must be comprehensive -- treat it as the sole reference.mode: overlay(or no mode field): read the embedded./references/defaults.mdfirst, then apply the custom document's sections on top. A custom section replaces the matching default section (matched by exact heading); new sections append after the defaults.
- If a custom path is configured but no document exists at it → tell the user which configured path is missing, then fall back to
./references/defaults.md. - If there is no config file or no
paths.secure_codingkey, read./references/defaults.md. - Language adaptation: if
paths.language_idiomsis set in the config and the document exists, read its "Error Handling" section and adapt §2 (Input Validation Patterns) error-message patterns to the language's idioms. Language idioms take precedence over the pseudocode defaults.
Self-Validation Checklist
STOP after generating each component. Verify ALL checks before proceeding. A check clearly fails → fix the code before presenting. A check is a judgment call with multiple valid approaches (see Ambiguity Signals) → flag it -- present options and reasoning rather than silently choosing.
- TRUST BOUNDARIES: Where does trusted code meet untrusted data? Are all boundaries explicitly identified?
- INPUT VALIDATION: Is every external input validated at the boundary with an allowlist before it reaches business logic?
- QUERY SAFETY: Are all database queries parameterized? Is any string concatenation used in query building?
- COMMAND SAFETY: Is there any shell/command execution? If so, is the input strictly allowlisted?
- SECRETS: Are there API keys, passwords, tokens, or connection strings in code? If so → move them to environment variables or a secret manager.
- OUTPUT ENCODING: Is output encoded appropriately for its render context (HTML, JSON, URL)?
- AUTHORIZATION: Is authorization verified at the service layer, not just the controller? Does every endpoint enforce least privilege?
- ERROR MESSAGES: Do error messages exposed to users avoid revealing internal detail (stack traces, SQL queries, file paths)?
- DEPENDENCIES: Is each new third-party package necessary? Are versions pinned or constrained? Is any known-vulnerable package being added?
All checks pass → state "Passes secure-coding. [next step]."
Active Anti-Pattern Scan
STOP: After verifying the checklist above, scan the output for each anti-pattern below. Any box you can check → fix before presenting the code.
- Trust All Input: no validation on request parameters; data flows straight into business logic → validate at the boundary with an allowlist.
- SQL String Concatenation: user input interpolated into a SQL query → use a parameterized query or ORM query builder.
- Hardcoded Secrets: API key, password, or token in source code → use an env var or secret manager.
- Missing Authorization: auth checked at login but not re-verified at the service or resource level → check at every layer.
- Overly Broad Permissions: admin access granted where read-only suffices → apply least privilege.
- Unvalidated Redirects: a user-controlled URL used in a redirect → allowlist permitted destinations.
- Verbose Error Messages: stack trace or SQL in an API response → return a generic message; log details server-side.
- Logging Sensitive Data: passwords, tokens, or PII in log files → log the event, not the value; mask sensitive fields.
Ambiguity Signals
Checks here often have multiple valid outcomes. When you encounter one, present the options rather than silently choosing. If framework:collaborative-judgment is loaded, use its presentation format.
- Trust Boundary Scope: an internal API behind a trusted gateway may or may not need full boundary validation.
- Error Message Detail: how much detail is "actionable but safe" depends on whether the consumer is a human user, a frontend client, or an internal service.
- Validation Depth: whether to re-validate at inner layers (defense-in-depth) or trust boundary validation alone.
- Auth vs Authz Failure Response: whether to return 401 (not authenticated) or 403 (not authorized) depends on whether the identity is known.
Core Principle
Govern the security posture of generated code -- trust boundaries, input validation, injection prevention, secrets, authorization.
Boundary with clean-code: clean-code governs error-message craft; this skill governs what error messages must not reveal (internal detail).
Boundary with architecture: architecture defines where checks live (service layer, not controller); this skill defines what to check (identity confirmed, permission granted, resource owned).
See ./references/defaults.md.


