api security

Implementing API Security Testing with 42Crunch

Implement comprehensive API security testing using the 42Crunch platform to perform static audit and dynamic conformance scanning of OpenAPI specifications.

42crunchapi-auditapi-scanapi-securityci-cd-securityconformance-testingopenapiowasp-api-top-10
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

42Crunch is an API security platform that combines Shift-Left security testing with Shield-Right runtime protection. It provides API Audit for static security analysis of OpenAPI definitions, API Conformance Scan for dynamic vulnerability detection, and API Protect for real-time threat prevention. The platform integrates into CI/CD pipelines and IDEs to identify OWASP API Security Top 10 vulnerabilities before and after deployment.

When to Use

  • When deploying or configuring implementing api security testing with 42crunch capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • 42Crunch platform account (free tier available for evaluation)
  • OpenAPI Specification (OAS) v2.0, v3.0, or v3.1 definitions for target APIs
  • IDE with 42Crunch extension (VS Code, IntelliJ, or Eclipse)
  • CI/CD pipeline (Jenkins, GitHub Actions, Azure DevOps, or GitLab CI)
  • Running API instance for dynamic scanning (conformance scan)
  • Node.js or Python environment for CLI tooling

Core Concepts

API Audit (Static Analysis)

API Audit performs static security analysis of OpenAPI definitions without requiring a running API. It evaluates the specification against 300+ security checks organized into categories:

Security Score Categories:

  • Data Validation: Schema definitions, parameter constraints, response validation
  • Authentication: Security scheme definitions, scope requirements
  • Transport Security: Server URL schemes, TLS requirements
  • Error Handling: Error response definitions, information leakage prevention

Running API Audit via VS Code Extension:

  1. Install the 42Crunch extension from the VS Code marketplace
  2. Open an OpenAPI specification file (YAML or JSON)
  3. Click the security audit icon in the editor toolbar
  4. Review the security score (0-100) and individual findings
  5. Address issues using the inline remediation guidance

Example OpenAPI Definition with Security Controls:

openapi: 3.0.3
info:
  title: Secure User API
  version: 1.0.0
servers:
  - url: https://api.example.com/v1
    description: Production server (HTTPS only)
security:
  - BearerAuth: []
paths:
  /users/{userId}:
    get:
      operationId: getUserById
      summary: Retrieve user by ID
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
            pattern: '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'
            maxLength: 36
      responses:
        '200':
          description: User details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Unauthorized
        '404':
          description: User not found
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    User:
      type: object
      required:
        - id
        - email
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        email:
          type: string
          format: email
          maxLength: 254
        name:
          type: string
          maxLength: 100
          pattern: '^[a-zA-Z\s\-]+$'
      additionalProperties: false
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string
          maxLength: 256
      additionalProperties: false

API Conformance Scan (Dynamic Testing)

The conformance scan dynamically tests a running API against its OpenAPI contract to detect runtime vulnerabilities including OWASP API Security Top 10 issues:

Scan v2 Configuration:

# 42c-conf.yaml
version: "2.0"
scan:
  target:
    url: https://api.example.com/v1
  authentication:
    - type: bearer
      token: "${API_TOKEN}"
      in: header
      name: Authorization
  settings:
    maxScanTime: 3600
    requestsPerSecond: 10
    followRedirects: false
  tests:
    owasp:
      - bola
      - bfla
      - injection
      - ssrf
      - massAssignment
      - excessiveDataExposure

Running Conformance Scan via CLI:

# Install the 42Crunch CLI
npm install -g @42crunch/cicd-cli
 
# Run conformance scan
42crunch-cli scan \
  --api-definition ./openapi.yaml \
  --target-url https://api.example.com/v1 \
  --token $CRUNCH_TOKEN \
  --min-score 70 \
  --report-format sarif \
  --output scan-report.sarif

CI/CD Pipeline Integration

GitHub Actions Integration:

name: API Security Testing
on:
  push:
    paths:
      - 'api/**'
      - 'openapi/**'
jobs:
  api-security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: 42Crunch API Audit
        uses: 42Crunch/api-security-audit-action@v3
        with:
          api-token: ${{ secrets.CRUNCH_API_TOKEN }}
          collection-name: "my-api-collection"
          min-score: 75
          upload-to-code-scanning: true
 
      - name: 42Crunch Conformance Scan
        if: github.ref == 'refs/heads/main'
        uses: 42Crunch/api-conformance-scan@v1
        with:
          api-token: ${{ secrets.CRUNCH_API_TOKEN }}
          target-url: ${{ secrets.STAGING_API_URL }}
          scan-config: ./42c-conf.yaml

Jenkins Pipeline Integration:

