# Security Testing Guide This comprehensive guide covers security testing methodologies, tools, and procedures for ensuring the security of Trilium's codebase and deployments. ## Security Testing Overview ### Testing Pyramid for Security ``` Manual Security Testing (Penetration Testing, Code Review) ┌─────────────────────────────┐ │ │ │ Integration Security │ │ (API, E2E Tests) │ └─────────────────────────────┘ ┌─────────────────────────────────┐ │ │ │ Unit Security Tests │ │ (Input Validation, Crypto) │ └─────────────────────────────────────┘ ┌─────────────────────────────────────────┐ │ │ │ Static Analysis │ │ (SAST, Dependency Scanning) │ └─────────────────────────────────────────────┘ ``` ### Security Testing Goals 1. **Vulnerability Detection**: Identify security flaws before deployment 2. **Compliance Verification**: Ensure adherence to security standards 3. **Risk Assessment**: Evaluate potential security impact 4. **Defense Validation**: Verify security controls effectiveness ## Static Analysis Security Testing (SAST) ### Code Quality and Security Analysis #### ESLint Security Rules ```json { "extends": [ "plugin:security/recommended", "plugin:@typescript-eslint/recommended" ], "rules": { "security/detect-sql-injection": "error", "security/detect-xss": "error", "security/detect-eval-with-expression": "error", "security/detect-non-literal-fs-filename": "warn", "security/detect-unsafe-regex": "error", "security/detect-buffer-noassert": "error", "security/detect-child-process": "warn", "security/detect-disable-mustache-escape": "error", "security/detect-no-csrf-before-method-override": "error", "security/detect-non-literal-require": "warn", "security/detect-possible-timing-attacks": "error", "security/detect-pseudoRandomBytes": "error" } } ``` #### SonarQube Security Rules ```javascript // Example sonar-project.properties configuration sonar.projectKey=trilium-security sonar.sources=src sonar.exclusions=**/*.test.ts,**/*.spec.ts,**/node_modules/** sonar.typescript.tsconfigPath=tsconfig.json // Security-focused quality gates sonar.qualitygate.wait=true sonar.security.hotspots.maxAllowed=0 sonar.security.vulnerabilities.maxAllowed=0 ``` #### Custom Security Linting Rules ```typescript // Custom ESLint rule for Trilium-specific security patterns module.exports = { meta: { type: "problem", docs: { description: "Detect unencrypted storage of sensitive data" } }, create(context) { return { CallExpression(node) { if (node.callee.name === 'setOption' && node.arguments[0].value.includes('password')) { context.report({ node, message: "Potential unencrypted password storage" }); } } }; } }; ``` ### Dependency Vulnerability Scanning #### npm audit Integration ```bash #!/bin/bash # security-scan.sh - Comprehensive dependency scanning echo "Running npm audit..." npm audit --audit-level moderate echo "Checking for known vulnerabilities..." npm audit --json > audit-report.json echo "Analyzing audit results..." node scripts/analyze-audit.js audit-report.json echo "Checking for outdated packages..." npm outdated echo "Running Snyk scan..." npx snyk test --json > snyk-report.json echo "Generating security report..." node scripts/generate-security-report.js ``` #### Automated Vulnerability Monitoring ```typescript // scripts/analyze-audit.js interface VulnerabilityReport { advisories: Record; } function analyzeAuditReport(report: VulnerabilityReport): void { const criticalVulns = Object.values(report.advisories) .filter(vuln => vuln.severity === 'critical'); if (criticalVulns.length > 0) { console.error(`Found ${criticalVulns.length} critical vulnerabilities`); process.exit(1); } const highVulns = Object.values(report.advisories) .filter(vuln => vuln.severity === 'high'); if (highVulns.length > 5) { console.warn(`Found ${highVulns.length} high severity vulnerabilities`); } } ``` ## Dynamic Application Security Testing (DAST) ### Automated Security Scanning #### OWASP ZAP Integration ```yaml # .github/workflows/security-scan.yml name: Security Scan on: pull_request: branches: [ main ] schedule: - cron: '0 2 * * 1' # Weekly scan jobs: security-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Start application run: npm start & - name: Wait for application run: sleep 30 - name: Run OWASP ZAP scan uses: zaproxy/action-full-scan@v0.4.0 with: target: 'http://localhost:8080' rules_file_name: '.zap/rules.tsv' cmd_options: '-a' - name: Upload ZAP results uses: actions/upload-artifact@v3 with: name: zap-report path: report_html.html ``` #### Custom Security Test Suite ```typescript // test/security/security.test.ts import request from 'supertest'; import app from '../../src/app'; describe('Security Tests', () => { describe('XSS Protection', () => { test('should sanitize script tags in note content', async () => { const maliciousContent = 'Hello'; const response = await request(app) .post('/api/notes') .send({ title: 'Test Note', content: maliciousContent }) .expect(200); expect(response.body.content).not.toContain('', 'Save and view the note', 'Check if script executes', 'Verify content is properly sanitized' ], expectedResult: 'Script should not execute, content should be sanitized', risk: 'medium' } ]; ``` #### Security Checklist ```typescript interface SecurityChecklist { item: string; status: 'pass' | 'fail' | 'not_applicable'; notes?: string; } const securityChecklist: SecurityChecklist[] = [ { item: 'HTTPS enforced in production', status: 'pass' }, { item: 'Security headers properly configured', status: 'pass' }, { item: 'Input validation on all endpoints', status: 'pass' }, { item: 'SQL injection protection implemented', status: 'pass' }, { item: 'XSS protection mechanisms active', status: 'pass' }, { item: 'CSRF protection enabled', status: 'pass' }, { item: 'Strong password policy enforced', status: 'pass' }, { item: 'MFA available and working', status: 'pass' }, { item: 'Session management secure', status: 'pass' }, { item: 'Rate limiting implemented', status: 'pass' }, { item: 'Error messages dont leak information', status: 'pass' }, { item: 'File upload restrictions in place', status: 'pass' }, { item: 'Sensitive data encrypted at rest', status: 'pass' }, { item: 'Audit logging comprehensive', status: 'pass' }, { item: 'Dependencies up to date', status: 'pass' } ]; ``` ## Security Test Automation ### CI/CD Security Pipeline ```yaml # .github/workflows/security-pipeline.yml name: Security Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: static-analysis: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Run ESLint security rules run: npm run lint:security - name: Run dependency vulnerability scan run: npm audit --audit-level moderate - name: Run Snyk scan uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high unit-security-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Run security unit tests run: npm run test:security - name: Generate coverage report run: npm run coverage:security integration-security-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Start test database run: npm run db:test - name: Run integration security tests run: npm run test:security:integration - name: Cleanup run: npm run db:cleanup dynamic-security-scan: runs-on: ubuntu-latest needs: [static-analysis, unit-security-tests] steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install dependencies run: npm ci - name: Start application run: | npm run build npm start & sleep 30 - name: Run OWASP ZAP scan uses: zaproxy/action-full-scan@v0.4.0 with: target: 'http://localhost:8080' - name: Upload security reports uses: actions/upload-artifact@v3 with: name: security-reports path: | report_html.html report_json.json ``` ### Security Metrics and Reporting ```typescript // scripts/security-metrics.ts interface SecurityMetrics { vulnerabilities: { critical: number; high: number; medium: number; low: number; }; testCoverage: { securityTests: number; totalTests: number; percentage: number; }; dependencies: { total: number; outdated: number; vulnerable: number; }; scanResults: { lastScan: Date; passed: boolean; findings: number; }; } function generateSecurityReport(metrics: SecurityMetrics): void { const report = ` # Security Report - ${new Date().toISOString()} ## Vulnerability Summary - Critical: ${metrics.vulnerabilities.critical} - High: ${metrics.vulnerabilities.high} - Medium: ${metrics.vulnerabilities.medium} - Low: ${metrics.vulnerabilities.low} ## Test Coverage - Security Tests: ${metrics.testCoverage.securityTests} - Total Tests: ${metrics.testCoverage.totalTests} - Coverage: ${metrics.testCoverage.percentage}% ## Dependencies - Total Dependencies: ${metrics.dependencies.total} - Outdated: ${metrics.dependencies.outdated} - Vulnerable: ${metrics.dependencies.vulnerable} ## Last Security Scan - Date: ${metrics.scanResults.lastScan} - Status: ${metrics.scanResults.passed ? 'PASSED' : 'FAILED'} - Findings: ${metrics.scanResults.findings} `; console.log(report); // Fail build if critical issues found if (metrics.vulnerabilities.critical > 0) { process.exit(1); } } ``` This comprehensive security testing guide ensures that Trilium maintains a robust security posture through automated and manual testing procedures. Regular execution of these tests helps identify and remediate security issues before they can be exploited.