Skip to content

OpenAPI Generator Security — Securing Generated Code and API Specs in CI/CD

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about OpenAPI Generator Security. We cover key concepts, practical examples, and best practices to help you master this topic.

OpenAPI Generator security covers securing your API specifications, validating specs for security vulnerabilities, hardening generated code against common attacks, and ensuring secure code generation in CI/CD pipelines.

What You'll Learn

  • Securing OpenAPI spec storage and access
  • Security schema validation in generated code
  • Hardening generated clients and servers
  • Spec injection and supply chain attacks
  • Secure CI/CD pipelines for code generation

Why It Matters

Generated code inherits vulnerabilities from the spec. An insecure spec produces insecure code. DodaTech's security scanning pipeline validates every API spec for OWASP API Security Top 10 issues before generation, preventing thousands of potential vulnerabilities from reaching production code.

Real-World Use

A team generates server stubs from an OpenAPI spec. The spec defines a POST /execute endpoint that takes raw shell commands as a string parameter. Security validation detects this before generation and blocks the pipeline, preventing remote code execution in the generated server.

flowchart LR
    A["OpenAPI Spec"] --> B["Security Validator"]
    B --> C{"Security checks pass?"}
    C -->|"No"| D["Block pipeline"]
    C -->|"Yes"| E["Secure Generator"]
    E --> F["Generated Code"]
    F --> G["Security Hardening"]
    G --> H["Input validation"]
    G --> I["Output encoding"]
    G --> J["Rate limiting"]
    G --> K["Auth enforcement"]
    H --> L["Deploy"]

Code Examples

Example 1: Spec Security Validation

import json
import re
from pathlib import Path

class SpecSecurityValidator:
    def __init__(self, spec_path):
        with open(spec_path) as f:
            self.spec = json.load(f)

    def validate(self):
        """Run all security checks on the spec."""
        issues = []
        issues.extend(self._check_missing_auth())
        issues.extend(self._check_injection_prone_params())
        issues.extend(self._check_unbounded_arrays())
        issues.extend(self._check_clear_text_schemes())
        issues.extend(self._check_excessive_scope())
        return issues

    def _check_missing_auth(self):
        """Find endpoints without authentication."""
        issues = []
        paths = self.spec.get('paths', {})
        security_global = self.spec.get('security', [])

        for path, methods in paths.items():
            for method, operation in methods.items():
                # Check per-operation security
                op_security = operation.get('security', security_global)
                if not op_security or op_security == [{}]:
                    issues.append({
                        'severity': 'HIGH',
                        'path': f"{method.upper()} {path}",
                        'issue': 'No authentication defined',
                        'fix': 'Add security requirement or global security'
                    })
        return issues

    def _check_injection_prone_params(self):
        """Find parameters vulnerable to injection."""
        issues = []
        for path, methods in self.spec.get('paths', {}).items():
            for method, operation in methods.items():
                params = operation.get('parameters', [])
                for param in params:
                    name = param.get('name', '')
                    schema = param.get('schema', {})
                    if any(kw in name.lower() for kw in
                           ['command', 'exec', 'eval', 'query', 'sql']):
                        issues.append({
                            'severity': 'CRITICAL',
                            'path': f"{method.upper()} {path}",
                            'param': name,
                            'issue': 'Parameter name suggests injection risk',
                            'fix': 'Add pattern validation or use enum'
                        })
        return issues

    def _check_excessive_scope(self):
        """Check for overly permissive security scopes."""
        issues = []
        for path, methods in self.spec.get('paths', {}).items():
            for method, operation in methods.items():
                security = operation.get('security', [])
                for sec_req in security:
                    for scheme, scopes in sec_req.items():
                        if 'admin' in scopes and method.upper() == 'GET':
                            issues.append({
                                'severity': 'MEDIUM',
                                'path': f"{method.upper()} {path}",
                                'issue': f"Read operation uses 'admin' scope",
                                'fix': 'Use more granular read scope'
                            })
        return issues

# Validate spec
validator = SpecSecurityValidator('openapi.yaml')
issues = validator.validate()
for issue in issues:
    print(f"[{issue['severity']}] {issue['path']}: {issue['issue']}")

Example 2: Input Validation in Generated Code

# Custom template addition for Python client input validation

from pydantic import BaseModel, validator, Field
from typing import Optional, List
import re

class CreateThreatRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=255)
    severity: str = Field(...)
    indicator_type: str = Field(...)
    indicator_value: str = Field(...)
    description: Optional[str] = Field(None, max_length=5000)

    @validator('severity')
    def validate_severity(cls, v):
        allowed = ['low', 'medium', 'high', 'critical']
        if v.lower() not in allowed:
            raise ValueError(f'Severity must be one of: {allowed}')
        return v.lower()

    @validator('indicator_value')
    def validate_indicator(cls, v, values):
        indicator_type = values.get('indicator_type', '')

        if indicator_type == 'IP':
            if not re.match(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', v):
                raise ValueError('Invalid IP address format')
        elif indicator_type == 'DOMAIN':
            if not re.match(r'^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$', v):
                raise ValueError('Invalid domain format')
        elif indicator_type == 'HASH':
            if not re.match(r'^[a-fA-F0-9]{32,128}$', v):
                raise ValueError('Invalid hash format')

        return v

    @validator('description')
    def sanitize_description(cls, v):
        if v:
            # Strip HTML/script tags
            v = re.sub(r'<[^>]*>', '', v)
            return v.strip()
        return v

Example 3: Secure CI/CD Pipeline

#!/usr/bin/env python3
"""
Secure CI/CD pipeline for OpenAPI generation.
"""
import subprocess
import hashlib
import json
from pathlib import Path

def verify_spec_integrity(spec_path, checksum_file):
    """Verify spec hasn't been tampered with."""
    current_hash = hashlib.sha256(Path(spec_path).read_bytes()).hexdigest()
    expected_hash = Path(checksum_file).read_text().strip()

    if current_hash != expected_hash:
        raise Exception(f"Spec integrity check failed for {spec_path}")
    print(f"Integrity check passed for {spec_path}")

def validate_spec_security(spec_path):
    """Run security validation on spec."""
    validator = SpecSecurityValidator(spec_path)
    issues = validator.validate()

    critical = [i for i in issues if i['severity'] == 'CRITICAL']
    high = [i for i in issues if i['severity'] == 'HIGH']

    if critical:
        raise Exception(
            f"CRITICAL security issues found: {len(critical)}. "
            "Pipeline blocked."
        )

    if high:
        print(f"WARNING: {len(high)} high-severity issues found")
        # May want to block here depending on policy

    print(f"Security validation passed: {len(issues)} issues found")

def scan_generated_code(output_dir):
    """Scan generated code for secrets and vulnerabilities."""
    # Check for hardcoded secrets
    result = subprocess.run([
        'gitleaks', 'detect',
        '--source', output_dir,
        '--no-git',
        '-v'
    ], capture_output=True, text=True)

    if result.returncode != 0:
        print("WARNING: Secrets detected in generated code:")
        print(result.stdout)

    # Check for vulnerable dependencies
    subprocess.run([
        'safety', 'check',
        '-r', f'{output_dir}/requirements.txt'
    ])

    # Run static analysis
    subprocess.run([
        'bandit', '-r', output_dir,
        '-ll'  # Only high confidence issues
    ])

def generate_securely(spec_path, generator, output_dir):
    """Generate code with security checks."""
    # Step 1: Verify integrity
    verify_spec_integrity(spec_path, 'spec.checksum')

    # Step 2: Validate spec security
    validate_spec_security(spec_path)

    # Step 3: Generate code
    subprocess.run([
        'openapi-generator-cli', 'generate',
        '-i', spec_path,
        '-g', generator,
        '-o', output_dir,
        '--additional-properties=performSecurityValidation=true'
    ], check=True)

    # Step 4: Scan generated code
    scan_generated_code(output_dir)

    print(f"Secure generation completed for {generator}")

# Run pipeline
generate_securely('openapi.yaml', 'python', '/tmp/secure-sdk')

Common Mistakes

1. Storing Specs in Public Repositories

API specs reveal your entire attack surface. Store them in private repositories with access control.

2. Not Validating Spec Security Before Generation

Specs with security issues produce code with security issues. Validate before generating.

3. Generated Code Without Input Validation

Generated code often trusts API parameters. Add validation layers for production use.

4. Ignoring OAuth2 Security Schemes

The spec's securitySchemes must be correctly referenced. Missing auth produces unprotected endpoints.

5. No Dependency Scanning of Generated Code

Generated code uses libraries that may have vulnerabilities. Scan dependencies in the pipeline.

Practice Questions

  1. What security validation should run before code generation?
  2. How do you protect API specs from unauthorized access?
  3. What vulnerabilities can specs introduce into generated code?
  4. How do you add input validation to generated code?
  5. What should a secure generation CI/CD pipeline include?

Answers:

  1. Check for missing auth, injection-prone parameters, unbounded arrays, and excessive scopes.
  2. Use private Git repos, access control lists, encryption at rest, and signed commits.
  3. SQL injection (via unbounded string params), authentication bypass (missing security), and privilege escalation (excessive scopes).
  4. Override templates to include validation decorators, or add post-generation hooks that insert validation logic.
  5. Spec integrity verification, security validation, dependency scanning, Static Analysis, and secret detection.

Challenge: Build a secure CI/CD pipeline that validates an OpenAPI spec for the OWASP API Security Top 10 issues, generates code only if validation passes, scans generated code for vulnerabilities, and rejects the pipeline on critical findings.

FAQ

Can OpenAPI Generator produce secure code by default?

: It produces functionally correct code, but security hardening (input validation, Rate Limiting, output encoding) requires customization.

How do I handle API keys in generated clients?

: Never hardcode. Use environment variables or a secrets manager. Generated clients should accept credentials at runtime.

What is a spec injection attack?

: An attacker with write access to the spec file can inject malicious parameters or schemas that produce vulnerable code.

Should I validate generated code in CI?

: Yes. Run SAST tools, dependency scanners, and secret detectors on generated code before deployment.

How do I version API specs securely?

: Use signed Git tags and checksums. Verify spec integrity before generation.

What's Next

Apply security practices to your {{< ilink "OpenAPI" "CI/CD Code Generation with OpenAPI Generator" }} pipeline, and review {{< ilink "OpenAPI" "OpenAPI Generator Testing" }} for contract-based Security Testing.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro