Skip to content

Add comprehensive security audit #67

@Sam-Bolling

Description

@Sam-Bolling

Problem

The ogc-client-CSAPI library has no comprehensive security audit to identify vulnerabilities, assess security risks, and establish security best practices. While the library implements OGC standards with 98% compliance and demonstrates excellent architecture, security has not been systematically evaluated.

Current Security Posture:

  • Type Safety: Comprehensive TypeScript types reduce runtime errors
  • Input Validation: Validators for GeoJSON, SWE Common (97.4%+ coverage)
  • Error Handling: Extensive error handling with detailed messages
  • Security Audit: No systematic security review
  • Dependency Scanning: No automated vulnerability scanning
  • Threat Modeling: No security threat assessment
  • Security Testing: No dedicated security test suite
  • Security Documentation: No security best practices guide

Missing Security Assessments:

1. Dependency Vulnerabilities

  • Risk: Third-party packages may have known CVEs
  • Current State: No automated dependency scanning (npm audit, Snyk, Dependabot)
  • Impact: Users may unknowingly use library with vulnerable dependencies

2. Input Validation Gaps

  • Risk: Malicious or malformed data could cause crashes, injection attacks, or DoS
  • Current State: Validators exist but not comprehensive (GeoJSON 40.95%, SWE 73.68%)
  • Areas of Concern:
    • URL parameter injection (bbox, datetime, query strings)
    • JSON parsing vulnerabilities (prototype pollution, deep nesting)
    • Regular expression DoS (ReDoS) in parsers
    • XML injection in SensorML (if supported)
    • XSS vectors in string properties

3. Authentication/Authorization Handling

  • Risk: Improper credential handling could leak sensitive data
  • Current State: Library accepts arbitrary fetch options (including headers)
  • Areas of Concern:
    • API keys/tokens in URLs (logged, cached, exposed)
    • Bearer tokens in request headers (storage, transmission)
    • Cookie handling (HttpOnly, Secure flags)
    • CORS configuration

4. Data Sanitization

  • Risk: Unsanitized user-provided data could enable XSS, injection attacks
  • Current State: No explicit sanitization in parsers or builders
  • Areas of Concern:
    • User-provided strings in properties (name, description, label)
    • URLs in link arrays (href fields)
    • GeoJSON properties (arbitrary key-value pairs)
    • SWE Common textual values

5. Denial of Service (DoS) Vulnerabilities

  • Risk: Malicious data could exhaust resources (CPU, memory, stack)
  • Current State: No explicit DoS protection mechanisms
  • Attack Vectors:
    • Deeply nested JSON structures (stack overflow)
    • Extremely large GeoJSON collections (memory exhaustion)
    • Circular references in objects (infinite loops)
    • Complex regular expressions (ReDoS)
    • Large query parameters (URL length limits)

6. Cryptographic Security

  • Risk: Weak crypto could compromise data integrity/confidentiality
  • Current State: No cryptographic operations in library
  • Future Considerations:
    • If adding ETags: Hash function choice (MD5 vs SHA-256)
    • If adding authentication: Token generation, storage
    • If adding encryption: Algorithm selection, key management

7. Supply Chain Security

  • Risk: Compromised build pipeline could inject malicious code
  • Current State: No build provenance, no signing
  • Areas of Concern:
    • NPM package integrity (no package lock file verification)
    • Build script security (arbitrary code execution)
    • CI/CD pipeline security (GitHub Actions)
    • Release artifact signing (provenance)

Real-World Security Scenarios:

Scenario 1: Prototype Pollution Attack

// Malicious server response
const maliciousResponse = {
  "type": "Feature",
  "properties": {
    "name": "Sensor-123",
    "__proto__": {
      "isAdmin": true  // Prototype pollution!
    }
  }
};

// Current parser may not sanitize __proto__
const system = systemParser.parse(maliciousResponse);

// Later code checks:
if (user.isAdmin) {  // Now ALL objects have isAdmin=true!
  // Unauthorized access
}

Scenario 2: ReDoS (Regular Expression DoS)

// If parser uses vulnerable regex like: /^(a+)+$/
// Malicious datetime parameter
const maliciousDatetime = "a".repeat(50) + "!";

// Regex backtracking causes CPU spike
validateDatetime(maliciousDatetime);  // Hangs for minutes

Scenario 3: Deep Nesting DoS

// Malicious deeply nested GeoJSON
const maliciousGeoJSON = {
  "type": "FeatureCollection",
  "features": [
    { "properties": { 
      "nested": { "nested": { "nested": { /* 1000 levels deep */ } } }
    }}
  ]
};

