Skip to main content

Security Testing Policy

Security Testing Policy

Project / Organization: BilkoALAI Holding ASBalkanDrop AccountingPayment SaaSApp Policy Number: POL-SEC-TEST-001 Version: 1.0 Date: 2026-02-23 Author: ComplianceSecurity Architect Status: Draft Reviewers: CTO,CISO, Engineering LeadLead, CTO Next Review: 2026-08-2027-02-23 Classification: Confidential

Document History

Version Date Author Changes
0.1 2026-02-23 ComplianceSecurity Architect Initial draft — BilkoDrop security testing policymethodology

1. Purpose & Scope

Purpose: This policy defines the security testing methodology, tools, frequency, and remediation requirements for all systems operated by Bilko.ALAI Holding AS for the Drop payment app. Security testing is mandatory — no system goes to production without completing applicable security tests.

Regulatory basis:

  • IKT-forskriften (FOR-2003-05-21-630) §§ 5-6 — ICT security verification
  • DORA (EU) 2022/2554 Art. 24-25 — Digital operational resilience testing
  • Finanstilsynet licensing requirements — penetration test before production launch
  • GDPR Art. 32(1)(d) — regular testing of technical measures

Scope:

  • All production applications:APIs bilko.ioand endpoints (Vercel)getdrop.no, api.bilko.io (Railway)getdrop.no)
  • PostgreSQLAll databaseAWS infrastructure (RailwayApp EURunner, West)
  • S3,
  • CloudflareKMS, R2Secrets file storageManager)
  • All CI/CD pipelines and build systems
  • Third-All third-party integrations: SEFintegrations (Serbia),BankID, HR-FISK/FINASumsub, (Croatia)Open Banking partners)
  • Developer workstations handling Confidential or Restricted data

Policy Owner: Compliance ArchitectCISO ([email protected])[email protected]) Operational Owner: Security team + Engineering Lead

Regulatory basis:

  • GDPR Art. 32 — "regular testing, assessing and evaluating the effectiveness of technical and organisational measures"
  • ZZPL Art. 50 (Serbia) — security testing obligation
  • Zakon o računovodstvu — integrity of financial processing systems

2. Security Testing Methodology

Approach: Shift-left security — testing integrated throughout development, not bolted on at the end.

Testing layers:

Development Phase
    ├──+-- SASTUnit security testsStatic code analysisVitest (everycurrent: commit)20+ ├──security-specific tests)
    +-- SCA — Dependencynpm vulnerability scanaudit (every commit)commit, └──automated)
    +-- Secret scanning — Detectdetect leaked credentials (every commit)

Build / CI Phase
    ├──+-- SAST — Fullstatic codebasecode scananalysis (every PR — planned Phase 2)
    +-- SCA — dependency vulnerability check (every PR)
    ├── SCA — Full dependency audit (every PR)
    └──+-- Secret scanning — Full repofull scan (every PR)

Deployment Phase
    ├──+-- DAST — OWASP ZAP scan against staging (everyplanned deployment) └──Phase 3)
    +-- API security:security Org-scopescan isolation testsendpoint fuzzing (everyplanned deployment)— Phase 3)

Operational Phase
    ├──+-- Vulnerability assessment — Externalexternal attack surface (quarterly)
    └──+-- Penetration test — Manualmanual expert testing (annual,before Phase 2+)3 launch)
    +-- Post-incident review — regression tests after any security incident

3. Current Security Test Coverage

3.1 Vitest Unit Security Tests

Status: Implemented — 20+ security-specific tests Source: src/drop-app/src/__tests__/

Test CategoryTestSource
AuthenticationJWT secret required in productionauth.test.ts
AuthenticationCookie: httpOnly=true, secure=true, sameSite=strictauth.test.ts
AuthenticationJWT contains setIssuedAt()auth.test.ts
AuthenticationSession revocation: revoked token rejectedauth.test.ts
AuthenticationLogout revokes all user sessionsauth.test.ts
Passwordbcrypt used — not SHA-256utils-server.test.ts
Passwordbcrypt cost factor >= 12utils-server.test.ts
PasswordSHA-256 hash rejected as invalid (fix C4)utils-server.test.ts
Input ValidationIBAN checksum validationvalidation.test.ts
Input ValidationCurrency whitelist enforcedvalidation.test.ts
Input ValidationLanguage whitelist enforcedvalidation.test.ts
Input ValidationAmount: NaN/Infinity rejectedvalidation.test.ts
Input ValidationHTML tags stripped by sanitizeText()validation.test.ts
SQL InjectionParameterized queries for all user inputsdb.test.ts
Rate LimitingAuth rate limit: 10/60s enforcedmiddleware.test.ts
Rate LimitingTransaction rate limit: 10/60s enforcedmiddleware.test.ts
CSRFOrigin header validatedmiddleware.test.ts
CSRFInvalid origin rejectedmiddleware.test.ts
IDORTransaction query scoped to user_idtransactions.test.ts
IDORRecipient query scoped to user_idrecipients.test.ts
Feature FlagsCards endpoint returns 404 when flag disabledfeature-flags.test.ts

3.2 Running the Security Test Suite

# Run all security tests
cd src/drop-app && npx vitest run --reporter verbose

# Run specific security test file
npx vitest run src/__tests__/auth.test.ts

# Run with coverage
npx vitest run --coverage

Blocking criteria: All security tests MUST pass before merge to main branch.


4. Testing Types, Tools & Schedule

3.4.1 SAST — Static Application Security Testing

Purpose: Detect security vulnerabilities in TypeScript/JavaScript source code.

PropertyValue
ToolESLint with eslint-plugin-security + TypeScript strict mode
FrequencyEvery commit (pre-commit hook) + every PR (CI)
LanguagesTypeScript (frontend Next.js + backend Express)
IntegrationPre-commit hook + GitHub Actions
BlockingYES — PR cannot merge if Critical or High findings

SAST rules in scope:

  • OWASP Top 10 (A01-A10)
  • SQL injection patterns
  • XSS patterns (dangerouslySetInnerHTML without sanitization)
  • Hardcoded secrets / API keys
  • Insecure JWT usage (no algorithm verification, expired tokens not rejected)
  • Raw SQL in Prisma ($queryRaw with user input)
  • Missing org-scope WHERE clauses
  • No-eval, no-unsafe-regex rules

ESLint configuration:

{
  "extends": ["plugin:security/recommended"],
  "rules": {
    "security/detect-object-injection": "warn",
    "security/detect-non-literal-regexp": "error",
    "security/detect-possible-timing-attacks": "error",
    "no-eval": "error",
    "@typescript-eslint/no-explicit-any": "error"
  }
}

3.2 DAST — Dynamic Application Security Testing

Purpose: Detect runtime vulnerabilities by sending attack traffic to a running instance.

PropertyValue
ToolOWASP ZAP (Zed Attack Proxy)
FrequencyEvery deployment to staging + weekly full scan
Targethttps://staging.bilko.io — NEVER production without written approval
IntegrationPost-deployment CI step
BlockingYES — deployment halted if Critical finding

DAST scan scope for Bilko:

  • All API endpoints (authenticated + unauthenticated)
  • Authentication flows: login, register, password reset, 2FA
  • Invoice CRUD endpoints (create, update, delete)
  • Expense endpoints
  • VAT report generation
  • File upload (receipt attachments)
  • SEF/HR-FISK submission endpoints
  • Org-scope isolation (cross-tenant access attempts)
  • Security headers presence and correctness
  • SSL/TLS configuration

Critical Bilko-specific DAST tests:

1. Cross-tenant IDOR test:
   - Login as org A user
   - Attempt GET /api/v1/invoices/{invoice-id-from-org-B}
   - Expected: 403 Forbidden
   - If 200: CRITICAL finding — immediate halt

2. RBAC bypass test:
   - Login as accountant role
   - Attempt POST /api/v1/invoices (create)
   - Expected: 403 Forbidden
   - Attempt DELETE /api/v1/invoices/{id}
   - Expected: 403 Forbidden

3. SQL injection via Prisma:
   - Attempt org-scope bypass via invoice filter parameters
   - Expected: Prisma parameterization prevents injection

4. Tax ID in response check:
   - Verify tax IDs returned as masked/encrypted, not plaintext
   - Verify tax IDs not present in error responses or logs

3.3 SCA — Software Composition Analysis

Purpose:Status: IdentifyImplemented known(npm vulnerabilities in open source dependencies.audit)

Property Value
Tool npm audit (built-in) + GitHub Dependabot (GitHub)planned)
Frequency Every commit (Dependabot)pre-commit hook) + weeklyevery full npm auditPR
Blocking YES — PR cannot merge with Critical CVE blocks merge

Current dependency security status (unresolved)2026-02-13 audit):

