Documents
Security Anti-Patterns And Safe Coding Practices
Security Anti-Patterns And Safe Coding Practices
Type
Topic
Status
Published
Created
Mar 4, 2026
Updated
Apr 3, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

Security Anti-Patterns And Safe Coding Practices#

Lead Section#

DBSurveyor enforces security-first development principles through explicit prohibition of dangerous patterns and mandatory safe coding practices. The codebase implements comprehensive security guarantees for credential protection, encryption, and database operations.

Key security principles:

Explicitly Prohibited Security Anti-Patterns#

Credential Exposure#

Never log or expose database credentials in any form. Prohibited patterns include:

Logging connection strings:

// NEVER do this
log::info!("Connecting to {}", database_url);

Including credentials in error messages:

// NEVER do this
#[error("Failed to connect to {url}")]
ConnectionError { url: String },

Storing credentials in persistent structs

Connection strings are sanitized in all error messages and logs - credentials are automatically masked (e.g., postgres://user:secret123@localhost becomes postgres://user:****@localhost).

Unsafe unwrap() Usage#

All code must pass cargo clippy -- -D warnings, treating all clippy warnings as compilation errors.

Never use unwrap() in production:

  • Prohibited: Using unwrap() or expect() on Result or Option types
  • Required: Use proper error propagation with ? operator or explicit error handling

SQL String Concatenation#

All queries must use parameterized statements with no SQL injection risk.

Never concatenate SQL strings:

// NEVER do this
format!("SELECT * FROM {}", table)

Required: Use parameterized query interfaces provided by database drivers

Clippy Lint Suppression#

Zero warnings requirement means suppressing clippy lints is not acceptable.

Never suppress clippy lints:

// NEVER do this
#[allow(clippy::all)]

Required: Fix the underlying code issue instead of suppressing the lint

Required Safe Coding Practices#

Zeroize Trait for Sensitive Data#

Credentials must be automatically zeroed using the zeroize crate.

Required pattern (actual implementation):

use zeroize::{Zeroize, Zeroizing};

#[derive(Debug, Clone, Zeroize)]
#[zeroize(drop)]
pub struct Credentials {
    pub username: Zeroizing<String>,
    pub password: Zeroizing<Option<String>>,
}

Purpose: Ensure credentials are automatically zeroed from memory when dropped.

Connection String Parsing#

Credentials must be parsed separately from connection configuration.

Required pattern (actual implementation):

pub fn parse_connection_string(
    connection_string: &str,
) -> crate::Result<(ConnectionInfo, Credentials)> {
    let url = url::Url::parse(connection_string)?;

    let username = url.username().to_string();
    let password = url.password().map(|p| p.to_string());
    let credentials = Credentials::new(username, password);

    let config = ConnectionInfo {
        scheme: url.scheme().to_string(),
        host,
        port,
        database,
        query_params: url.query_pairs().into_owned().collect(),
    };

    Ok((config, credentials))
}

The ConnectionInfo struct intentionally excludes credentials and provides a to_safe_string() method for logging.

Sanitized Logging#

Credentials must never appear in log output.

Correct logging patterns:

log::info!("Connecting to database");
log::debug!("Connection timeout: {}", config.to_safe_string());

Never log sensitive data:

log::info!("Connecting to {}", database_url);

Sanitization implementation (redact_database_url function):

pub fn redact_database_url(url: &str) -> String {
    match url::Url::parse(url) {
        Ok(mut parsed_url) => {
            if parsed_url.password().is_some() {
                let _ = parsed_url.set_password(Some("****"));
            }
            parsed_url.to_string()
        }
        Err(_) => "<redacted>".to_string(),
    }
}

This function is used in connection pool error messages.

Parameterized Queries#

All queries must use parameterized statements.

Implementation example (PostgreSQL sampling):

let rows = sqlx::query(pk_query)
    .bind(table)
    .bind(schema)
    .fetch_all(pool)
    .await

Column collection uses parameterized queries with placeholders:

WHERE c.table_name = $1
AND c.table_schema = $2

let column_rows = sqlx::query(columns_query)
    .bind(table_name)
    .bind(schema)
    .fetch_all(&self.pool)

Database adapters: Use driver-provided parameterized query interfaces (sqlx for PostgreSQL/MySQL/SQLite, mongodb driver for MongoDB).

Read-Only Transaction Mode#

All database operations are SELECT/DESCRIBE only; no INSERT, UPDATE, DELETE, or DDL operations.

Required enforcement (PostgreSQL adapter):

// Set read-only mode if requested (enforced by default for security)
if read_only {
    conn.execute("SET default_transaction_read_only = on")
        .await?;
}

The default ConnectionConfig enforces read-only mode:

impl Default for ConnectionConfig {
    fn default() -> Self {
        Self {
            // ...
            read_only: true, // Enforced by default
            // ...
        }
    }
}

Additional protection: Recommend using read-only database users.

Statement Timeouts#

All connections and queries must have configurable timeouts.

Required configuration (default timeouts):

ConnectionConfig {
    connect_timeout: Duration::from_secs(30),
    query_timeout: Duration::from_secs(30),
    max_connections: 10,
    read_only: true,
}

Enforcement (statement timeout via after_connect callback):

// Set query timeout to prevent resource exhaustion
conn.execute(
    format!("SET statement_timeout = '{}s'", query_timeout_secs).as_str(),
)
.await?;

// Set lock timeout to prevent blocking operations
conn.execute("SET lock_timeout = '30s'").await?;

// Set idle timeout for session cleanup
conn.execute("SET idle_in_transaction_session_timeout = '60s'")
    .await?;

Workspace-Level Security Policies#

No Unsafe Code#

The workspace enforces a strict no-unsafe-code policy.

Enforcement (Cargo.toml workspace lints):

[workspace.lints.rust]
unsafe_code = "deny" # No unsafe code allowed (security)
missing_docs = "warn" # Documentation required
unreachable_pub = "warn" # No dead public APIs

No unsafe blocks are permitted without explicit security review and documentation.

Zero Warnings Policy#

All contributions must pass cargo clippy -- -D warnings.

Enforcement (Cargo.toml clippy configuration):

[workspace.lints.clippy]
all = "deny" # Strict linting
pedantic = { level = "warn", priority = -1 }

# Security-specific lints
unwrap_used = "deny" # No unwrap in production code
expect_used = "deny" # Use proper error handling
panic = "deny" # No panic in production code

Justfile enforces -D warnings:

clippy:
    cargo clippy --workspace --all-targets --all-features -- -D warnings

Error Sanitization Policy#

All error messages must be sanitized to prevent credential leakage.

Implementation: Error messages are sanitized throughout the adapter layer to prevent credential exposure, using generic messages like "Database connection failed" rather than including connection details.

Offline Operation Guarantee#

No external network calls permitted beyond database connections:

  • NO NETWORK CALLS
  • NO TELEMETRY
  • NO AUTO-UPDATES
  • AIRGAP COMPATIBLE

Validation and Testing#

Security validation commands (justfile):

just security-full # Complete security validation
just test-encryption # Test encryption capabilities
just test-offline # Verify offline operation
just test-credential-security # Check for credential leakage
just audit # Security audit

Security Test Suite#

Comprehensive credential security tests validate credential protection at the integration layer.

Security-sensitive contributions require comprehensive security tests.

Contribution Security Requirements#

Security-sensitive contributions require additional review:

  1. No credential exposure
  2. Offline operation only
  3. Encryption security (AES-GCM with random nonces)
  4. Memory safety (use zeroize)
  5. Test coverage (>80% with security-specific tests)
  6. Threat model review
  7. Documentation updates

Relevant Code Files#

File PathPurposeKey Security Features
.kiro/specs/database-schema-collection/design/security.mdSecurity architecture documentationComprehensive security guarantees, anti-patterns, implementation examples
dbsurveyor-core/src/security/credentials.rsCredential handlingZeroize trait implementation, secure memory clearing
dbsurveyor-core/src/security/connection.rsConnection parsingSeparation of credentials from config, sanitized logging
dbsurveyor-core/src/error.rsError handlingredact_database_url function for credential sanitization
dbsurveyor-core/src/adapters/config/connection.rsConnection configurationDefault read-only mode, timeout configuration
dbsurveyor-core/src/adapters/postgres/connection.rsPostgreSQL connectionRead-only mode enforcement, statement timeouts via after_connect
dbsurveyor-core/src/adapters/postgres/schema_collection.rsSchema collectionParameterized queries for metadata collection
dbsurveyor-core/src/adapters/postgres/sampling.rsData samplingParameterized queries for data sampling
dbsurveyor-collect/tests/security_tests.rsSecurity test suiteCredential leak detection, error sanitization validation
Cargo.tomlWorkspace configurationWorkspace-level lints, unsafe code denial, clippy enforcement
justfileBuild automationSecurity validation commands, clippy with -D warnings
.github/workflows/ci.ymlCI/CD pipelineAutomated security checks in CI
.github/workflows/security.ymlSecurity workflowDedicated security validation pipeline
  • Credential Memory Security in Rust: Implementation of secure credential handling using Rust's Zeroize crate for automatic memory clearing
  • Database Connection Security Architecture: Design patterns for separating credentials from configuration and enforcing read-only operations at the connection level
  • Query Safety and SQL Injection Prevention: Use of parameterized queries with bind parameters across PostgreSQL operations to prevent SQL injection
  • Rust Security Linting Enforcement: Workspace-level cargo configuration and CI/CD pipelines that enforce strict security-focused clippy lints with zero-warning policies
  • Security Testing Infrastructure: Dedicated security test suite, justfile commands, and CI workflows that validate security guarantees
Security Anti-Patterns And Safe Coding Practices | Dosu