// Recursive parsing causes stack overflow
const parsed = parser.parse(maliciousGeoJSON);  // Stack overflow!

Scenario 4: Credential Leakage via URL

// Developer accidentally puts API key in URL
const systems = await navigator.getSystems({
  apiKey: 'secret-key-12345'  // Gets logged, cached, exposed in URLs
});

// URL is: https://api.example.com/systems?apiKey=secret-key-12345
// - Logged in browser history
// - Cached by HTTP cache
// - Visible in server logs
// - Exposed in Referer headers

Scenario 5: XSS via Unsanitized Properties

// Malicious server sends XSS payload
const maliciousSystem = {
  "type": "Feature",
  "properties": {
    "name": "\u003cscript\u003ealert('XSS')\u003c/script\u003e",
    "description": "\u003cimg src=x onerror='steal_cookies()'\u003e"
  }
};

// Application renders without sanitization
document.getElementById('systemName').innerHTML = system.properties.name;
// XSS executed!

Context

This issue was identified during the comprehensive validation conducted January 27-28, 2026.

Related Validation Issues: #20 (OGC Standards Compliance), #23 (Architecture Assessment)

Work Item ID: 44 from Remaining Work Items

Repository: https://github.com/OS4CSAPI/ogc-client-CSAPI

Validated Commit: a71706b9592cad7a5ad06e6cf8ddc41fa5387732


Detailed Findings