PackageVersionRiskStatus
jose^6.1.3LowNo known CVEs
License checkbcryptjs YES^3.0.3LowNo known CVEs
better-sqlite3^12.6.2LowNo known CVEs
next16.1.6LowRecent version
react19.2.3LowLatest major
radix-ui^1.4.3LowUI onlycopyleftno licensesknown require legal reviewCVEs

Source: ~/ALAI/products/Drop/security/drop-security-rapport.md

Dependency update policy:

  • Security patches (Critical/High CVE)High): Merge within 24hSLA /(see 7 days per remediation SLA§5)
  • Minor security updates: Merge within 14 days
  • Major updates: Planned migration within 90 days

Approved licenses: MIT, Apache 2.0, BSD (2-clause, 3-clause), ISC Requires review: GPL, LGPL, AGPL

Current


Bilko

4.2 key dependencies to monitor:

prisma (ORMSASTSQLStatic injection prevention)
jsonwebtoken / jose (JWT — auth bypass if vulnerable)
bcrypt / bcryptjs (password hashing — compromise risk)
zod (input validation — bypass risk)
express (web framework — RCE risk)

3.4 VitestApplication Security TestsTesting

Purpose:Status: Bilko-specificPlanned automated(Phase security regression tests for accounting isolation.2)

Property Value
Tool VitestSemgrep or CodeQL (unitvia +GitHub integration)Advanced + Playwright (E2E)Security)
Frequency Every commitPR (CI)full scan)
LanguagesTypeScript, JavaScript
Blocking YES — testCritical failureor blocksHigh deploymentfindings block merge

RequiredSAST securityrules testin cases:scope (when implemented):

  • SQL injection detection (parameterized queries validation)
  • JWT algorithm confusion (/alg: none detection)
  • Hardcoded secrets / 1.credentials
  • RBAC
  • Insecure testscryptography (MD5, SHA-1, DES, RC4)
  • Path traversal / LFI
  • IDOR patterns (database queries without user_id scoping)
  • Missing authentication middleware

4.3 DASTallDynamic role/actionApplication combinationsSecurity describe('RBAC',Testing

Status: Planned ()Phase => { test('accountant cannot create invoice', async () => { const res = await api.post('/api/v1/invoices', invoice, { role: 'accountant' }); expect(res.status).toBe(403); }); test('viewer cannot generate report', async () => { const res = await api.get('/api/v1/reports/vat', { role: 'viewer' }); expect(res.status).toBe(403); }); }); // 2. Org-scope isolation tests describe('Multi-tenant isolation', () => { test('org A cannot access org B invoice', async () => { const orgBInvoice = await createInvoice({ org: 'org-b' }); const res = await api.get(`/api/v1/invoices/${orgBInvoice.id}`, { org: 'org-a' }); expect(res.status).toBe(403); }); test('org A cannot list org B contacts', async () => { const res = await api.get('/api/v1/contacts', { org: 'org-a' }); expect(res.body.data.every(c => c.organizationId === 'org-a-id')).toBe(true); }); }); // 3. VAT calculation accuracy tests describe('VAT calculations', () => { test('Serbian VAT at 20%', () => { expect(calculateVAT(new Decimal('100.00'), 'RS')).toEqual(new Decimal('20.00')); }); test('Croatian VAT at 25%', () => { expect(calculateVAT(new Decimal('100.00'), 'HR')).toEqual(new Decimal('25.00')); }); test('BiH VAT at 17%', () => { expect(calculateVAT(new Decimal('100.00'), 'BA')).toEqual(new Decimal('17.00')); }); test('NUMERIC precision3nobefore floatproduction rounding',launch)

=>{expect(calculateVAT(newDecimal('33.33'),
PropertyValue
ToolOWASP ZAP ()planned)
Frequency Every 'RS')).toEqual(newdeployment Decimal('6.67'));to });staging });+ weekly full scan
Targethttps://staging.getdrop.no 4. NEVER production without CISO written approval
BlockingYES — deployment halted if Critical finding discovered

DAST scan scope:

  • All 24 API endpoints (authenticated + unauthenticated)
  • Authentication flows (login, registration, logout, session handling)
  • Rate limiting (verify 10/60s limits enforced)
  • CSRF protection (Origin header validation)
  • Input validation tests(IBAN, describe('Zodcurrency, validation',language, amount)
  • Security headers presence (HSTS, CSP, X-Frame-Options, etc.)
  • =>
  • SSL/TLS { test('rejects non-UUID customerId', asyncconfiguration ()TLS =>1.3, {no constTLS res1.0/1.1)
  • =
  • JWT await api.post('/api/v1/invoices', { customerId: 'not-a-uuid' }); expect(res.status).toBe(400); }); test('rejects future invoice date beyond 1 year', asynchandling ()expiry, =>algorithm, {revocation)
  • const
  • Feature resflag =enforcement await(cards api.post('/api/v1/invoices',endpoints {return invoiceDate:404 '2030-01-01'when });disabled)
  • expect(res.status).toBe(400);
}); });

