Skip to content

Latest commit

 

History

History
175 lines (134 loc) · 8.32 KB

File metadata and controls

175 lines (134 loc) · 8.32 KB

Secure Coding Guidelines

1. Input Validation

  • Treat all external input as untrusted, including user input, API requests, uploaded files, headers, and data from third-party services.
  • Validate input on the server side using allowlists wherever practical.
  • Enforce appropriate type, length, range, and format constraints.
  • Reject malformed or unexpected input rather than attempting to “fix” it.
  • Do not rely on client-side validation for security.

2. Authentication & Authorization

  • Use established authentication mechanisms rather than implementing authentication from scratch.
  • Enforce strong password policies and securely hash passwords using modern password-hashing algorithms.
  • Apply authorization checks on every protected operation, not only in the UI.
  • Follow the principle of least privilege.
  • Never hard-code passwords, API keys, tokens, or other credentials in source code.
  • Implement appropriate session expiration and revocation.

3. Secrets Management

  • Store application secrets in an approved secrets manager, such as Azure Key Vault, rather than in source code or configuration files.
  • Access secrets using managed identities or workload identities where possible instead of storing credentials for Key Vault access.
  • Never commit secrets, connection strings, API keys, passwords, or certificates to source control.
  • Apply least-privilege access policies/Role-Base-Access-Control to Key Vault resources.
  • Enable auditing and monitoring for secret access.
  • Rotate secrets and keys according to their security requirements.

4. Database Security

  • Use parameterized queries or prepared statements.
  • Never construct SQL queries by concatenating untrusted input.
  • Use database accounts with the minimum required privileges.
  • Validate and constrain data before storing it.
  • Protect sensitive data at rest and in transit.
  • Avoid exposing database error details to users.

5. Output Encoding & Injection Prevention

  • Encode output according to its destination: HTML, JavaScript, URLs, shell commands, etc.
  • Use framework-provided escaping mechanisms whenever available.
  • Never pass untrusted input directly to operating-system commands, interpreters, templates, or dynamic code execution.
  • Avoid dynamic evaluation such as eval() unless there is a documented and reviewed security requirement.

6. Web Application Security

  • Protect against common vulnerabilities such as XSS, CSRF, SQL injection, SSRF, path traversal, and insecure direct object references.
  • Use appropriate security-related HTTP headers.
  • Configure cookies with Secure, HttpOnly, and appropriate SameSite attributes.
  • Use HTTPS for all sensitive communications.
  • Implement rate limiting for authentication, password-reset, and other abuse-prone endpoints.
  • Do not expose internal implementation details through APIs.

7. API Security

  • Authenticate and authorize every protected API endpoint.
  • Validate request bodies, parameters, headers, and uploaded content.
  • Apply rate limits and request-size limits.
  • Return only the data the caller is authorized to receive.
  • Avoid excessive data exposure in API responses.
  • Use explicit API schemas and reject unexpected fields where appropriate.
  • Version APIs when security-sensitive changes could affect existing clients.

8. File Handling

  • Treat uploaded files as untrusted.
  • Validate file type, size, name, and content rather than trusting extensions or client-supplied MIME types.
  • Store uploads outside executable directories where possible.
  • Generate server-side filenames instead of using user-supplied paths.
  • Prevent path traversal and unauthorized file access.
  • Scan potentially dangerous uploads where appropriate.

9. Error Handling & Logging

  • Show users generic, actionable error messages without revealing sensitive implementation details.
  • Log security-relevant events such as authentication failures, authorization failures, privilege changes, and suspicious activity.
  • Never log passwords, tokens, session identifiers, encryption keys, or other sensitive secrets.
  • Protect logs from unauthorized access and tampering.
  • Ensure logs contain enough context to support investigation without unnecessarily collecting personal data.

10. Cryptography

  • Use well-established cryptographic libraries and approved algorithms.
  • Do not implement cryptographic algorithms yourself.
  • Do not use deprecated or broken algorithms or protocols.
  • Generate cryptographic keys and random values using a cryptographically secure random-number generator.
  • Protect encryption keys separately from encrypted data.
  • Define key rotation and lifecycle procedures.

11. Dependencies & Third-Party Code

  • Keep dependencies updated and remove unused dependencies.
  • Use trusted package repositories and verify package integrity where supported.
  • Scan dependencies for known vulnerabilities.
  • Review new dependencies before introducing them into production systems.
  • Pin or otherwise control dependency versions appropriately for reproducible builds.
  • Treat third-party code as potentially untrusted.

12. Secure Configuration

  • Use secure defaults.
  • Disable debugging, verbose errors, development accounts, and unnecessary services in production.
  • Separate configuration from application code.
  • Review infrastructure and application configuration as part of security testing.
  • Ensure development and test configurations cannot accidentally expose production data or credentials.

13. Memory & Resource Safety

For languages where memory safety is a concern:

  • Check array and buffer boundaries.
  • Validate allocation sizes.
  • Avoid unsafe memory operations unless necessary and thoroughly reviewed.
  • Properly release resources such as files, sockets, database connections, and locks.
  • Protect against resource exhaustion through appropriate limits and timeouts.

14. Concurrency & Distributed Systems

  • Protect shared state from race conditions.
  • Use appropriate synchronization mechanisms.
  • Design operations that may be retried to be idempotent where possible.
  • Set timeouts on external calls.
  • Avoid trusting client-controlled timestamps, counters, or state transitions.
  • Consider replay, duplicate-request, and partial-failure scenarios.

15. Privacy & Sensitive Data

  • Collect only data required for the application's purpose.
  • Minimize storage and retention of sensitive information.
  • Restrict access to personal and confidential data.
  • Do not include sensitive information in URLs when avoidable.
  • Apply appropriate encryption and access controls.
  • Follow applicable privacy and data-protection requirements.

16. Code Review & Security Testing

Every security-sensitive change should receive appropriate review.

Developers should:

  • Review authentication and authorization changes carefully.
  • Check for injection and input-validation issues.
  • Run automated static analysis and dependency scanning.
  • Include security-focused tests for important controls.
  • Perform dynamic/application security testing where appropriate.
  • Treat security findings as engineering defects and track them to resolution.

17. Production Deployment

Before production deployment:

  • Ensure secrets are not present in source code or build artifacts.
  • Verify security configuration.
  • Run applicable automated security checks.
  • Confirm required authentication and authorization controls.
  • Remove debugging functionality.
  • Ensure monitoring and security logging are operational.
  • Have a rollback procedure for security-related releases.

Definition of Done — Security Checklist

A development task should not be considered complete until the developer has considered:

  • All external input is validated.
  • Authentication is correctly enforced where required.
  • Authorization is checked server-side.
  • No secrets are hard-coded or committed.
  • Database queries use safe parameterization.
  • Output is appropriately encoded.
  • Errors do not expose sensitive information.
  • Sensitive information is not unnecessarily logged.
  • Dependencies have been checked for known vulnerabilities.
  • Security-relevant functionality has appropriate tests.
  • Secure configuration has been verified.
  • Security-sensitive code has received peer review.