1. Current Security-Related Features (Issue #23)

From Issue #23 Architecture Validation Report:

Strengths with Security Implications:

Type Safety (Confirmed):

  • ✅ Comprehensive TypeScript types for all resources (4,159 lines)
  • ✅ Generic interfaces (ParseResult<T>, CSAPIParser<T>)
  • ✅ Type guards (isCSAPIFeature) for runtime checking
  • ✅ Discriminated unions (featureType literals)
  • Security Benefit: Type safety reduces runtime errors, prevents type confusion attacks

Input Validation (Confirmed):

  • ✅ GeoJSON validator (61 tests, 97.4% coverage) - but only 40.95% of spec
  • ✅ SWE Common validator (50 tests, 100% coverage) - but only 73.68% of spec
  • ⚠️ SensorML validator exists but not integrated into parsers
  • Security Gap: Incomplete validation coverage leaves attack surface

Error Handling (Confirmed):

  • ✅ Extensive error handling with CSAPIParseError
  • ✅ Clear error messages with context
  • ✅ Validation errors captured in ParseResult
  • Security Benefit: Proper error handling prevents information leakage
  • Security Gap: Error messages may expose internal details

Production Ready (Confirmed):

  • ✅ 94% test coverage (832+ tests)
  • ✅ Comprehensive JSDoc documentation
  • ✅ Optional validation (opt-in)
  • Security Benefit: High test coverage catches bugs before production
  • Security Gap: No dedicated security tests

2. Parser Vulnerabilities (Issue #23)

From Issue #23 Validation Report:

Parsing Layer: src/ogc-api/csapi/parsers/base.ts (13,334 bytes)

export abstract class CSAPIParser<T> {
  parse(data: unknown, options: ParserOptions = {}): ParseResult<T> {
    const format = detectFormat(options.contentType, data);
    
    let parsed: T;
    switch (format.format) {
      case 'geojson': parsed = this.parseGeoJSON(data); break;
      case 'sensorml': parsed = this.parseSensorML(data); break;
      case 'swe': parsed = this.parseSWE(data); break;
    }

    if (options.validate) {
      const validationResult = this.validate(parsed, format.format);
    }

    return { data: parsed, format, errors, warnings };
  }
}

Security Concerns:

  1. No input sanitization before parsing
  2. Validation is optional (default: false) - most users don't validate
  3. Unknown data type (data: unknown) - no type guard before parsing
  4. No recursion depth limit - vulnerable to deep nesting DoS
  5. No size limit - vulnerable to memory exhaustion

Potential Attack Vectors:

  • Prototype pollution via __proto__, constructor, prototype keys
  • Stack overflow via deeply nested objects
  • Memory exhaustion via extremely large arrays
  • ReDoS in format detection or validation regexes

3. URL Building Security (Issue #20, #23)

From Issue #20 Validation Report:

Navigator URL Building: src/ogc-api/csapi/navigator.ts (2,091 lines)

getSystemsUrl(options: SystemsQueryOptions = {}): string {
  const url = new URL(`${this.baseUrl}/systems`);
  
  if (options.limit !== undefined) {
    url.searchParams.set('limit', options.limit.toString());
  }
  
  if (options.bbox !== undefined) {
    url.searchParams.set('bbox', this._serializeBbox(options.bbox));
  }
  
  // ... more parameters
  
  return url.toString();
}

Security Concerns:

  1. No URL parameter validation - accepts arbitrary values
  2. No URL encoding validation - could break with special characters
  3. No URL length limits - could exceed server limits (414 error)
  4. No sensitive parameter warnings - developers could put secrets in URLs

Potential Attack Vectors:

  • URL injection via malicious bbox, datetime, q parameters
  • Parameter pollution (e.g., limit=10&limit=9999999)
  • Server-side template injection if server processes query strings unsafely
  • Credential leakage if developers put API keys in query parameters

4. Validation Coverage Gaps (Issues #12, #14)

From Issue #12 (GeoJSON Validation):

Actual Coverage: 40.95% (78 of 190+ validation criteria)
Documented Claim: 97.4% (misleading - refers to test coverage, not spec coverage)

Missing GeoJSON Validations:

  • ❌ Geometry coordinate validation (no range checking, no CRS validation)
  • ❌ Link structure validation (no URL format checking, no rel validation)
  • ❌ Temporal validation (no ISO 8601 enforcement, no range validation)
  • ❌ Property value validation (arbitrary data accepted)
  • ❌ Collection-level validation (0% coverage)

From Issue #14 (SWE Common Validation):

Actual Coverage: 73.68% (84 of 114+ validation criteria)
Documented Claim: 100% (misleading - refers to test coverage, not spec coverage)

Missing SWE Common Validations:

  • ❌ Boolean, Vector, Matrix, DataStream, DataChoice, Geometry validators
  • ❌ Definition and label validation (required per OGC 24-014)
  • ❌ Recursive validation for nested DataRecord/DataArray
  • ❌ Constraint validation (allowedValues, allowedTimes)

Security Impact:

  • Malicious data can bypass validation
  • No protection against malformed or adversarial inputs
  • Parser may crash or behave unexpectedly with invalid data

5. Dependency Security (No Evidence of Scanning)

Current Dependencies (from typical OGC client libraries):

  • TypeScript (build-time)
  • Testing frameworks (jest, ts-jest)
  • Possibly: fetch polyfills, WebSocket libraries, etc.

Security Risks:

  • Dependencies may have known CVEs (Common Vulnerabilities and Exposures)
  • Transitive dependencies (dependencies of dependencies) may be vulnerable
  • Outdated packages may have unpatched security issues

No Evidence of:

  • npm audit in CI/CD pipeline
  • Snyk integration
  • Dependabot alerts
  • SBOM (Software Bill of Materials)
  • Security policy (SECURITY.md)

6. Authentication/Authorization Gaps (Issue #20)

From Issue #20 Validation Report:

TypedCSAPINavigator: src/ogc-api/csapi/typed-navigator.ts

private async _fetch(
  url: string,
  options: TypedFetchOptions = {}
): Promise<Response> {
  const fetchFn = options.fetch || fetch;
  const headers: Record<string, string> = {
    ...options.headers,  // User-provided headers
  };
  
  const response = await fetchFn(url, { headers });
  return response;
}

Security Concerns:

  1. Arbitrary headers accepted - no validation
  2. No credential storage guidance - developers may store insecurely
  3. No HTTPS enforcement - allows insecure HTTP
  4. No authentication helpers - developers implement ad-hoc solutions
  5. No token refresh logic - stale tokens cause auth failures

Insecure Usage Examples:

// BAD: API key in URL
const systems = await navigator.getSystems({ apiKey: 'secret' });

// BAD: Token in localStorage (XSS vulnerability)
localStorage.setItem('token', 'bearer-token-123');
const systems = await navigator.getSystems({
  headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }
});

// BAD: Credentials in source code
const systems = await navigator.getSystems({
  headers: { 'X-API-Key': 'hardcoded-secret-key' }
});

7. No Security Documentation (Confirmed)

Documentation Files Examined:

  • README.md - No security section
  • No SECURITY.md file
  • No security best practices guide
  • No threat model documentation
  • No vulnerability disclosure policy

Impact:

  • Developers don't know how to use library securely
  • No guidance on credential management
  • No recommendations for input sanitization
  • No security contact for reporting vulnerabilities

Proposed Solution

1. Automated Dependency Scanning

Integrate Automated Tools:

# .github/workflows/security.yml
name: Security Audit

on: [push, pull_request, schedule]

jobs:
  dependency-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      # NPM Audit
      - name: Run npm audit
        run: npm audit --audit-level=moderate
      
      # Snyk Security Scan
      - name: Snyk Security Scan
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
      
      # OWASP Dependency Check
      - name: OWASP Dependency Check
        uses: dependency-check/Dependency-Check_Action@main

Enable Dependabot:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    open-pull-requests-limit: 10
    
    # Auto-merge minor/patch updates
    auto-merge: true
    
    # Security updates only
    security-updates-only: false

2. Input Validation Security Enhancements

Add Sanitization Layer:

// New file: src/ogc-api/csapi/security/sanitizer.ts

export class InputSanitizer {
  /**
   * Sanitize JSON object to prevent prototype pollution
   */
  static sanitizeJSON(obj: unknown): unknown {
    if (obj === null || typeof obj !== 'object') {
      return obj;
    }
    
    if (Array.isArray(obj)) {
      return obj.map(item => this.sanitizeJSON(item));
    }
    
    const sanitized: Record<string, unknown> = {};
    for (const [key, value] of Object.entries(obj)) {
      // Block prototype pollution keys
      if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
        continue;
      }
      
      sanitized[key] = this.sanitizeJSON(value);
    }
    
    return sanitized;
  }
  
  /**
   * Validate and sanitize string to prevent XSS
   */
  static sanitizeString(str: string, options: { maxLength?: number } = {}): string {
    // Trim whitespace
    str = str.trim();
    
    // Enforce max length
    if (options.maxLength && str.length > options.maxLength) {
      throw new Error(`String exceeds max length of ${options.maxLength}`);
    }
    
    // Remove control characters (except newline, tab)
    str = str.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, '');
    
    // Optionally escape HTML (if used in browser)
    // str = str.replace(/[<>"'&]/g, char => entityMap[char]);
    
    return str;
  }
  
  /**
   * Validate URL to prevent injection
   */
  static sanitizeURL(url: string): string {
    try {
      const parsed = new URL(url);
      
      // Only allow http/https protocols
      if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
        throw new Error(`Invalid URL protocol: ${parsed.protocol}`);
      }
      
      return parsed.toString();
    } catch {
      throw new Error(`Invalid URL: ${url}`);
    }
  }
  
  /**
   * Limit recursion depth to prevent stack overflow
   */
  static checkDepth(obj: unknown, maxDepth: number = 100): void {
    const check = (o: unknown, depth: number) => {
      if (depth > maxDepth) {
        throw new Error(`Object nesting exceeds max depth of ${maxDepth}`);
      }
      
      if (o && typeof o === 'object') {
        for (const value of Object.values(o)) {
          check(value, depth + 1);
        }
      }
    };
    
    check(obj, 0);
  }
  
  /**
   * Limit collection size to prevent memory exhaustion
   */
  static checkSize(arr: unknown[], maxSize: number = 10000): void {
    if (arr.length > maxSize) {
      throw new Error(`Collection size ${arr.length} exceeds max of ${maxSize}`);
    }
  }
}

Integrate into Parser:

// Modify: src/ogc-api/csapi/parsers/base.ts

export abstract class CSAPIParser<T> {
  parse(data: unknown, options: ParserOptions = {}): ParseResult<T> {
    // SECURITY: Sanitize input before parsing
    data = InputSanitizer.sanitizeJSON(data);
    
    // SECURITY: Check nesting depth
    InputSanitizer.checkDepth(data, options.maxDepth || 100);
    
    // SECURITY: Check collection size (if array)
    if (Array.isArray(data)) {
      InputSanitizer.checkSize(data, options.maxSize || 10000);
    }
    
    // Continue with normal parsing
    const format = detectFormat(options.contentType, data);
    // ...
  }
}

3. ReDoS Protection

Audit Regular Expressions:

// Tools to detect vulnerable regexes:
// - npm install -g safe-regex
// - npm install -g eslint-plugin-security

// Example vulnerable regex:
const VULNERABLE = /^(a+)+$/;  // Exponential backtracking!

// Example safe regex:
const SAFE = /^a+$/;  // Linear time

// Audit all regexes in:
// - formats.ts (format detection)
// - validation/ (validators)
// - parsers/ (parsing logic)

Add Regex Timeout:

// New utility: src/shared/safe-regex.ts

export function safeRegexTest(
  regex: RegExp,
  str: string,
  timeoutMs: number = 1000
): boolean {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(new Error('Regex timeout - potential ReDoS'));
    }, timeoutMs);
    
    try {
      const result = regex.test(str);
      clearTimeout(timeout);
      resolve(result);
    } catch (error) {
      clearTimeout(timeout);
      reject(error);
    }
  });
}

