Skip to content

Security: brook1717/BoundaryGuard

Security

SECURITY.md

BoundaryGuard — Security Policy


Supported Versions

BoundaryGuard is currently pre-1.0. Only the main branch is supported.

Component Current version Supported
identityops-core-api 0.1.0
identityops-ingestion-api 0.1.0
identityops-incident-worker 0.1.0
identityops-webhook-worker 0.1.0
identityops-sdk 0.1.0
Older commits on main
Any fork not maintained here

Security fixes are applied to main only. There are no back-ported patch releases at this time.


Responsible Disclosure Process

Do not open a public GitHub issue for security vulnerabilities.

Use GitHub's private advisory mechanism:

  1. Navigate to the Security tab of this repository.
  2. Click Report a vulnerability.
  3. Complete the private advisory form with the information described in Reporting Vulnerabilities below.

Maintainers will acknowledge the report within 5 business days and aim to deliver a fix within 30 days of confirmation. If a coordinated public disclosure date is agreed, it will be respected.

TODO: Add a PGP public key or security email address here once a dedicated security contact is established.


Reporting Vulnerabilities

Include the following in your report:

  • Affected component — e.g. core-api, worker-webhooks, sdk, dashboard, infra
  • Vulnerability class — e.g. authentication bypass, SSRF, privilege escalation, secret leakage
  • Reproduction steps — a minimal sequence of commands or requests that demonstrate the issue
  • Observed vs. expected behaviour — what the system does versus what it should do
  • Potential impact — which users, tenants, or data are affected and how
  • Suggested mitigation (optional) — if you have a proposed fix

Use the local dev stack (docker compose -f docker/docker-compose.dev.yml up -d) for reproduction. Do not test against production systems.

In scope

The following are in scope for responsible disclosure:

Area Examples
Authentication bypass Forging a valid X-API-Key or Clerk JWT to gain tenant access
RBAC privilege escalation Viewer-role caller executing freeze or admin operations
Tenant isolation failure Reading or modifying incident data across tenant boundaries
HMAC signature bypass Submitting unsigned or invalidly signed events to ingestion-api that are accepted
Blocklist bypass in the SDK middleware A revoked session passing the BlocklistMiddleware check
Audit chain manipulation Writing or modifying audit_events or mitigation_logs rows in a way that passes chain verification
Secret leakage Credentials, tokens, or plaintext secrets exposed in API responses, logs, or error messages
Infrastructure misconfiguration Public exposure of private-subnet services; IAM policy over-permissions

Out of scope

  • Vulnerabilities that require physical access to AWS infrastructure
  • Social engineering of maintainers
  • Denial-of-service attacks requiring volumetric capacity beyond a single server
  • Issues in dependencies that have no published fix (ignore-unfixed is set in Trivy)
  • TODO-marked items in ROADMAP.md that are not yet implemented

Secret Management Expectations

The following summarises how secrets are handled in this project. Contributors must follow these expectations.

Platform secrets

Secret Storage (dev) Storage (production)
HMAC_SECRET .env file (gitignored) AWS Secrets Manager → ECS task secret mapping
SDK API key (plaintext) Returned once at generation; never stored
SDK API key (hash) PostgreSQL tenants.sdk_api_key_hash (SHA-256) RDS (encrypted at rest)
CLERK_SECRET_KEY .env file (gitignored) Secrets Manager → ECS env
Auth0 client_id / client_secret / domain .env file (gitignored) Per-tenant AES-256-GCM encrypted JSONB in tenants.provider_credentials_enc
webhook_secret .env file (gitignored) AES-256-GCM encrypted in tenants.webhook_secret_enc (decrypted only in worker-webhooks)
DATABASE_URL .env file (gitignored) Secrets Manager → ECS task secret
REDIS_URL .env file (gitignored) Secrets Manager → ECS task secret

Rules for contributors:

  • Never commit secrets. .env files are gitignored. .env.example contains only non-secret placeholder values. Gitleaks scans the full git history on every push — a committed secret will block the CI pipeline.
  • Never log secrets. Do not pass credentials, tokens, or hashed keys into log statements. API key values must not appear in exception messages.
  • Store only hashes, not plaintexts. SDK API keys are stored as SHA-256 hex digests. Authentication uses hmac.compare_digest to prevent timing oracles.
  • Use rediss:// in production. The core-api startup validator (_enforce_production_tls) hard-fails if APP_ENV=production and REDIS_URL does not begin with rediss://.
  • Use DB_SSL_MODE=require or higher in production. Values disable, allow, and prefer are rejected at startup.

Dependency Update Policy

Dependencies are audited continuously through the CI security pipeline (.github/workflows/security.yml):

