Penetration Testing
This page describes the PrimeCalendar attack surface relevant to penetration testing, what security controls are in place, and what is known to be incomplete or not yet hardened.
Before You Test
If you are conducting authorized penetration testing against a PrimeCalendar deployment:
- Obtain written authorization from the system owner before testing any non-local environment
- Do not test against the production database at
taseventeeen.tarhely.euwithout explicit approval — it is a shared hosted environment - Set up a dedicated test environment with a separate PostgreSQL database for destructive testing
- The backend's rate limiting (
LOGIN_MAX_ATTEMPTS=5,LOGIN_BLOCK_SECONDS=900) will trigger during brute-force tests — adjust via env vars in the test environment
Attack Surface Overview
Public endpoints (no authentication required)
GET /api/feature-flags— returns feature flag state, no sensitive dataPOST /api/auth/login— credential submission (rate-limited)POST /api/auth/register— user registrationGET /api/auth/google,GET /api/auth/microsoft— OAuth redirect initiatorsPOST /api/automation/webhooks/:token/receive— webhook receiver (token per rule, HMAC validation in progress)- Public booking pages if
ENABLE_RESERVATIONS=true
Authenticated endpoints
All other /api/* routes require a valid JWT (delivered via HttpOnly cookie). The JwtAuthGuard enforces this globally. Specific routes additionally require:
- Admin role (
AdminGuard/ role check) - Organisation membership (
OrganisationOwnershipGuard) - Feature entitlement (
FeatureAccessGuard)
WebSocket
The backend uses @nestjs/websockets with socket.io. WebSocket connections are authenticated.
Implemented Security Controls
| Control | Implementation |
|---|---|
| HTTP security headers | Helmet with CSP, HSTS, X-Frame-Options: DENY, Permissions-Policy |
| CORS | Allow-list with per-origin logging of blocked requests |
| Input validation | Global ValidationPipe with whitelist: true, forbidNonWhitelisted: true |
| Authentication | JWT (access 15m TTL, refresh 14d) via HttpOnly Secure SameSite cookies |
| CSRF protection | X-CSRF-Token header injected by secureFetch on mutating requests |
| Rate limiting | @nestjs/throttler global + login-specific lockout (LoginAttemptService) |
| Idempotency | Reservation creation requires Idempotency-Key header |
| Correlation IDs | x-request-id header on all responses, propagated through logs |
| Error sanitization | AllExceptionsFilter returns sanitized messages; stack traces are not exposed to clients |
| Token redaction | AppLoggerService redacts password, token, secret, authorization, cookie from logs |
| DOMPurify | Frontend sanitizes HTML via sanitizeHtml.ts utility |
| CSP nonces | Frontend uses CSP-compatible patterns, no inline scripts |
| XSS filter | Helmet xssFilter: false (the legacy X-XSS-Protection header is omitted as browsers ignore or misuse it; CSP is the real control) |
Known Incomplete Controls
Be aware of these gaps when scoping a pentest:
| Gap | Status | Reference |
|---|---|---|
| PostgreSQL Row Level Security | Not enabled — app-layer guards are in place but DB-level RLS is not yet active | SECURITY.md Section 2 |
| Webhook HMAC verification | In progress — the signature check is designed but not fully deployed | SECURITY.md Section 3 |
| Automated dependency scanning | Not configured (no Dependabot, no CodeQL in CI) | SECURITY.md Section 5 |
| Docker hardening | Not applied — containers may run as root | SECURITY.md Section 6 |
| Secrets manager | Secrets live in .env, no Key Vault integration | SECURITY.md Section 7 |
| OWASP ASVS compliance matrix | Not built yet | SECURITY.md Section 8 |
Priority Test Areas
Given the known gaps, these areas are highest value for a pentest:
1. Cross-tenant data isolation
The OrganisationOwnershipGuard enforces org scoping at the application layer. Verify that authenticated user A in organisation 1 cannot read, update, or delete resources belonging to organisation 2 by manipulating IDs in API requests (IDOR testing).
2. Webhook receiver
POST /api/automation/webhooks/:token/receive accepts arbitrary JSON payloads. Test:
- Whether a token from one user can be guessed or enumerated
- Whether the payload is used in any downstream operation that could be exploited (SQL injection, template injection, etc.)
- Whether the HMAC signature validation (if deployed) can be bypassed with a replayed request
3. Authentication flow
- Session fixation after login
- Refresh token rotation: verify the old token is invalidated after rotation
- Concurrent session handling
POST /api/auth/logout— verify the refresh token is invalidated server-side, not just cleared from the cookie
4. File upload paths
If any endpoint accepts file uploads, test for path traversal, file type bypass, and oversized file attacks.
5. Rate limiting bypass
Test whether the x-forwarded-for header can be spoofed to bypass IP-based rate limiting.
Reporting
If you discover a security vulnerability:
- For internal findings, file an issue or internal report referencing the relevant
SECURITY.mdsection - For external researchers, the project does not currently have a public security disclosure process (
SECURITY.mdSection 9 lists this as a planned item)
Do not publicly disclose vulnerabilities before the team has had a reasonable time to patch them.