3.54.4 Penetration Testing

Purpose:Status: ExpertRequired manualbefore securityPhase assessment.3 production launch (Finanstilsynet licensing requirement)

Property Value
Frequency AnnualBefore minimum;production afterlaunch major+ architecturalannual changesthereafter
WhenScope BeforeFull Croatia/Serbiaapplication launch+ (mandatoryAPI for+ HR-FISKAWS compliance)
ProviderExternal security firm (TBD)infrastructure
Methodology OWASP Testing Guide v4.2 + PTES
ProviderExternal security firm (not yet selected)
Blocking Critical findings: system taken offline until remediated

Penetration test scope for Bilko:scope:

In-scope:
- Production:Staging pre-launch: https://bilko.io,staging.getdrop.no
- Production (after launch): https://getdrop.no, https://api.bilko.iogetdrop.no
- Authentication flows (login, register,registration, 2FA,BankID passwordOIDC reset)callback — Phase 2)
- All 24 authenticated API endpoints
- Multi-tenantSession isolationmanagement (IDORJWT, acrosscookie organizations)handling, revocation)
- FileRate uploadlimiting (receiptand attachments)CSRF protection
- SEFAWS andApp HR-FISKRunner submission endpointsconfiguration
- FinancialCloudflare calculationWAF integrity (VAT, double-entry)configuration

Out-of-scope:
- Denial of service attacks
- RailwaySocial andengineering Vercelof staff without prior approval
- AWS infrastructure itself (cloudAWS providerglobal responsibility)
- CloudflareBankID infrastructureNorge AS systems
- Social engineering
- Third-party SEF/FINASumsub systems

Rules of engagement:
- Testing window: AgreedTo be agreed in writing with provider
- Notify before engagementtesting: [email protected]
- Halt on critical finding: Immediately notify [email protected][email protected] -+ Test accounts provided: Separate test organizations in stagingCTO

Key test areas for Drop:

  1. JWT manipulation (algorithm confusion, expiry bypass, forged tokens)
  2. Session revocation bypass (sessions table manipulation)
  3. IDOR attacks (user_id scoping validation across all 24 endpoints)
  4. Rate limiting bypass (IP spoofing via X-Forwarded-For)
  5. CSRF (Origin header bypass)
  6. SQLi in all 24 endpoints (parameterized query verification)
  7. BankID OIDC callback manipulation (Phase 2)
  8. Feature flag bypass (cards endpoints when disabled)
  9. Foedselsnummer exposure (ensure never in plaintext logs or API responses)

4.5. Vulnerability Classification & Remediation SLAs

4.5.1 Severity Classification (CVSS v3.1)

forgery,bypass,
Severity CVSS Score Drop-Specific DefinitionBilko Example
Critical 9.0-10.0 Remote code execution, fullRCE, auth bypass,bypass without credentials, mass dataPII accessexfiltration, withoutJWT auth Prismafoedselsnummer raw SQL injection exposing all orgsexposure
High 7.0-8.9 Privilege escalation, IDOR (cross-tenantuser IDOR,data authenticatedaccess), auth bypass Org-scope(authenticated), bypassSQL — viewing another org's invoicesinjection
Medium 4.0-6.9 Limited data exposure, CSRF, RBACreflected bypassXSS, forrate non-criticallimit action Viewerinformation role accessing reportsdisclosure
Low 0.1-3.9 Minor infoVersion disclosure, theoretical riskStack trace inweak error responsemessages, minor misconfigurations
Informational N/A Best practice recommendationMissing cache-control headerrecommendations

4.5.2 Remediation SLAs

Severity SLA Action on Breach of SLA
Critical ImmediateContainment containmentin 4h; full remediation in 24 hours Emergency — CISO + CTO + CEO. System taken offline if risk cannot be mitigated; notify CEOmitigated.
High 7 calendar days Escalate to CTO + CEO.CISO. Engineering managerLead approvesmust approve extension.
Medium 30 calendar days Engineering leadLead tracks. Exception requires Security team sign-off.
Low 90 calendar days Backlog.Tracked Quarterlyin backlog. Reviewed in quarterly security review.
Informational Next sprint (best effort) Not SLA-bound.