Tool Scope Fail threshold Frequency
Trivy (filesystem) All repo files + deps CRITICAL or HIGH CVE Every push, PR, nightly
Trivy (image) 4 service container images CRITICAL CVE Every push to main/develop
pip-audit Python deps for all 4 services Any known vulnerability Every push, PR, nightly
npm audit Dashboard Node.js deps CRITICAL level Every push, PR, nightly
GitHub Dependency Review Newly introduced deps in PRs CRITICAL severity Every PR to main/develop

Policy:

  • Any dependency introducing a CRITICAL CVE will block the CI security gate and must be resolved before merging.
  • HIGH-severity CVEs are surfaced in Trivy filesystem scans and will block CI (exit-code: "1").
  • Unfixed CVEs (no upstream patch exists) are suppressed in .trivyignore with a documented justification comment; this file is reviewed on each PR.
  • GPL-3.0 and AGPL-3.0 licensed dependencies are automatically blocked by the GitHub Dependency Review action.

Maintainers review nightly scan results at the start of each working week.

TODO: Define a maximum SLA for remediating HIGH-severity CVEs once the team grows beyond a single maintainer.


Threat Model Summary

The full threat model is maintained in THREAT_MODEL.md (classified internal/security-sensitive). The following is a public summary.

Trust boundaries

BoundaryGuard enforces defence-in-depth across six trust boundaries:

Boundary Controls
Internet → ALB AWS WAF v2 (OWASP Top 10, rate limit 2 000 req/5 min per IP, IP reputation), TLS 1.3, HTTP→HTTPS redirect
ALB → ECS Security groups restricting source to ALB only; ECS tasks in private VPC subnets with no public IPs
ECS → RDS PostgreSQL SSL verify-full; security group allowing ECS source only
ECS → Redis TLS + AUTH token; rediss:// enforced in production; security group allowing ECS source only
ECS → AWS APIs IAM Task Role with minimal SQS send/receive/delete permissions; Secrets Manager resource policy
Human → Dashboard Clerk JWT (RS256, 60 s expiry); auth.protect() enforced on all dashboard routes

Authentication model

Caller Mechanism Scope
Human operator (dashboard) Clerk JWT — RS256, JWKS-verified, 60 s expiry, tenant_id claim required Tenant-scoped; role from DB
Machine caller (SDK) X-API-Key — SHA-256 digest compared with hmac.compare_digest Tenant-scoped; non-role identity
Ingestion sender X-IdentityOps-Signature — HMAC-SHA256, replay window 300 s Provider-level

Key security controls

  • RBAC: Three-tier role hierarchy (viewer, responder, security_admin) enforced server-side on all management and action endpoints. Viewer-role callers cannot execute freeze operations.
  • Tenant isolation: All database queries include a tenant_id predicate derived from the verified Clerk JWT claim. The query parameter on the SSE stream is validated against the JWT claim — mismatches return HTTP 403.
  • Idempotent freeze: Account freeze writes an audit event and revokes token families atomically in a single serialisable PostgreSQL transaction. Idempotency-Key (UUID v4, SHA-256 hashed in Redis, 24 h TTL) prevents double-execution.
  • Tamper-evident audit chain: audit_events and mitigation_logs use a SHA-256 linked hash chain. REVOKE UPDATE, DELETE is granted to the application user — the database role cannot modify committed rows.
  • Immutable audit storage: CloudTrail multiregion with log file validation; S3 Object Lock COMPLIANCE (365 days); S3 deletion protection.
  • Read-only container filesystem: readonlyRootFilesystem: true in all ECS task definitions.

Known Limitations

The following limitations are accepted and documented. They do not have immediate mitigations but are tracked for future resolution.

ID Limitation Impact Status
AR-01 If Redis is unavailable, idempotency middleware fails open — a freeze request may execute twice Duplicate audit event; functionally idempotent (second freeze revokes 0 families) Accepted; fail-open is preferred over blocking incident response
AR-02 SDK X-API-Key tokens have no expiry — exfiltrated keys can be replayed indefinitely High if key is leaked; requires manual rotation Mitigated by WAF rate-limiting and CloudTrail monitoring; rotation workflow documented in OPERATIONS.md
AR-03 Token family issued after a freeze begins may escape the initial revocation New session is active on a frozen account until a second freeze or TTL expiry Mitigated by short token TTL (default 24 h) and GuardDuty anomaly re-detection
AR-04 A single authenticated operator can hold an unlimited number of concurrent SSE connections ECS memory pressure under extreme conditions Accepted for multi-tab SOC workflows; ECS memory alarms alert on saturation
AR-05 Clerk JWKS public key compromise would allow JWT forgery Critical; complete authentication bypass Mitigated by Clerk's HSM key management and short JWT TTL (60 s)
AR-06 Concurrent worker-incident instances may both create a new incident for the same account Duplicate open incidents for the same event Known edge case at MVP scale; addressed by a partial unique index planned in ROADMAP.md

Review this register after any significant architecture change or quarterly, whichever is sooner.

There aren't any published security advisories