pipeline {
    agent any
    stages {
        stage('API Security Audit') {
            steps {
                script {
                    def auditResult = sh(
                        script: '''
                            42crunch-cli audit \
                              --api-definition openapi.yaml \
                              --token ${CRUNCH_TOKEN} \
                              --min-score 75 \
                              --report-format json \
                              --output audit-report.json
                        ''',
                        returnStatus: true
                    )
                    if (auditResult != 0) {
                        error("API Security Audit failed - score below threshold")
                    }
                }
            }
        }
        stage('Conformance Scan') {
            when { branch 'main' }
            steps {
                sh '''
                    42crunch-cli scan \
                      --api-definition openapi.yaml \
                      --target-url ${STAGING_URL} \
                      --token ${CRUNCH_TOKEN} \
                      --scan-config 42c-conf.yaml
                '''
            }
        }
    }
    post {
        always {
            archiveArtifacts artifacts: '*-report.*'
            publishHTML([
                reportDir: '.',
                reportFiles: 'audit-report.html',
                reportName: 'API Security Report'
            ])
        }
    }
}

API Protect (Runtime Protection)

API Protect deploys as a micro-gateway in front of API endpoints to enforce the OpenAPI contract at runtime:

# api-protect-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: api-protect-config
data:
  protection-config.json: |
    {
      "apiDefinition": "/config/openapi.yaml",
      "enforcement": {
        "validateRequests": true,
        "validateResponses": true,
        "blockOnFailure": true,
        "logLevel": "warn"
      },
      "rateLimit": {
        "enabled": true,
        "requestsPerMinute": 100,
        "burstSize": 20
      },
      "allowlist": {
        "contentTypes": ["application/json"],
        "methods": ["GET", "POST", "PUT", "DELETE"]
      }
    }

Remediation Workflow

When 42Crunch identifies issues, follow this remediation process:

  1. Triage: Review findings sorted by severity (Critical, High, Medium, Low)
  2. Analyze: Understand the specific security control missing from the OpenAPI definition
  3. Fix: Apply the recommended changes to the specification
  4. Validate: Re-run audit to confirm the score improvement
  5. Deploy: Push the updated specification through the CI/CD pipeline

Common Audit Findings and Fixes:

Finding Severity Fix
No authentication defined Critical Add securitySchemes and security requirements
Missing input validation High Add type, format, pattern, maxLength constraints
Server URL uses HTTP High Change server URLs to HTTPS
No error responses defined Medium Add 4xx and 5xx response definitions
additionalProperties not restricted Medium Set additionalProperties: false on object schemas
Missing rate limiting Medium Add x-rateLimit extension or use API Protect

Key Security Checks

42Crunch evaluates APIs against these critical security areas:

  • BOLA Prevention: Validates that object-level authorization patterns are defined
  • BFLA Prevention: Checks for function-level access control definitions
  • Injection Prevention: Ensures input parameters have proper type/format/pattern constraints
  • Data Exposure: Verifies response schemas limit returned properties
  • Security Misconfiguration: Checks authentication schemes, transport security, CORS settings
  • Mass Assignment: Validates that request bodies use explicit property allowlists

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md1.5 KB

API Reference: Implementing API Security Testing with 42Crunch

42Crunch API Security Audit

# Upload OpenAPI spec for audit
curl -X POST https://platform.42crunch.com/api/v2/apis \
  -H "X-API-KEY: $CRUNCH_KEY" \
  -F "specfile=@openapi.yaml"
 
# Get audit report
curl https://platform.42crunch.com/api/v2/apis/{api_id}/assessmentreport \
  -H "X-API-KEY: $CRUNCH_KEY"

OWASP API Security Top 10 (2023)

ID Risk Audit Check
API1 Broken Object Level Auth BOLA path patterns
API2 Broken Authentication Security schemes
API3 Broken Object Property Auth Mass assignment
API4 Unrestricted Resource Consumption Rate limits
API5 Broken Function Level Auth Admin endpoints
API8 Security Misconfiguration HTTP, CORS, headers

Security Score Deductions

Issue Deduction Severity
No security schemes -30 CRITICAL
Security disabled on endpoint -25 CRITICAL
No global security -20 HIGH
HTTP server URL -15 HIGH
No input schema -15 HIGH
Mass assignment risk -10 MEDIUM
Unbounded string param -5 MEDIUM

CI/CD Integration (GitHub Actions)

- uses: 42Crunch/api-security-audit-action@v3
  with:
    api-token: ${{ secrets.CRUNCH_TOKEN }}
    min-score: 70

References

Scripts 1

