Please report security vulnerabilities to security@ndsep.gov.ng or open a private GitHub Security Advisory. Do not file public issues for security bugs.
| Package | CVE / GHSA | Severity | Resolution |
|---|---|---|---|
fast-xml-parser |
GHSA-gh4j-gqv2-49f6 | Moderate | Forced to >=5.7.0 via pnpm override |
| Package | CVE / GHSA | Severity | Reason Accepted |
|---|---|---|---|
uuid |
GHSA-w5hq-g745-h8pq | Moderate | Requires caller to pass explicit buf argument; NDSEP never passes user-controlled buffers to uuid. Upstream packages (@temporalio/client, exceljs, mermaid) have not released uuid v14 compatible versions. Will upgrade when upstream support is available. |
| Control | Status |
|---|---|
| Helmet CSP headers (strict in production) | ✅ Enabled |
| HSTS (1 year, includeSubDomains, preload) | ✅ Production |
| Rate limiting (API: 200/min, Auth: 20/15min) | ✅ Enabled |
| SQL injection prevention (parameterised queries) | ✅ All queries |
| XSS filter (helmet xssFilter) | ✅ Enabled |
| HTTP parameter pollution guard | ✅ Enabled |
| Suspicious request guard (SQL/XSS in URLs) | ✅ Enabled |
| Body sanitiser on all tRPC mutations | ✅ Enabled |
| Auth failure tracker (brute-force alerting) | ✅ Enabled |
| Request ID middleware (X-Request-ID) | ✅ Enabled |
| Security audit logger (401/403/429) | ✅ Enabled |
| Stripe webhook signature verification | ✅ Enabled |
| Open redirect prevention (demo-login) | ✅ Enabled |
| No hardcoded secrets in application code | ✅ Verified |
| Environment variables via platform secrets | ✅ Configured |
| Role-based access control (admin/user) | ✅ Enforced |
| JWT session signing (JWT_SECRET) | ✅ Enabled |
| CORS restricted to known origins | ✅ Enabled |
| Field-level encryption (AES-256-GCM) | ✅ Enabled |
| PII columns encrypted at rest (27 fields, 13 tables) | ✅ Enabled |
| PostgreSQL SSL with CA verification | ✅ Production |
| Encrypted volume support (LUKS/cloud KMS) | ✅ Configured |
| pgcrypto extension for DB-level crypto ops | ✅ Enabled |
| Encryption key rotation support | ✅ Available |
| Redis dangerous commands disabled (FLUSHALL/FLUSHDB/DEBUG) | ✅ Enabled |
| PostgreSQL data checksums (corruption detection) | ✅ Enabled |
All PII columns are encrypted with AES-256-GCM using a 256-bit key via FIELD_ENCRYPTION_KEY. Encrypted values are stored as enc:v1:<iv>:<authTag>:<ciphertext> — each value has a unique random IV (12 bytes) and authenticated encryption tag (16 bytes).
Protected fields (27 columns across 13 tables):
users.email,users.nameorganizations.contact_emailcitizen_requests.citizen_email,citizen_requests.citizen_ninbreach_incidents.data_subject_email,breach_incidents.data_subject_nindpo_appointments.dpo_email,dpo_appointments.dpo_phonedpco_registrations.email,dpco_registrations.phone,dpco_registrations.dpo_email- All
contact_name,contact_email,contact_phonefields in portal/DPCO tables - See
server/encryption.ts→PII_FIELDSfor the complete list.
Production docker-compose.production.yml is configured for encrypted volume mounts:
PG_DATA_DIR→ PostgreSQL data directory (use LUKS, AWS EBS encryption, or GCP CMEK)REDIS_DATA_DIR→ Redis persistence directory
- Generate key:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" - Rotate key:
OLD_KEY=<old> NEW_KEY=<new> DATABASE_URL=<url> npx tsx scripts/rotate-encryption-key.ts - Dry run: append
--dry-runto rotation script
OWASP Top 10 Assessment: A+ (0 critical, 0 high, 0 medium exploitable)
The 3 remaining moderate findings are transitive dependencies with no exploitable code path in NDSEP's usage pattern.