Cross-tenantSLA IDOR (High+) is treated as Critical for Bilkotracking: GitHub financialIssues datawith exposurelabel forsecurity-finding any+ organizationseverity triggers immediate P1 incident response.label.


5.6. Security Code Review Checklist

Required for every PR touching authentication, RBAC,authorization, financialpayment calculations,processing, PII, or PII:cryptography:

Authentication & Authorization:

  • No hardcoded secretscredentials, inJWT codesecrets, or API keys
  •  Password hashing uses bcrypt (cost >= 12) — SHA-256 explicitly rejected (fix C4)
  • JWT validated:validation: signature, expiry, iss,iat audclaim verified via jose
  • org-scopedSession WHERErevocation: clauseall onprotected everyendpoints Prismacheck querysessions touchingtable multi-tenantfor datarevoked = 0
  • RBACNo requireRole()role middlewareflags appliedfrom onuser-supplied every protected endpointinput
  • 2FAAll codeprotected validationendpoints useshave constant-timeauthentication comparisonmiddleware applied
  •  Logout revokes sessions server-side (not just clears cookie)

Input Validation:

  • ZodAll schemauser forinputs allvalidated requestusing bodiesDrop validators (validateAmount, validateIBAN, validateCurrency, validateLanguage, sanitizeText)
  • PrismaAll database operations use parameterized ? queries only — no $queryRawstring with user inputconcatenation
  • FileUser uploads:data typequeries validated,include storedAND inuser_id R2= not? webrootscoping (IDOR prevention)
  • No stringeval(), exec(), or shell command interpolation inwith SQLuser or system commands

Financial Integrity:

  •  All monetary values use Decimal / NUMERIC — no number or float
  •  VAT rates validated against country code (not user-supplied)
  •  Double-entry: debit = credit enforced
  •  Exchange rates locked at transaction dateinput

Cryptography:

  • No MD5, SHA-1, DES, RC4 anywhere(per data-encryption-policy.md §2.2)
  • Random values fromuse crypto.randomBytes() — not Math.random()
  • bcryptIVs/nonces costare factorrandom =(96-bit 12minimum) forand anynever new password hashingreused
  • PrivateNo cryptographic keys / secrets not in source codecode, logs, or logserror messages

Error Handling:

  •  No stack traces or internal paths in API error responses
  •  Generic messages for authentication failures (no user enumeration)
  •  Errors logged to Sentry internally but not exposed in API responses

Data Handling:

  • TaxFoedselsnummer IDsnot logged in plaintext (PIB/JMBG/OIB/JIB)never andin IBANSentry, encryptedBetterStack, before storageconsole.log)
  • Sensitive data not in query parameters or(use URLsPOST body)
  • PIIFeature notflags inchecked Sentrybefore errorany reportscards-related (use .addEventProcessor() to scrub)endpoint
  • LoggedActionAML entriesretention: foruser alldata financialdeletion mutationsrespects 5-year retention (Hvitvaskingsloven § 30)

Dependencies:

  •  New dependencies reviewed with npm audit before adding
  •  No end-of-life packages introduced
  •  License compatible (MIT, Apache 2.0, BSD, ISC)

6.7. Security Testing in CI/CD Pipeline

Current pipeline (MVP):

Developer Commit
    +-- Pre-commit hook: npm audit (SCA)
        |
        v
    Git Push -> PR
        |
        v
    Vitest security tests (20+ tests)
        |
        v (all pass)
    Merge to main
        |
        v
    Deploy to AWS App Runner

Target pipeline (Phase 2+):

flowchart LR
    COMMIT[Developer\nCommit] -->|Pre-commit| SAST_INC[ESLint\nSASTSCA_INC[npm incremental]audit\nSCA SAST_INCcheck]
    SCA_INC -->|Pass| PUSH[Git Push]
    PUSH --> PR[Pull Request]

    PR --> SAST_FULL[ESLintVITEST[Vitest\nSecurity Full\n+ TypeScript strict]Tests]
    PR --> SCA[SAST[SAST\nSemgrep/CodeQL]
    PR --> SCA_FULL[npm audit\nDependabot]nFull scan]
    PR --> SECRET[Secret\nScanning]

    PR --> VITEST[Vitest\nSecurity tests]

    SAST_FULLVITEST & SCASAST & SCA_FULL & SECRET & VITEST -->|All pass| BUILD[Build]Build\nDrop App]
    BUILD --> STAGING[Deploy Staging]to\nStaging]
    STAGING --> DAST[OWASP ZAP\nDAST scan]
    STAGING --> E2E[Playwright\nIsolation tests]Scan]
    DAST & E2E -->|Pass| GATE{Security Gate}Security\nGate}

    GATE -->|Pass| PROD[Deploy Production]to\nProduction]
    GATE -->|Fail| BLOCK[Block Deploy\nAlert [email protected]][email protected]]

