OWL Enabled Node Secrets App

A small team credential vault — built directly on @owasp-webshield/core, no framework — showing every OWASP Top 10 category (A01–A10) doing real work. This example replaces core-node-demo.

Unlike the browser-based owl-enabled-react-todo-app example, this one runs in real Node, so it can use the two modules that need Node’s native crypto module and can’t run in a browser bundle: CryptoManager (real AES-256-GCM encryption at rest) and CSRFTokenManager (real, not mocked). It also runs a real npm audit, not a fixture.

Run locally

From this folder:

npm install
npm start          # scripted CLI walkthrough — every category, one run, no server
npm run serve       # a small REST API on :8787 — see "Try the API" below

What npm start demonstrates

Category Where
A01 Broken Access Control RBACManager + ACLManager + PermissionChecker — RBAC denies a viewer reveal outright; a per-secret ACL freeze denies reveal even for admin (deny-override, scoped to one secret instead of a whole resource type)
A02 Crypto Failures CryptoManager (AES-256-GCM) encrypts every secret at rest with a vault master key; SecretPolicy flags weak stored values and overdue rotations
A03 Injection InputValidator.validateSchema + InputSanitizer on secret name/description
A04 Insecure Design A lifecycle guard (active → rotating → active, active → revoked) plus abuse-case checks on metadata length, self-audited against a DesignChecklist
A05 Security Misconfiguration SecurityConfigManager + HardeningReporter, run once at boot
A06 Vulnerable Components DependencyRiskScanner backed by a real NpmAuditProvider (shells out to npm audit --json against the repo root)
A07 Auth & Session AuthManager + TokenManager
A08 Data Integrity A real CSRFTokenManager + HTTPClient
A09 Logging & Monitoring SecurityLogger — a reveal is logged with the plaintext under the key secretValue, which auto-redacts to [REDACTED] because it matches the default redact-key list; EventEmitter builds the full audit trail printed at the end
A10 SSRF SafeFetcher/SSRFGuard guards the “notify on reveal” webhook call; a literal cloud-metadata IP (169.254.169.254) is blocked

Try the API (npm run serve)

The server keeps one global session at a time (same simplification the CLI makes) — log in again to switch roles. Every mutating request needs both the bearer token from /login and the CSRF token in X-CSRF-Token; omitting either is rejected.

# Log in — returns { accessToken, csrfToken }
curl -s -X POST localhost:8787/login -H 'Content-Type: application/json' -d '{"role":"contributor"}'

TOKEN=<accessToken from above>
CSRF=<csrfToken from above>

# Rejected — no CSRF header (403 CSRF_INVALID)
curl -s -X POST localhost:8787/secrets \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"name":"STRIPE_KEY","value":"sk_live_...","description":"Stripe secret key"}'

# Accepted
curl -s -X POST localhost:8787/secrets \
  -H "Authorization: Bearer $TOKEN" -H "X-CSRF-Token: $CSRF" -H 'Content-Type: application/json' \
  -d '{"name":"STRIPE_KEY","value":"sk_live_...","description":"Stripe secret key"}'

# Log in as admin, reveal it
curl -s -X POST localhost:8787/login -H 'Content-Type: application/json' -d '{"role":"admin"}'
curl -s -X POST localhost:8787/secrets/STRIPE_KEY/reveal -H "Authorization: Bearer $TOKEN" -H "X-CSRF-Token: $CSRF"

# Freeze it (per-secret ACL deny) — reveal now fails even for admin
curl -s -X POST localhost:8787/secrets/STRIPE_KEY/freeze \
  -H "Authorization: Bearer $TOKEN" -H "X-CSRF-Token: $CSRF" -H 'Content-Type: application/json' -d '{"frozen":true}'

Other routes: GET /secrets, POST /secrets/:name/rotate ({"newValue": "..."}), DELETE /secrets/:name.

Notes