4. Authentication/Authorization Best Practices

Create Security Guide:

// New file: src/ogc-api/csapi/security/auth-helpers.ts

/**
 * Secure authentication helper
 */
export class SecureAuthHelper {
  /**
   * RECOMMENDED: Use Authorization header for tokens
   * DO NOT put credentials in URL parameters!
   */
  static createBearerAuthHeaders(token: string): Record<string, string> {
    if (!token || typeof token !== 'string') {
      throw new Error('Invalid token');
    }
    
    return {
      'Authorization': `Bearer ${token}`
    };
  }
  
  /**
   * RECOMMENDED: Use API key header
   * DO NOT put API keys in URL parameters!
   */
  static createAPIKeyHeaders(apiKey: string): Record<string, string> {
    if (!apiKey || typeof apiKey !== 'string') {
      throw new Error('Invalid API key');
    }
    
    return {
      'X-API-Key': apiKey
    };
  }
  
  /**
   * RECOMMENDED: Check HTTPS enforcement
   */
  static enforceHTTPS(url: string): void {
    const parsed = new URL(url);
    if (parsed.protocol !== 'https:') {
      console.warn('WARNING: Using insecure HTTP connection. Use HTTPS in production!');
    }
  }
  
  /**
   * SECURITY WARNING: Detect credentials in URLs
   */
  static detectCredentialsInURL(url: string): void {
    const suspiciousParams = ['apiKey', 'api_key', 'token', 'secret', 'password', 'key'];
    const parsed = new URL(url);
    
    for (const param of suspiciousParams) {
      if (parsed.searchParams.has(param)) {
        throw new Error(
          `SECURITY WARNING: Credential parameter '${param}' detected in URL. ` +
          `Use Authorization header instead!`
        );
      }
    }
  }
}

