Skip to content

Security

dbcooper edited this page Mar 28, 2026 · 2 revisions

Security

Security posture and secrets handling for ShadowCheck


Security Architecture

ShadowCheck uses a layered model:

  1. Transport security: HTTPS/TLS, HSTS, reverse-proxy hardening
  2. Application security: CSP, CORS, input validation, rate limiting
  3. Data security: parameterized SQL, least-privilege DB roles, audit-friendly backups
  4. Access control: session auth, admin gating, API key protection for sensitive routes
  5. Secrets management: AWS Secrets Manager as the canonical store, environment variables only as explicit runtime overrides

Security Headers

Applied by the server security middleware:

Content-Security-Policy
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Strict-Transport-Security

Exact header values can evolve with deployment settings, but the intent is stable: reduce script injection, clickjacking, MIME confusion, and downgrade risk.


Secrets Management

Current source of truth

ShadowCheck does not use Docker secrets or local keyring as the primary mechanism.

The current implementation is:

  1. AWS Secrets Manager: canonical source of truth
  2. Environment variables: explicit runtime overrides only

Secrets are loaded by server/src/services/secretsManager.ts.

What is no longer current

The following guidance is obsolete and should not be used:

  • Docker secret files under /run/secrets/*
  • local secrets/*.txt files
  • keyring / keytar workflows as the normal path

Required secrets

  • db_password

Common optional secrets

  • db_admin_password
  • mapbox_token
  • wigle_api_name
  • wigle_api_token
  • wigle_api_encoded
  • google_maps_api_key
  • mapbox_unlimited_api_key
  • opencage_api_key
  • locationiq_api_key

Resolution behavior

At startup, the app:

  1. checks for an explicit environment override for a secret
  2. otherwise loads from AWS Secrets Manager
  3. auto-generates db_password only if missing, then attempts to persist it back to AWS Secrets Manager

This means AWS remains the authoritative store even when bootstrap recovery is needed.

Operational rules

  • Do not write secrets to .env
  • Do not create helper files containing secrets
  • Do not rely on Docker secret mounts
  • Do not document keyring-only procedures as current practice
  • Keep non-secret config separate from credential material

Password Rotation

Rotate database and service credentials on a regular schedule and verify the updated values exist in AWS Secrets Manager before restarting dependent services.

If you rotate database credentials, also confirm:

  • the PostgreSQL user password matches the stored secret
  • the application can still read the updated secret
  • any admin tooling using db_admin_password is updated consistently

SQL Injection Prevention

Database queries should remain parameterized:

const result = await query('SELECT * FROM networks WHERE bssid = $1', [bssid]);

Avoid string interpolation for SQL input.


Authentication and Authorization

  • Admin-only routes remain gated behind authenticated admin access
  • Sensitive operational endpoints can require API key checks
  • Session and cookie behavior should be reviewed with every auth change

Security Best Practices

Do

  • keep credentials in AWS Secrets Manager
  • use environment variables only as intentional overrides
  • rotate credentials regularly
  • validate secrets at startup
  • use parameterized queries everywhere
  • keep file permissions tight on non-secret operational config
  • use HTTPS in deployed environments

Do not

  • commit secrets
  • store secrets in .env
  • write secret helper files to disk
  • document Docker secrets as the active production model
  • treat local keyring as the canonical source

Threat Model

Primary risks:

  • unauthorized data access
  • credential leakage
  • admin endpoint abuse
  • injection and input-manipulation attacks

Primary mitigations:

  • parameterized SQL
  • rate limiting
  • CSP / header hardening
  • least-privilege DB access
  • startup secret validation
  • keeping secrets out of the filesystem

Troubleshooting

Secret not found

If a required secret is missing:

  1. check the AWS secret exists in the configured secret bundle
  2. verify AWS region and IAM access
  3. use an environment override only if you intentionally need a temporary local override

AWS access failure

If AWS Secrets Manager cannot be reached:

  • verify AWS_REGION or AWS_DEFAULT_REGION
  • verify IAM credentials and permissions
  • confirm the configured secret name is correct

ShadowCheck may log that AWS Secrets Manager is unavailable; treat that as a deployment or credentials problem first, not as a cue to fall back to disk-backed secret files.


Related Documentation

Clone this wiki locally