Pipeline security gate criteria:

Gate Tool Blocking Criteria
Pre-commit ESLint security rulesCritical findings in changed files
PR gate 1ESLint + TypeScript strictAny Critical or High
PR gate 2npm audit Critical CVE
PR gate 3Secret scanningAny detected secret
PR gate 41 Vitest security tests Any test failure
PR gate 2SAST (Phase 2)Critical or High finding
PR gate 3npm audit fullCritical CVE
PR gate 4Secret scanningAny detected secret
Post-staging OWASPDAST ZAP(Phase 3) Critical or High dynamic finding

8. Security Audit History

DateTypeProviderFindingsStatus
Post-staging2026-02-12 PlaywrightFull E2Esecurity isolationaudit Cross-tenant access succeedsInternal (shouldSecurity fail)Architect)4C / 5H / 6M / 4LComplete
2026-02-13Hardening verificationInternal0C / 0H / 2M / 4LComplete
TBD (Phase 3)External penetration testTBDPlanned — required before launch
TBD (Phase 3+)Annual pentestTBDAnnual thereafter

Source: ~/ALAI/products/Drop/security/drop-security-rapport.md

Security Hardening Summary (2026-02-13)

FindingIDStatus
Card data: only last_four + token_ref stored (no PAN/CVV)C1Resolved
Demo credentials gated behind NODE_ENV !== 'production'C2Resolved
SHA-256 password support removed — bcrypt onlyC4Resolved
Session revocation implemented and activeC6/H1Resolved
Input sanitization applied to all text fieldsH4Resolved
Notification IDs validated (max 100, format check)M5Resolved
Settings: currency/language validated against whitelistsM6Resolved

Remaining items:

FindingIDTypePlan
CSP: unsafe-inline/unsafe-eval required by Next.jsM1MediumNonce-based CSP in Phase 3
Proxy HOSTNAME configM2MediumResolve in Phase 2 AWS config

7.9. Reporting Format

9.1 Individual Finding

Finding ID: VULN-{YEAR}-{SEQUENCE}
Title: {SHORT_DESCRIPTION}
Severity: Critical / High / Medium / Low
CVSS Score: {SCORE} (v3.1)

Description:
{DETAILED_DESCRIPTION}

Affected Endpoint / File:
- {ENDPOINT_OR_FILE}: {URL_OR_LINE_NUMBER}

Proof of Concept:
{STEPS_TO_REPRODUCE}

Impact:
{WHAT_AN_ATTACKER_CAN_DO}

GDPR/AML Implications:
{IF_PERSONAL_DATA_OR_FINANCIAL_DATA_AFFECTED}

Remediation:
{SPECIFIC_FIX}

Owner: {ASSIGNED_ENGINEER}
SLA Due Date: {DATE}
Status: Open / In Progress / Resolved / Accepted Risk

10. Metrics & KPIs

Metric Target Reporting Frequency
Critical findings resolved within SLA 100% Monthly
High findings resolved within SLA 95%100% Monthly
Vitest security test pass rate100% (blocking)Every PR
MTTR — Critical < 24 hours Per incident
MTTR — High < 7 days Monthly
%Open deploymentsHigh+ with passing security gatefindings 100%0 at launch Monthly
VitestAnnual securitypenetration test pass ratecompleted 100%Yes (before Phase 3) Every deployment
Open High+ findings (backlog)0MonthlyAnnual
npm audit Critical CVEs 0 in production Weekly
Penetration test — Critical findings closed100% within 30 daysPer testContinuous

11. Bug Bounty Program

Security metrics tracking:Status: GitHubPlanned Issues(Phase with3 security labelpost-launch) QuarterlyPlatform: Intigriti or HackerOne

Responsible disclosure (interim — before bug bounty): Report security report: Publishedvulnerabilities to CEO[email protected].

and
    engineering
  • Acknowledgment: team

    within 1 business day
  • Triage: within 5 business days
  • Safe harbor: researchers acting in good faith are protected from legal action

Approval

Role Name Date Signature
Author ComplianceSecurity Architect 2026-02-23
CTOCISO
Engineering Lead
DPOCTO
Management