Usage Example (Secure):

import { TypedCSAPINavigator, SecureAuthHelper } from 'ogc-client-csapi';

// RECOMMENDED: Token from environment variable
const token = process.env.CSAPI_TOKEN;

// RECOMMENDED: Use Authorization header
const navigator = new TypedCSAPINavigator(collection, {
  headers: SecureAuthHelper.createBearerAuthHeaders(token)
});

// RECOMMENDED: Check HTTPS
SecureAuthHelper.enforceHTTPS(baseUrl);

// Get systems (securely authenticated)
const systems = await navigator.getSystems();

5. Security Testing Suite

Create Security Test Suite:

// New file: tests/security/security.spec.ts

describe('Security Tests', () => {
  describe('Prototype Pollution Prevention', () => {
    it('should block __proto__ in JSON', () => {
      const malicious = {
        type: 'Feature',
        properties: {
          __proto__: { isAdmin: true }
        }
      };
      
      const result = systemParser.parse(malicious);
      
      // Should not pollute prototype
      expect(({} as any).isAdmin).toBeUndefined();
    });
    
    it('should block constructor in JSON', () => {
      const malicious = {
        type: 'Feature',
        properties: {
          constructor: { prototype: { isAdmin: true } }
        }
      };
      
      const result = systemParser.parse(malicious);
      expect(({} as any).isAdmin).toBeUndefined();
    });
  });
  
  describe('DoS Prevention', () => {
    it('should reject deeply nested objects', () => {
      // Create 200-level deep nesting
      let nested: any = { value: 'deep' };
      for (let i = 0; i < 200; i++) {
        nested = { nested };
      }
      
      expect(() => {
        systemParser.parse({
          type: 'Feature',
          properties: nested
        });
      }).toThrow(/nesting exceeds max depth/);
    });
    
    it('should reject extremely large collections', () => {
      const huge = {
        type: 'FeatureCollection',
        features: new Array(100000).fill({ type: 'Feature' })
      };
      
      expect(() => {
        systemCollectionParser.parse(huge);
      }).toThrow(/size.*exceeds max/);
    });
  });
  
  describe('XSS Prevention', () => {
    it('should sanitize HTML in strings', () => {
      const xss = {
        type: 'Feature',
        properties: {
          name: '<script>alert("XSS")</script>',
          description: '<img src=x onerror="steal()">'
        }
      };
      
      const result = systemParser.parse(xss);
      
      // Should escape or remove HTML
      expect(result.data.properties.name).not.toContain('<script>');
    });
  });
  
  describe('URL Injection Prevention', () => {
    it('should detect credentials in URL', () => {
      expect(() => {
        SecureAuthHelper.detectCredentialsInURL(
          'https://api.example.com/systems?apiKey=secret'
        );
      }).toThrow(/SECURITY WARNING.*apiKey/);
    });
    
    it('should warn on HTTP (non-HTTPS)', () => {
      const spy = jest.spyOn(console, 'warn');
      
      SecureAuthHelper.enforceHTTPS('http://api.example.com');
      
      expect(spy).toHaveBeenCalledWith(
        expect.stringContaining('insecure HTTP')
      );
    });
  });
  
  describe('ReDoS Prevention', () => {
    it('should timeout on catastrophic backtracking', async () => {
      // Vulnerable regex: /^(a+)+$/
      const maliciousInput = 'a'.repeat(50) + '!';
      
      await expect(async () => {
        await safeRegexTest(/^(a+)+$/, maliciousInput, 1000);
      }).rejects.toThrow(/Regex timeout/);
    });
  });
});