agent.py5.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for API security testing using 42Crunch audit methodology."""

import json
import argparse
from datetime import datetime

try:
    import yaml
except ImportError:
    yaml = None


OWASP_API_CHECKS = {
    "API1:2023": {"name": "Broken Object Level Authorization", "check": "bola"},
    "API2:2023": {"name": "Broken Authentication", "check": "auth"},
    "API3:2023": {"name": "Broken Object Property Level Authorization", "check": "bopla"},
    "API4:2023": {"name": "Unrestricted Resource Consumption", "check": "resource"},
    "API5:2023": {"name": "Broken Function Level Authorization", "check": "bfla"},
    "API6:2023": {"name": "Unrestricted Access to Sensitive Business Flows", "check": "flow"},
    "API7:2023": {"name": "Server-Side Request Forgery", "check": "ssrf"},
    "API8:2023": {"name": "Security Misconfiguration", "check": "config"},
    "API9:2023": {"name": "Improper Inventory Management", "check": "inventory"},
    "API10:2023": {"name": "Unsafe Consumption of APIs", "check": "consumption"},
}


def load_spec(spec_path):
    """Load OpenAPI spec."""
    with open(spec_path) as f:
        if spec_path.endswith((".yaml", ".yml")):
            return yaml.safe_load(f)
        return json.load(f)


def audit_spec_security(spec):
    """Perform static security audit of OpenAPI specification."""
    findings = []
    security_schemes = spec.get("components", {}).get("securitySchemes", {})
    global_security = spec.get("security", [])
    if not security_schemes:
        findings.append({
            "owasp": "API2:2023", "issue": "no_security_schemes",
            "severity": "CRITICAL", "score_deduction": 30,
        })
    if not global_security:
        findings.append({
            "owasp": "API8:2023", "issue": "no_global_security",
            "severity": "HIGH", "score_deduction": 20,
        })
    paths = spec.get("paths", {})
    for path, methods in paths.items():
        for method, details in methods.items():
            if method not in ("get", "post", "put", "patch", "delete"):
                continue
            if details.get("security") == []:
                findings.append({
                    "path": path, "method": method.upper(),
                    "owasp": "API2:2023", "issue": "security_disabled",
                    "severity": "CRITICAL", "score_deduction": 25,
                })
            if method in ("post", "put", "patch"):
                body = details.get("requestBody", {})
                content = body.get("content", {})
                for media, media_def in content.items():
                    schema = media_def.get("schema", {})
                    if not schema:
                        findings.append({
                            "path": path, "method": method.upper(),
                            "owasp": "API3:2023", "issue": "no_input_schema",
                            "severity": "HIGH", "score_deduction": 15,
                        })
                    if schema.get("additionalProperties") is not False:
                        findings.append({
                            "path": path, "method": method.upper(),
                            "owasp": "API3:2023", "issue": "mass_assignment_risk",
                            "severity": "MEDIUM", "score_deduction": 10,
                        })
            for param in details.get("parameters", []):
                p_schema = param.get("schema", {})
                if p_schema.get("type") == "string" and not p_schema.get("maxLength"):
                    findings.append({
                        "path": path, "method": method.upper(),
                        "parameter": param.get("name"),
                        "owasp": "API4:2023", "issue": "unbounded_string",
                        "severity": "MEDIUM", "score_deduction": 5,
                    })
            responses = details.get("responses", {})
            if "429" not in responses:
                findings.append({
                    "path": path, "method": method.upper(),
                    "owasp": "API4:2023", "issue": "no_429_response",
                    "severity": "MEDIUM", "score_deduction": 5,
                })
    servers = spec.get("servers", [])
    for server in servers:
        url = server.get("url", "")
        if url.startswith("http://"):
            findings.append({
                "server": url, "owasp": "API8:2023",
                "issue": "http_not_https", "severity": "HIGH", "score_deduction": 15,
            })
    return findings


def calculate_security_score(findings):
    """Calculate security score (0-100) based on findings."""
    total_deduction = sum(f.get("score_deduction", 0) for f in findings)
    score = max(0, 100 - total_deduction)
    if score >= 80:
        grade = "A"
    elif score >= 60:
        grade = "B"
    elif score >= 40:
        grade = "C"
    else:
        grade = "F"
    return {"score": score, "grade": grade, "total_findings": len(findings)}


def main():
    parser = argparse.ArgumentParser(description="42Crunch-Style API Security Testing Agent")
    parser.add_argument("--spec", required=True, help="OpenAPI spec file")
    parser.add_argument("--output", default="api_security_test_report.json")
    args = parser.parse_args()

    spec = load_spec(args.spec)
    report = {"generated_at": datetime.utcnow().isoformat()}

    findings = audit_spec_security(spec)
    score = calculate_security_score(findings)
    report["security_score"] = score
    report["findings"] = findings
    report["owasp_coverage"] = {k: v["name"] for k, v in OWASP_API_CHECKS.items()}

    print(f"[+] Security Score: {score['score']}/100 (Grade: {score['grade']})")
    print(f"[+] Findings: {len(findings)}")

    with open(args.output, "w") as f:
        json.dump(report, f, indent=2, default=str)
    print(f"[+] Report saved to {args.output}")


if __name__ == "__main__":
    main()
Keep exploring