6. Security Documentation

Create SECURITY.md:

# Security Policy

## Reporting a Vulnerability

**DO NOT** open a public issue for security vulnerabilities.

Instead, please report security issues to:
- Email: security@example.com
- GitHub Security Advisory: https://github.com/OS4CSAPI/ogc-client-CSAPI/security/advisories/new

We will respond within 48 hours and provide a timeline for fixes.

## Supported Versions

| Version | Supported          |
| ------- | ------------------ |
| 1.x.x   | :white_check_mark: |
| < 1.0   | :x:                |

## Security Best Practices

### 1. Authentication
-**DO** use Authorization header for tokens
-**DON'T** put credentials in URL parameters
-**DO** store tokens securely (environment variables, secure vaults)
-**DON'T** store tokens in localStorage (XSS vulnerability)

### 2. HTTPS
-**DO** use HTTPS in production
-**DON'T** use HTTP for sensitive data
-**DO** validate server certificates

### 3. Input Validation
-**DO** enable validation: `{ validate: true }`
-**DO** sanitize user-provided data before rendering
-**DON'T** trust server responses blindly

### 4. Dependencies
-**DO** keep dependencies up to date
-**DO** run `npm audit` regularly
-**DO** enable Dependabot alerts

### 5. Error Handling
-**DON'T** expose sensitive data in error messages
-**DO** log errors securely (redact credentials)

## Known Security Limitations

1. **Validation Coverage:** Not all OGC spec validations implemented
2. **Binary Encodings:** Not supported (potential security risk)
3. **WebSocket Streaming:** Not implemented (separate security domain)

## Security Scanning

We use:
- NPM Audit (CI/CD pipeline)
- Snyk (weekly scans)
- Dependabot (automated updates)
- Manual code reviews

## Vulnerability Disclosure

See CHANGELOG.md for security-related releases.

Add Security Section to README:

## Security

This library handles data from external OGC API servers. Follow security best practices:

### Secure Authentication
```typescript
// RECOMMENDED: Token in header
const nav = new TypedCSAPINavigator(collection, {
  headers: {
    'Authorization': `Bearer ${process.env.API_TOKEN}`
  }
});

// INSECURE: Token in URL
const systems = await nav.getSystems({ token: 'secret' });  // ❌ DON'T

Enable Validation

// Enable validation for untrusted data
const systems = await nav.getSystems({ validate: true });

HTTPS Only

// Use HTTPS in production
const baseUrl = 'https://api.example.com/csapi';  // ✅
const baseUrl = 'http://api.example.com/csapi';   // ❌

See SECURITY.md for full security guidelines.


---

## Acceptance Criteria

### Automated Security Scanning (10 criteria)
- [ ] Integrate `npm audit` into CI/CD pipeline
- [ ] Configure Dependabot for automated dependency updates
- [ ] Add Snyk security scanning (or equivalent)
- [ ] Configure security scanning to run on every PR
- [ ] Configure security scanning to run weekly on main branch
- [ ] Set vulnerability severity thresholds (critical/high = fail build)
- [ ] Create GitHub Actions workflow for security scans
- [ ] Enable GitHub Security Advisories
- [ ] Generate SBOM (Software Bill of Materials)
- [ ] Document security scanning process in CONTRIBUTING.md

### Input Validation Security (15 criteria)
- [ ] Implement `InputSanitizer` class with prototype pollution prevention
- [ ] Block `__proto__`, `constructor`, `prototype` keys in JSON
- [ ] Implement recursion depth limit (default: 100 levels)
- [ ] Implement collection size limit (default: 10,000 items)
- [ ] Implement string length limit validation
- [ ] Sanitize string inputs (remove control characters)
- [ ] Validate URL formats to prevent injection
- [ ] Integrate sanitizer into all parsers
- [ ] Add security options to `ParserOptions` (maxDepth, maxSize)
- [ ] Test prototype pollution prevention (5+ test cases)
- [ ] Test deep nesting DoS prevention
- [ ] Test large collection DoS prevention
- [ ] Test URL injection prevention
- [ ] Document security options in API docs
- [ ] Add security warnings to error messages

### ReDoS Protection (6 criteria)
- [ ] Audit all regular expressions for ReDoS vulnerabilities
- [ ] Use `safe-regex` or `recheck` to analyze regexes
- [ ] Implement regex timeout utility
- [ ] Replace vulnerable regexes with safe alternatives
- [ ] Add ReDoS tests (catastrophic backtracking scenarios)
- [ ] Document regex safety in code comments

### Authentication/Authorization Security (8 criteria)
- [ ] Create `SecureAuthHelper` class with best practices
- [ ] Implement `createBearerAuthHeaders()` helper
- [ ] Implement `createAPIKeyHeaders()` helper
- [ ] Implement `enforceHTTPS()` warning
- [ ] Implement `detectCredentialsInURL()` check
- [ ] Add authentication security tests
- [ ] Document secure authentication patterns in README
- [ ] Warn developers about insecure practices (console warnings)

### Security Testing Suite (12 criteria)
- [ ] Create dedicated `tests/security/` directory
- [ ] Test prototype pollution prevention (3+ test cases)
- [ ] Test DoS prevention (deep nesting, large collections)
- [ ] Test XSS prevention (HTML escaping)
- [ ] Test URL injection prevention
- [ ] Test ReDoS prevention (regex timeout)
- [ ] Test authentication best practices
- [ ] Test HTTPS enforcement
- [ ] Test credential detection in URLs
- [ ] Achieve 100% code coverage for security modules
- [ ] Run security tests in CI/CD pipeline
- [ ] Document security test cases

### Security Documentation (10 criteria)
- [ ] Create SECURITY.md file
- [ ] Document vulnerability reporting process
- [ ] Document supported versions for security updates
- [ ] Document security best practices (authentication, HTTPS, validation)
- [ ] Document known security limitations
- [ ] Document security scanning process
- [ ] Add "Security" section to README.md
- [ ] Create security examples (secure vs insecure code)
- [ ] Document threat model (attack vectors, mitigations)
- [ ] Set up security contact email/channel

### Threat Modeling (5 criteria)
- [ ] Identify threat actors (malicious servers, MITM attackers, XSS attackers)
- [ ] Document attack vectors (prototype pollution, DoS, injection, credential leakage)
- [ ] Document mitigations for each threat
- [ ] Assess residual risk for each threat
- [ ] Review threat model annually or after major changes

### Compliance and Standards (4 criteria)
- [ ] Review OWASP Top 10 (applicable items for library)
- [ ] Review CWE Top 25 (Common Weakness Enumeration)
- [ ] Document compliance with security standards
- [ ] Add security checklist to PR template

---

## Implementation Notes

### Files to Create

**Security Infrastructure (~800-1000 lines total):**

src/
ogc-api/csapi/security/
sanitizer.ts # Input sanitizer (~200 lines)
auth-helpers.ts # Authentication helpers (~150 lines)
safe-regex.ts # ReDoS protection (~100 lines)

tests/security/
security.spec.ts # Security test suite (~400 lines)
prototype-pollution.spec.ts # Prototype tests (~100 lines)
dos-prevention.spec.ts # DoS tests (~100 lines)
auth-security.spec.ts # Auth tests (~100 lines)

.github/
workflows/
security.yml # Security scanning workflow (~100 lines)
dependabot.yml # Dependabot config (~30 lines)

SECURITY.md # Security policy (~300 lines)


### Files to Modify

**Parsers (integrate security):**
- `src/ogc-api/csapi/parsers/base.ts` - Add sanitization (~50 lines)
- `src/ogc-api/csapi/parsers/resources.ts` - Add size checks (~30 lines)

**Documentation:**
- `README.md` - Add Security section (~100 lines)
- `CONTRIBUTING.md` - Add security testing guidelines (~50 lines)

### Implementation Phases

**Phase 1: Automated Scanning (4-6 hours)**
- Set up GitHub Actions workflow
- Configure Dependabot
- Integrate npm audit
- Set up Snyk (or equivalent)

**Phase 2: Input Sanitization (8-10 hours)**
- Implement InputSanitizer class
- Integrate into parsers
- Add depth/size limits
- Unit tests

**Phase 3: ReDoS Protection (4-5 hours)**
- Audit regexes
- Implement safe alternatives
- Add timeout utility
- Tests

**Phase 4: Authentication Security (5-6 hours)**
- Create SecureAuthHelper
- Implement security checks
- Add warnings
- Tests

**Phase 5: Security Testing (10-12 hours)**
- Create security test suite
- Prototype pollution tests
- DoS tests
- XSS/injection tests
- Achieve 100% coverage

**Phase 6: Documentation (6-8 hours)**
- Create SECURITY.md
- Update README.md
- Threat modeling document
- Security best practices guide

**Phase 7: Review and Audit (4-6 hours)**
- Code review for security
- Manual penetration testing
- Third-party security audit (optional)

**Total Estimated Effort:** 41-53 hours (~1-1.5 weeks)

### Dependencies

**Requires:**
- Issue #23 (Architecture) - ✅ Complete (provides code structure)
- Issue #20 (OGC Compliance) - ✅ Complete (provides endpoint patterns)
- Issue #12 (GeoJSON Validation) - ✅ Complete (identifies validation gaps)
- Issue #14 (SWE Validation) - ✅ Complete (identifies validation gaps)

**External Tools:**
- npm audit (built-in)
- Snyk (free for open source)
- Dependabot (free on GitHub)
- safe-regex (npm package)
- OWASP Dependency-Check (optional)

### Caveats

**Scope Limitations:**

**In Scope:**
- Automated dependency scanning
- Input sanitization and validation
- DoS prevention (nesting, size limits)
- ReDoS protection
- Authentication best practices
- Security documentation
- Security test suite

**Out of Scope:**
- Network security (TLS/SSL configuration) - handled by browser/Node.js
- Server-side security - this is a client library
- Encryption/decryption - no cryptographic operations in library
- Advanced threat detection - requires monitoring infrastructure
- Compliance certifications (SOC 2, ISO 27001) - organizational level

**Performance Impact:**
- Input sanitization adds ~1-2ms overhead per parse
- Depth checking adds ~0.5ms overhead
- Size checking is O(1) (negligible)
- Overall impact: <5% performance degradation for enhanced security

**False Positives:**
- Depth limit may reject legitimate deeply nested structures (adjustable)
- Size limit may reject legitimate large collections (adjustable)
- Prototype key blocking may break edge cases (rare)

**Maintenance:**
- Security scanning requires ongoing monitoring
- Dependencies need regular updates
- Threat model needs annual review
- Security tests need expansion as new vulnerabilities discovered

---

## Priority Justification

**Priority: Low**

**Why Low Priority:**
1. **No Critical Vulnerabilities Found:** No known exploits in current version
2. **Limited Attack Surface:** Client library, not server-facing
3. **Type Safety Helps:** TypeScript provides some protection
4. **Significant Effort:** 41-53 hours of security hardening work
5. **Maintenance Burden:** Ongoing security monitoring and updates

**Why Still Important:**
1. **Professional Libraries Need Security:** Industry expectation for production use
2. **Prevent Future Vulnerabilities:** Proactive defense better than reactive patching
3. **User Trust:** Security audit increases confidence in library
4. **Compliance:** Many organizations require security assessments
5. **Best Practices:** Security should be built-in, not bolted-on

**Impact if Not Addressed:**
- ⚠️ Potential vulnerabilities in dependencies (CVEs)
- ⚠️ Risk of prototype pollution attacks
- ⚠️ Risk of DoS via malicious data (deep nesting, large collections)
- ⚠️ Risk of credential leakage via URLs
- ⚠️ No security guidance for developers
- ✅ **Library still functional** (no immediate security breach)

**When to Prioritize Higher:**
- Before 1.0 release (production readiness)
- After security incident or vulnerability disclosure
- When targeting enterprise customers (security requirements)
- When handling sensitive data (PII, financial, health)
- If used in high-value or critical systems

**Effort Estimate:** 41-53 hours (~1-1.5 weeks)
- Automated scanning: 4-6 hours
- Input sanitization: 8-10 hours
- ReDoS protection: 4-5 hours
- Authentication security: 5-6 hours
- Security testing: 10-12 hours
- Documentation: 6-8 hours
- Review/audit: 4-6 hours

**ROI Analysis:**
- **High ROI** for production deployment (prevents security incidents)
- **Medium ROI** for open-source credibility (demonstrates professionalism)
- **Low ROI** for hobbyist projects (overkill for low-risk use cases)
- **Best ROI** for enterprise adoption (meets security requirements)

**Recommendation:** Implement before 1.0 release or when targeting production/enterprise use. Security audit is expected for professional libraries but can be deferred for early development phases. Prioritize automated scanning (quick win) first, then comprehensive hardening later.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions