Initial commit
This commit is contained in:
708
skills/appsec/api-spectral/SKILL.md
Normal file
708
skills/appsec/api-spectral/SKILL.md
Normal file
@@ -0,0 +1,708 @@
|
||||
---
|
||||
name: api-spectral
|
||||
description: >
|
||||
API specification linting and security validation using Stoplight's Spectral with support for
|
||||
OpenAPI, AsyncAPI, and Arazzo specifications. Validates API definitions against security best
|
||||
practices, OWASP API Security Top 10, and custom organizational standards. Use when: (1) Validating
|
||||
OpenAPI/AsyncAPI specifications for security issues and design flaws, (2) Enforcing API design
|
||||
standards and governance policies across API portfolios, (3) Creating custom security rules for
|
||||
API specifications in CI/CD pipelines, (4) Detecting authentication, authorization, and data
|
||||
exposure issues in API definitions, (5) Ensuring API specifications comply with organizational
|
||||
security standards and regulatory requirements.
|
||||
version: 0.1.0
|
||||
maintainer: SirAppSec
|
||||
category: appsec
|
||||
tags: [api-security, openapi, asyncapi, linting, spectral, api-governance, owasp-api, specification-validation]
|
||||
frameworks: [OWASP]
|
||||
dependencies:
|
||||
tools: [node, npm]
|
||||
optional: [docker, git]
|
||||
references:
|
||||
- https://docs.stoplight.io/docs/spectral/674b27b261c3c-overview
|
||||
- https://github.com/stoplightio/spectral
|
||||
- https://owasp.org/API-Security/editions/2023/en/0x11-t10/
|
||||
---
|
||||
|
||||
# API Security with Spectral
|
||||
|
||||
## Overview
|
||||
|
||||
Spectral is a flexible JSON/YAML linter from Stoplight that validates API specifications against
|
||||
security best practices and organizational standards. With built-in rulesets for OpenAPI v2/v3.x,
|
||||
AsyncAPI v2.x, and Arazzo v1.0, Spectral helps identify security vulnerabilities, design flaws,
|
||||
and compliance issues during the API design phase—before code is written. Custom rulesets enable
|
||||
enforcement of OWASP API Security Top 10 patterns, authentication standards, and data protection
|
||||
requirements across your entire API portfolio.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Installation
|
||||
|
||||
```bash
|
||||
# Install via npm
|
||||
npm install -g @stoplight/spectral-cli
|
||||
|
||||
# Or using Yarn
|
||||
yarn global add @stoplight/spectral-cli
|
||||
|
||||
# Or using Docker
|
||||
docker pull stoplight/spectral
|
||||
|
||||
# Verify installation
|
||||
spectral --version
|
||||
```
|
||||
|
||||
### Basic API Specification Linting
|
||||
|
||||
```bash
|
||||
# Lint OpenAPI specification with built-in rules
|
||||
spectral lint openapi.yaml
|
||||
|
||||
# Lint with specific ruleset
|
||||
spectral lint openapi.yaml --ruleset .spectral.yaml
|
||||
|
||||
# Output as JSON for CI/CD integration
|
||||
spectral lint openapi.yaml --format json --output results.json
|
||||
```
|
||||
|
||||
### Quick Security Scan
|
||||
|
||||
```bash
|
||||
# Create security-focused ruleset
|
||||
echo 'extends: ["spectral:oas"]' > .spectral.yaml
|
||||
|
||||
# Lint API specification
|
||||
spectral lint api-spec.yaml --ruleset .spectral.yaml
|
||||
```
|
||||
|
||||
## Core Workflow
|
||||
|
||||
### Workflow Checklist
|
||||
|
||||
Progress:
|
||||
[ ] 1. Install Spectral and select appropriate base rulesets
|
||||
[ ] 2. Create or configure ruleset with security rules
|
||||
[ ] 3. Identify API specifications to validate (OpenAPI, AsyncAPI, Arazzo)
|
||||
[ ] 4. Run linting with appropriate severity thresholds
|
||||
[ ] 5. Review findings and categorize by security impact
|
||||
[ ] 6. Map findings to OWASP API Security Top 10
|
||||
[ ] 7. Create custom rules for organization-specific security patterns
|
||||
[ ] 8. Integrate into CI/CD pipeline with failure thresholds
|
||||
[ ] 9. Generate reports with remediation guidance
|
||||
[ ] 10. Establish continuous validation process
|
||||
|
||||
Work through each step systematically. Check off completed items.
|
||||
|
||||
### Step 1: Ruleset Configuration
|
||||
|
||||
Create a `.spectral.yaml` ruleset extending built-in security rules:
|
||||
|
||||
```yaml
|
||||
# .spectral.yaml - Basic security-focused ruleset
|
||||
extends: ["spectral:oas", "spectral:asyncapi"]
|
||||
|
||||
rules:
|
||||
# Enforce HTTPS for all API endpoints
|
||||
oas3-valid-schema-example: true
|
||||
oas3-server-not-example.com: true
|
||||
|
||||
# Authentication security
|
||||
operation-security-defined: error
|
||||
|
||||
# Information disclosure prevention
|
||||
info-contact: warn
|
||||
info-description: warn
|
||||
```
|
||||
|
||||
**Built-in Rulesets:**
|
||||
- `spectral:oas` - OpenAPI v2/v3.x security and best practices
|
||||
- `spectral:asyncapi` - AsyncAPI v2.x validation rules
|
||||
- `spectral:arazzo` - Arazzo v1.0 workflow specifications
|
||||
|
||||
**Ruleset Selection Best Practices:**
|
||||
- Start with built-in rulesets and progressively add custom rules
|
||||
- Use `error` severity for critical security issues (authentication, HTTPS)
|
||||
- Use `warn` for recommended practices and information disclosure risks
|
||||
- Use `info` for style guide compliance and documentation completeness
|
||||
|
||||
For advanced ruleset patterns, see `references/ruleset_patterns.md`.
|
||||
|
||||
### Step 2: Security-Focused API Linting
|
||||
|
||||
Run Spectral with security-specific validation:
|
||||
|
||||
```bash
|
||||
# Comprehensive security scan
|
||||
spectral lint openapi.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--format stylish \
|
||||
--verbose
|
||||
|
||||
# Focus on error-level findings only (critical security issues)
|
||||
spectral lint openapi.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--fail-severity error
|
||||
|
||||
# Scan multiple specifications
|
||||
spectral lint api-specs/*.yaml --ruleset .spectral.yaml
|
||||
|
||||
# Generate JSON report for further analysis
|
||||
spectral lint openapi.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--format json \
|
||||
--output security-findings.json
|
||||
```
|
||||
|
||||
**Output Formats:**
|
||||
- `stylish` - Human-readable terminal output (default)
|
||||
- `json` - Machine-readable JSON for CI/CD integration
|
||||
- `junit` - JUnit XML for test reporting platforms
|
||||
- `html` - HTML report (requires additional plugins)
|
||||
- `github-actions` - GitHub Actions annotations format
|
||||
|
||||
### Step 3: OWASP API Security Validation
|
||||
|
||||
Validate API specifications against OWASP API Security Top 10:
|
||||
|
||||
```yaml
|
||||
# .spectral-owasp.yaml - OWASP API Security focused rules
|
||||
extends: ["spectral:oas"]
|
||||
|
||||
rules:
|
||||
# API1:2023 - Broken Object Level Authorization
|
||||
operation-security-defined:
|
||||
severity: error
|
||||
message: "All operations must have security defined (OWASP API1)"
|
||||
|
||||
# API2:2023 - Broken Authentication
|
||||
security-schemes-defined:
|
||||
severity: error
|
||||
message: "API must define security schemes (OWASP API2)"
|
||||
|
||||
# API3:2023 - Broken Object Property Level Authorization
|
||||
no-additional-properties:
|
||||
severity: warn
|
||||
message: "Consider disabling additionalProperties to prevent data leakage (OWASP API3)"
|
||||
|
||||
# API5:2023 - Broken Function Level Authorization
|
||||
operation-tag-defined:
|
||||
severity: warn
|
||||
message: "Operations should be tagged for authorization policy mapping (OWASP API5)"
|
||||
|
||||
# API7:2023 - Server Side Request Forgery
|
||||
no-http-basic:
|
||||
severity: error
|
||||
message: "HTTP Basic auth transmits credentials in plain text (OWASP API7)"
|
||||
|
||||
# API8:2023 - Security Misconfiguration
|
||||
servers-use-https:
|
||||
description: All server URLs must use HTTPS
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^https://"
|
||||
message: "Server URL must use HTTPS (OWASP API8)"
|
||||
|
||||
# API9:2023 - Improper Inventory Management
|
||||
api-version-required:
|
||||
severity: error
|
||||
given: $.info
|
||||
then:
|
||||
field: version
|
||||
function: truthy
|
||||
message: "API version must be specified (OWASP API9)"
|
||||
```
|
||||
|
||||
**Run OWASP-focused validation:**
|
||||
```bash
|
||||
spectral lint openapi.yaml --ruleset .spectral-owasp.yaml
|
||||
```
|
||||
|
||||
For complete OWASP API Security Top 10 rule mappings, see `references/owasp_api_mappings.md`.
|
||||
|
||||
### Step 4: Custom Security Rule Development
|
||||
|
||||
Create organization-specific security rules using Spectral's rule engine:
|
||||
|
||||
```yaml
|
||||
# .spectral-custom.yaml
|
||||
extends: ["spectral:oas"]
|
||||
|
||||
rules:
|
||||
# Require API key authentication
|
||||
require-api-key-auth:
|
||||
description: All APIs must support API key authentication
|
||||
severity: error
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
field: type
|
||||
function: enumeration
|
||||
functionOptions:
|
||||
values: [apiKey, oauth2, openIdConnect]
|
||||
message: "API must define apiKey, OAuth2, or OpenID Connect security"
|
||||
|
||||
# Prevent PII in query parameters
|
||||
no-pii-in-query:
|
||||
description: Prevent PII exposure in URL query parameters
|
||||
severity: error
|
||||
given: $.paths[*][*].parameters[?(@.in == 'query')].name
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "(ssn|social.?security|credit.?card|password|secret|token)"
|
||||
message: "Query parameters must not contain PII identifiers"
|
||||
|
||||
# Require rate limiting headers
|
||||
require-rate-limit-headers:
|
||||
description: API responses should include rate limit headers
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[*].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
X-RateLimit-Limit: true
|
||||
X-RateLimit-Remaining: true
|
||||
message: "Consider adding rate limit headers for security"
|
||||
|
||||
# Enforce consistent error responses
|
||||
error-response-format:
|
||||
description: Error responses must follow standard format
|
||||
severity: error
|
||||
given: $.paths[*][*].responses[?(@property >= 400)].content.application/json.schema
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
required: [error, message]
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
message: "Error responses must include 'error' and 'message' fields"
|
||||
```
|
||||
|
||||
**Custom Rule Development Resources:**
|
||||
- `references/custom_rules_guide.md` - Complete rule authoring guide with functions
|
||||
- `references/custom_functions.md` - Creating custom JavaScript/TypeScript functions
|
||||
- `assets/rule-templates/` - Reusable rule templates for common security patterns
|
||||
|
||||
### Step 5: CI/CD Pipeline Integration
|
||||
|
||||
Integrate Spectral into continuous integration workflows:
|
||||
|
||||
**GitHub Actions:**
|
||||
```yaml
|
||||
# .github/workflows/api-security-lint.yml
|
||||
name: API Security Linting
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
spectral:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
- name: Install Spectral
|
||||
run: npm install -g @stoplight/spectral-cli
|
||||
|
||||
- name: Lint API Specifications
|
||||
run: |
|
||||
spectral lint api-specs/*.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--format github-actions \
|
||||
--fail-severity error
|
||||
|
||||
- name: Generate Report
|
||||
if: always()
|
||||
run: |
|
||||
spectral lint api-specs/*.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--format json \
|
||||
--output spectral-report.json
|
||||
|
||||
- name: Upload Report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: spectral-security-report
|
||||
path: spectral-report.json
|
||||
```
|
||||
|
||||
**GitLab CI:**
|
||||
```yaml
|
||||
# .gitlab-ci.yml
|
||||
api-security-lint:
|
||||
stage: test
|
||||
image: node:18
|
||||
script:
|
||||
- npm install -g @stoplight/spectral-cli
|
||||
- spectral lint api-specs/*.yaml --ruleset .spectral.yaml --fail-severity error
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit: spectral-report.xml
|
||||
```
|
||||
|
||||
**Docker-Based Pipeline:**
|
||||
```bash
|
||||
# Run in CI/CD with Docker
|
||||
docker run --rm \
|
||||
-v $(pwd):/work \
|
||||
stoplight/spectral lint /work/openapi.yaml \
|
||||
--ruleset /work/.spectral.yaml \
|
||||
--format json \
|
||||
--output /work/results.json
|
||||
|
||||
# Fail build on critical security issues
|
||||
if jq -e '.[] | select(.severity == 0)' results.json > /dev/null; then
|
||||
echo "Critical security issues detected!"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
For complete CI/CD integration examples, see `scripts/ci_integration_examples/`.
|
||||
|
||||
### Step 6: Results Analysis and Remediation
|
||||
|
||||
Analyze findings and provide security remediation:
|
||||
|
||||
```bash
|
||||
# Parse Spectral JSON output for security report
|
||||
python3 scripts/parse_spectral_results.py \
|
||||
--input spectral-report.json \
|
||||
--output security-report.html \
|
||||
--map-owasp \
|
||||
--severity-threshold error
|
||||
|
||||
# Generate remediation guidance
|
||||
python3 scripts/generate_remediation.py \
|
||||
--input spectral-report.json \
|
||||
--output remediation-guide.md
|
||||
```
|
||||
|
||||
**Validation Workflow:**
|
||||
1. Review all error-level findings (critical security issues)
|
||||
2. Verify each finding in API specification context
|
||||
3. Map findings to OWASP API Security Top 10 categories
|
||||
4. Prioritize by severity and exploitability
|
||||
5. Apply fixes to API specifications
|
||||
6. Re-lint to verify remediation
|
||||
7. Document security decisions and exceptions
|
||||
|
||||
**Feedback Loop Pattern:**
|
||||
```bash
|
||||
# 1. Initial lint
|
||||
spectral lint openapi.yaml --ruleset .spectral.yaml -o scan1.json
|
||||
|
||||
# 2. Apply security fixes to API specification
|
||||
|
||||
# 3. Re-lint to verify fixes
|
||||
spectral lint openapi.yaml --ruleset .spectral.yaml -o scan2.json
|
||||
|
||||
# 4. Compare results
|
||||
python3 scripts/compare_spectral_results.py scan1.json scan2.json
|
||||
```
|
||||
|
||||
## Advanced Patterns
|
||||
|
||||
### Pattern 1: Multi-Specification Governance
|
||||
|
||||
Enforce consistent security standards across API portfolio:
|
||||
|
||||
```bash
|
||||
# Scan all API specifications with organization ruleset
|
||||
find api-specs/ -name "*.yaml" -o -name "*.json" | while read spec; do
|
||||
echo "Linting: $spec"
|
||||
spectral lint "$spec" \
|
||||
--ruleset .spectral-org-standards.yaml \
|
||||
--format json \
|
||||
--output "reports/$(basename $spec .yaml)-report.json"
|
||||
done
|
||||
|
||||
# Aggregate findings across portfolio
|
||||
python3 scripts/aggregate_api_findings.py \
|
||||
--input-dir reports/ \
|
||||
--output portfolio-security-report.html
|
||||
```
|
||||
|
||||
### Pattern 2: Progressive Severity Enforcement
|
||||
|
||||
Start with warnings and progressively enforce stricter rules:
|
||||
|
||||
```yaml
|
||||
# .spectral-phase1.yaml - Initial rollout (warnings only)
|
||||
extends: ["spectral:oas"]
|
||||
rules:
|
||||
servers-use-https: warn
|
||||
operation-security-defined: warn
|
||||
|
||||
# .spectral-phase2.yaml - Enforcement phase (errors)
|
||||
extends: ["spectral:oas"]
|
||||
rules:
|
||||
servers-use-https: error
|
||||
operation-security-defined: error
|
||||
```
|
||||
|
||||
```bash
|
||||
# Phase 1: Awareness (don't fail builds)
|
||||
spectral lint openapi.yaml --ruleset .spectral-phase1.yaml
|
||||
|
||||
# Phase 2: Enforcement (fail on violations)
|
||||
spectral lint openapi.yaml --ruleset .spectral-phase2.yaml --fail-severity error
|
||||
```
|
||||
|
||||
### Pattern 3: API Security Pre-Commit Validation
|
||||
|
||||
Prevent insecure API specifications from being committed:
|
||||
|
||||
```bash
|
||||
# .git/hooks/pre-commit
|
||||
#!/bin/bash
|
||||
|
||||
# Find staged API specification files
|
||||
SPECS=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(yaml|yml|json)$' | grep -E '(openapi|swagger|api)')
|
||||
|
||||
if [ -n "$SPECS" ]; then
|
||||
echo "Validating API specifications..."
|
||||
for spec in $SPECS; do
|
||||
spectral lint "$spec" --ruleset .spectral.yaml --fail-severity error
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Security validation failed for $spec"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
```
|
||||
|
||||
### Pattern 4: Automated Security Review Comments
|
||||
|
||||
Generate security review comments for pull requests:
|
||||
|
||||
```bash
|
||||
# Generate PR review comments from Spectral findings
|
||||
spectral lint openapi.yaml \
|
||||
--ruleset .spectral.yaml \
|
||||
--format json | \
|
||||
python3 scripts/generate_pr_comments.py \
|
||||
--file openapi.yaml \
|
||||
--severity error,warn \
|
||||
--output pr-comments.json
|
||||
|
||||
# Post to GitHub PR via gh CLI
|
||||
gh pr comment $PR_NUMBER --body-file pr-comments.json
|
||||
```
|
||||
|
||||
## Custom Functions for Advanced Security Rules
|
||||
|
||||
Create custom JavaScript functions for complex security validation:
|
||||
|
||||
```javascript
|
||||
// spectral-functions/check-jwt-expiry.js
|
||||
export default (targetVal, opts) => {
|
||||
// Validate JWT security scheme includes expiration
|
||||
if (targetVal.type === 'http' && targetVal.scheme === 'bearer') {
|
||||
if (!targetVal.bearerFormat || targetVal.bearerFormat !== 'JWT') {
|
||||
return [{
|
||||
message: 'Bearer authentication should specify JWT format'
|
||||
}];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
```
|
||||
|
||||
```yaml
|
||||
# .spectral.yaml with custom function
|
||||
functions:
|
||||
- check-jwt-expiry
|
||||
functionsDir: ./spectral-functions
|
||||
|
||||
rules:
|
||||
jwt-security-check:
|
||||
description: Validate JWT security configuration
|
||||
severity: error
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
function: check-jwt-expiry
|
||||
```
|
||||
|
||||
For complete custom function development guide, see `references/custom_functions.md`.
|
||||
|
||||
## Automation & Continuous Validation
|
||||
|
||||
### Scheduled API Security Scanning
|
||||
|
||||
```bash
|
||||
# Automated daily API specification scanning
|
||||
./scripts/spectral_scheduler.sh \
|
||||
--schedule daily \
|
||||
--specs-dir api-specs/ \
|
||||
--ruleset .spectral-owasp.yaml \
|
||||
--output-dir scan-results/ \
|
||||
--alert-on error \
|
||||
--slack-webhook $SLACK_WEBHOOK
|
||||
```
|
||||
|
||||
### API Specification Monitoring
|
||||
|
||||
```bash
|
||||
# Monitor API specifications for security regressions
|
||||
./scripts/spectral_monitor.sh \
|
||||
--baseline baseline-scan.json \
|
||||
--current-scan latest-scan.json \
|
||||
--alert-on-new-findings \
|
||||
--email security-team@example.com
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Specification Security**: API specifications may contain sensitive information (internal URLs, authentication schemes) - control access and sanitize before sharing
|
||||
- **Rule Integrity**: Protect ruleset files from unauthorized modification - store in version control with code review requirements
|
||||
- **False Positives**: Manually review findings before making security claims - context matters for API design decisions
|
||||
- **Specification Versioning**: Maintain version history of API specifications to track security improvements over time
|
||||
- **Secrets in Specs**: Never include actual credentials, API keys, or secrets in example values - use placeholder values only
|
||||
- **Compliance Mapping**: Document how Spectral rules map to compliance requirements (PCI-DSS, GDPR, HIPAA)
|
||||
- **Governance Enforcement**: Define exception process for legitimate rule violations with security team approval
|
||||
- **Audit Logging**: Log all Spectral scans, findings, and remediation actions for security auditing
|
||||
- **Access Control**: Restrict modification of security rulesets to designated API security team members
|
||||
- **Continuous Validation**: Re-validate API specifications whenever they change or when new security rules are added
|
||||
|
||||
## Bundled Resources
|
||||
|
||||
### Scripts (`scripts/`)
|
||||
|
||||
- `parse_spectral_results.py` - Parse Spectral JSON output and generate security reports with OWASP mapping
|
||||
- `generate_remediation.py` - Generate remediation guidance based on Spectral findings
|
||||
- `compare_spectral_results.py` - Compare two Spectral scans to track remediation progress
|
||||
- `aggregate_api_findings.py` - Aggregate findings across multiple API specifications
|
||||
- `spectral_ci.sh` - CI/CD integration wrapper with exit code handling
|
||||
- `spectral_scheduler.sh` - Scheduled scanning with alerting
|
||||
- `spectral_monitor.sh` - Continuous monitoring with baseline comparison
|
||||
- `generate_pr_comments.py` - Convert Spectral findings to PR review comments
|
||||
|
||||
### References (`references/`)
|
||||
|
||||
- `owasp_api_mappings.md` - Complete OWASP API Security Top 10 rule mappings
|
||||
- `custom_rules_guide.md` - Custom rule authoring with examples
|
||||
- `custom_functions.md` - Creating custom JavaScript/TypeScript validation functions
|
||||
- `ruleset_patterns.md` - Reusable ruleset patterns for common security scenarios
|
||||
- `api_security_checklist.md` - API security validation checklist
|
||||
|
||||
### Assets (`assets/`)
|
||||
|
||||
- `spectral-owasp.yaml` - Comprehensive OWASP API Security Top 10 ruleset
|
||||
- `spectral-org-template.yaml` - Organization-wide API security standards template
|
||||
- `github-actions-template.yml` - Complete GitHub Actions workflow
|
||||
- `gitlab-ci-template.yml` - GitLab CI integration template
|
||||
- `rule-templates/` - Reusable security rule templates
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Pattern 1: Security-First API Design Validation
|
||||
|
||||
Validate API specifications during design phase:
|
||||
|
||||
```bash
|
||||
# Design phase validation (strict security rules)
|
||||
spectral lint api-design.yaml \
|
||||
--ruleset .spectral-owasp.yaml \
|
||||
--fail-severity warn \
|
||||
--verbose
|
||||
```
|
||||
|
||||
### Pattern 2: API Specification Diff Analysis
|
||||
|
||||
Detect security regressions between API versions:
|
||||
|
||||
```bash
|
||||
# Compare two API specification versions
|
||||
spectral lint api-v2.yaml --ruleset .spectral.yaml -o v2-findings.json
|
||||
spectral lint api-v1.yaml --ruleset .spectral.yaml -o v1-findings.json
|
||||
|
||||
python3 scripts/compare_spectral_results.py \
|
||||
--baseline v1-findings.json \
|
||||
--current v2-findings.json \
|
||||
--show-regressions
|
||||
```
|
||||
|
||||
### Pattern 3: Multi-Environment API Security
|
||||
|
||||
Different rulesets for development, staging, production:
|
||||
|
||||
```yaml
|
||||
# .spectral-dev.yaml (permissive)
|
||||
extends: ["spectral:oas"]
|
||||
rules:
|
||||
servers-use-https: warn
|
||||
|
||||
# .spectral-prod.yaml (strict)
|
||||
extends: ["spectral:oas"]
|
||||
rules:
|
||||
servers-use-https: error
|
||||
operation-security-defined: error
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **CI/CD**: GitHub Actions, GitLab CI, Jenkins, CircleCI, Azure DevOps
|
||||
- **API Gateways**: Kong, Apigee, AWS API Gateway (validate specs before deployment)
|
||||
- **IDE Integration**: VS Code extension, JetBrains plugins for real-time validation
|
||||
- **API Documentation**: Stoplight Studio, Swagger UI, Redoc
|
||||
- **Issue Tracking**: Jira, GitHub Issues, Linear (automated ticket creation for findings)
|
||||
- **API Governance**: Backstage, API catalogs (enforce standards across portfolios)
|
||||
- **Security Platforms**: Defect Dojo, SIEM platforms (via JSON export)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Too Many False Positives
|
||||
|
||||
**Solution**:
|
||||
- Start with `error` severity only: `spectral lint --fail-severity error`
|
||||
- Progressively add rules and adjust severity levels
|
||||
- Use `overrides` section in ruleset to exclude specific paths
|
||||
- See `references/ruleset_patterns.md` for filtering strategies
|
||||
|
||||
### Issue: Custom Rules Not Working
|
||||
|
||||
**Solution**:
|
||||
- Verify JSONPath expressions using online JSONPath testers
|
||||
- Check rule syntax with `spectral lint --ruleset .spectral.yaml --verbose`
|
||||
- Use `--verbose` flag to see which rules are being applied
|
||||
- Test rules in isolation before combining them
|
||||
|
||||
### Issue: Performance Issues with Large Specifications
|
||||
|
||||
**Solution**:
|
||||
- Lint specific paths only: `spectral lint api-spec.yaml --ignore-paths "components/examples"`
|
||||
- Use `--skip-rules` to disable expensive rules temporarily
|
||||
- Split large specifications into smaller modules
|
||||
- Run Spectral in parallel for multiple specifications
|
||||
|
||||
### Issue: CI/CD Integration Failing
|
||||
|
||||
**Solution**:
|
||||
- Check Node.js version compatibility (requires Node 14+)
|
||||
- Verify ruleset path is correct relative to specification file
|
||||
- Use `--fail-severity` to control when builds should fail
|
||||
- Review exit codes in `scripts/spectral_ci.sh`
|
||||
|
||||
## References
|
||||
|
||||
- [Spectral Documentation](https://docs.stoplight.io/docs/spectral/674b27b261c3c-overview)
|
||||
- [Spectral GitHub Repository](https://github.com/stoplightio/spectral)
|
||||
- [OWASP API Security Top 10](https://owasp.org/API-Security/editions/2023/en/0x11-t10/)
|
||||
- [OpenAPI Specification](https://spec.openapis.org/oas/latest.html)
|
||||
- [AsyncAPI Specification](https://www.asyncapi.com/docs/reference/specification/latest)
|
||||
9
skills/appsec/api-spectral/assets/.gitkeep
Normal file
9
skills/appsec/api-spectral/assets/.gitkeep
Normal file
@@ -0,0 +1,9 @@
|
||||
# Assets Directory
|
||||
|
||||
Place files that will be used in the output Claude produces:
|
||||
- Templates
|
||||
- Configuration files
|
||||
- Images/logos
|
||||
- Boilerplate code
|
||||
|
||||
These files are NOT loaded into context but copied/modified in output.
|
||||
357
skills/appsec/api-spectral/assets/ci-config-template.yml
Normal file
357
skills/appsec/api-spectral/assets/ci-config-template.yml
Normal file
@@ -0,0 +1,357 @@
|
||||
# Security-Enhanced CI/CD Pipeline Template
|
||||
#
|
||||
# This template demonstrates security best practices for CI/CD pipelines.
|
||||
# Adapt this template to your specific security tool and workflow needs.
|
||||
#
|
||||
# Key Security Features:
|
||||
# - SAST (Static Application Security Testing)
|
||||
# - Dependency vulnerability scanning
|
||||
# - Secrets detection
|
||||
# - Infrastructure-as-Code security scanning
|
||||
# - Container image scanning
|
||||
# - Security artifact uploading for compliance
|
||||
|
||||
name: Security Scan Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
schedule:
|
||||
# Run weekly security scans on Sunday at 2 AM UTC
|
||||
- cron: '0 2 * * 0'
|
||||
workflow_dispatch: # Allow manual trigger
|
||||
|
||||
# Security: Restrict permissions to minimum required
|
||||
permissions:
|
||||
contents: read
|
||||
security-events: write # For uploading SARIF results
|
||||
pull-requests: write # For commenting on PRs
|
||||
|
||||
env:
|
||||
# Configuration
|
||||
SECURITY_SCAN_FAIL_ON: 'critical,high' # Fail build on these severities
|
||||
REPORT_DIR: 'security-reports'
|
||||
|
||||
jobs:
|
||||
# Job 1: Static Application Security Testing (SAST)
|
||||
sast-scan:
|
||||
name: SAST Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Full history for better analysis
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Run SAST Scanner
|
||||
run: |
|
||||
# Example: Using Semgrep for SAST
|
||||
pip install semgrep
|
||||
semgrep --config=auto \
|
||||
--json \
|
||||
--output ${{ env.REPORT_DIR }}/sast-results.json \
|
||||
. || true
|
||||
|
||||
# Alternative: Bandit for Python projects
|
||||
# pip install bandit
|
||||
# bandit -r . -f json -o ${{ env.REPORT_DIR }}/bandit-results.json
|
||||
|
||||
- name: Process SAST Results
|
||||
run: |
|
||||
# Parse results and fail on critical/high severity
|
||||
python3 -c "
|
||||
import json
|
||||
import sys
|
||||
|
||||
with open('${{ env.REPORT_DIR }}/sast-results.json') as f:
|
||||
results = json.load(f)
|
||||
|
||||
critical = len([r for r in results.get('results', []) if r.get('extra', {}).get('severity') == 'ERROR'])
|
||||
high = len([r for r in results.get('results', []) if r.get('extra', {}).get('severity') == 'WARNING'])
|
||||
|
||||
print(f'Critical findings: {critical}')
|
||||
print(f'High findings: {high}')
|
||||
|
||||
if critical > 0:
|
||||
print('❌ Build failed: Critical security issues found')
|
||||
sys.exit(1)
|
||||
elif high > 0:
|
||||
print('⚠️ Warning: High severity issues found')
|
||||
# Optionally fail on high severity
|
||||
# sys.exit(1)
|
||||
else:
|
||||
print('✅ No critical security issues found')
|
||||
"
|
||||
|
||||
- name: Upload SAST Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sast-results
|
||||
path: ${{ env.REPORT_DIR }}/sast-results.json
|
||||
retention-days: 30
|
||||
|
||||
# Job 2: Dependency Vulnerability Scanning
|
||||
dependency-scan:
|
||||
name: Dependency Vulnerability Scan
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Scan Python Dependencies
|
||||
if: hashFiles('requirements.txt') != ''
|
||||
run: |
|
||||
pip install safety
|
||||
safety check \
|
||||
--json \
|
||||
--output ${{ env.REPORT_DIR }}/safety-results.json \
|
||||
|| true
|
||||
|
||||
- name: Scan Node Dependencies
|
||||
if: hashFiles('package.json') != ''
|
||||
run: |
|
||||
npm audit --json > ${{ env.REPORT_DIR }}/npm-audit.json || true
|
||||
|
||||
- name: Process Dependency Results
|
||||
run: |
|
||||
# Check for critical vulnerabilities
|
||||
if [ -f "${{ env.REPORT_DIR }}/safety-results.json" ]; then
|
||||
critical_count=$(python3 -c "import json; data=json.load(open('${{ env.REPORT_DIR }}/safety-results.json')); print(len([v for v in data.get('vulnerabilities', []) if v.get('severity', '').lower() == 'critical']))")
|
||||
echo "Critical vulnerabilities: $critical_count"
|
||||
if [ "$critical_count" -gt "0" ]; then
|
||||
echo "❌ Build failed: Critical vulnerabilities in dependencies"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Upload Dependency Scan Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dependency-scan-results
|
||||
path: ${{ env.REPORT_DIR }}/
|
||||
retention-days: 30
|
||||
|
||||
# Job 3: Secrets Detection
|
||||
secrets-scan:
|
||||
name: Secrets Detection
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Full history to scan all commits
|
||||
|
||||
- name: Run Gitleaks
|
||||
uses: gitleaks/gitleaks-action@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GITLEAKS_ENABLE_SUMMARY: true
|
||||
|
||||
- name: Alternative - TruffleHog Scan
|
||||
if: false # Set to true to enable
|
||||
run: |
|
||||
pip install truffleHog
|
||||
trufflehog --json --regex --entropy=True . \
|
||||
> ${{ env.REPORT_DIR }}/trufflehog-results.json || true
|
||||
|
||||
- name: Upload Secrets Scan Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: secrets-scan-results
|
||||
path: ${{ env.REPORT_DIR }}/
|
||||
retention-days: 30
|
||||
|
||||
# Job 4: Container Image Scanning
|
||||
container-scan:
|
||||
name: Container Image Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
if: hashFiles('Dockerfile') != ''
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build Docker Image
|
||||
run: |
|
||||
docker build -t app:${{ github.sha }} .
|
||||
|
||||
- name: Run Trivy Scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: app:${{ github.sha }}
|
||||
format: 'sarif'
|
||||
output: '${{ env.REPORT_DIR }}/trivy-results.sarif'
|
||||
severity: 'CRITICAL,HIGH'
|
||||
|
||||
- name: Upload Trivy Results to GitHub Security
|
||||
if: always()
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: '${{ env.REPORT_DIR }}/trivy-results.sarif'
|
||||
|
||||
- name: Upload Container Scan Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: container-scan-results
|
||||
path: ${{ env.REPORT_DIR }}/
|
||||
retention-days: 30
|
||||
|
||||
# Job 5: Infrastructure-as-Code Security Scanning
|
||||
iac-scan:
|
||||
name: IaC Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
if: hashFiles('**/*.tf', '**/*.yaml', '**/*.yml') != ''
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run Checkov
|
||||
run: |
|
||||
pip install checkov
|
||||
checkov -d . \
|
||||
--output json \
|
||||
--output-file ${{ env.REPORT_DIR }}/checkov-results.json \
|
||||
--quiet \
|
||||
|| true
|
||||
|
||||
- name: Run tfsec (for Terraform)
|
||||
if: hashFiles('**/*.tf') != ''
|
||||
run: |
|
||||
curl -s https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash
|
||||
tfsec . \
|
||||
--format json \
|
||||
--out ${{ env.REPORT_DIR }}/tfsec-results.json \
|
||||
|| true
|
||||
|
||||
- name: Process IaC Results
|
||||
run: |
|
||||
# Fail on critical findings
|
||||
if [ -f "${{ env.REPORT_DIR }}/checkov-results.json" ]; then
|
||||
critical_count=$(python3 -c "import json; data=json.load(open('${{ env.REPORT_DIR }}/checkov-results.json')); print(data.get('summary', {}).get('failed', 0))")
|
||||
echo "Failed checks: $critical_count"
|
||||
if [ "$critical_count" -gt "0" ]; then
|
||||
echo "⚠️ Warning: IaC security issues found"
|
||||
# Optionally fail the build
|
||||
# exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Upload IaC Scan Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: iac-scan-results
|
||||
path: ${{ env.REPORT_DIR }}/
|
||||
retention-days: 30
|
||||
|
||||
# Job 6: Security Report Generation and Notification
|
||||
security-report:
|
||||
name: Generate Security Report
|
||||
runs-on: ubuntu-latest
|
||||
needs: [sast-scan, dependency-scan, secrets-scan]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download All Scan Results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: all-results/
|
||||
|
||||
- name: Generate Consolidated Report
|
||||
run: |
|
||||
# Consolidate all security scan results
|
||||
mkdir -p consolidated-report
|
||||
|
||||
cat > consolidated-report/security-summary.md << 'EOF'
|
||||
# Security Scan Summary
|
||||
|
||||
**Scan Date**: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
|
||||
**Commit**: ${{ github.sha }}
|
||||
**Branch**: ${{ github.ref_name }}
|
||||
|
||||
## Scan Results
|
||||
|
||||
### SAST Scan
|
||||
See artifacts: `sast-results`
|
||||
|
||||
### Dependency Scan
|
||||
See artifacts: `dependency-scan-results`
|
||||
|
||||
### Secrets Scan
|
||||
See artifacts: `secrets-scan-results`
|
||||
|
||||
### Container Scan
|
||||
See artifacts: `container-scan-results`
|
||||
|
||||
### IaC Scan
|
||||
See artifacts: `iac-scan-results`
|
||||
|
||||
---
|
||||
|
||||
For detailed results, download scan artifacts from this workflow run.
|
||||
EOF
|
||||
|
||||
- name: Comment on PR (if applicable)
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const report = fs.readFileSync('consolidated-report/security-summary.md', 'utf8');
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: report
|
||||
});
|
||||
|
||||
- name: Upload Consolidated Report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: consolidated-security-report
|
||||
path: consolidated-report/
|
||||
retention-days: 90
|
||||
|
||||
# Security Best Practices Demonstrated:
|
||||
#
|
||||
# 1. ✅ Minimal permissions (principle of least privilege)
|
||||
# 2. ✅ Multiple security scan types (defense in depth)
|
||||
# 3. ✅ Fail-fast on critical findings
|
||||
# 4. ✅ Secrets detection across full git history
|
||||
# 5. ✅ Container image scanning before deployment
|
||||
# 6. ✅ IaC scanning for misconfigurations
|
||||
# 7. ✅ Artifact retention for compliance audit trail
|
||||
# 8. ✅ SARIF format for GitHub Security integration
|
||||
# 9. ✅ Scheduled scans for continuous monitoring
|
||||
# 10. ✅ PR comments for developer feedback
|
||||
#
|
||||
# Compliance Mappings:
|
||||
# - SOC 2: CC6.1, CC6.6, CC7.2 (Security monitoring and logging)
|
||||
# - PCI-DSS: 6.2, 6.5 (Secure development practices)
|
||||
# - NIST: SA-11 (Developer Security Testing)
|
||||
# - OWASP: Integrated security testing throughout SDLC
|
||||
189
skills/appsec/api-spectral/assets/github-actions-template.yml
Normal file
189
skills/appsec/api-spectral/assets/github-actions-template.yml
Normal file
@@ -0,0 +1,189 @@
|
||||
# GitHub Actions Workflow for Spectral API Security Linting
|
||||
# This workflow validates OpenAPI/AsyncAPI specifications against security best practices
|
||||
|
||||
name: API Security Linting with Spectral
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
paths:
|
||||
- 'api-specs/**/*.yaml'
|
||||
- 'api-specs/**/*.yml'
|
||||
- 'api-specs/**/*.json'
|
||||
- '.spectral.yaml'
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
paths:
|
||||
- 'api-specs/**/*.yaml'
|
||||
- 'api-specs/**/*.yml'
|
||||
- 'api-specs/**/*.json'
|
||||
- '.spectral.yaml'
|
||||
|
||||
jobs:
|
||||
spectral-lint:
|
||||
name: Lint API Specifications
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install Spectral CLI
|
||||
run: npm install -g @stoplight/spectral-cli
|
||||
|
||||
- name: Verify Spectral Installation
|
||||
run: spectral --version
|
||||
|
||||
- name: Lint API Specifications (GitHub Actions Format)
|
||||
run: |
|
||||
spectral lint api-specs/**/*.{yaml,yml,json} \
|
||||
--ruleset .spectral.yaml \
|
||||
--format github-actions \
|
||||
--fail-severity error
|
||||
continue-on-error: true
|
||||
|
||||
- name: Generate JSON Report
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p reports
|
||||
spectral lint api-specs/**/*.{yaml,yml,json} \
|
||||
--ruleset .spectral.yaml \
|
||||
--format json \
|
||||
--output reports/spectral-results.json || true
|
||||
|
||||
- name: Generate HTML Report
|
||||
if: always()
|
||||
run: |
|
||||
# Download parse script if not in repository
|
||||
if [ ! -f "scripts/parse_spectral_results.py" ]; then
|
||||
curl -o scripts/parse_spectral_results.py \
|
||||
https://raw.githubusercontent.com/SecOpsAgentKit/skills/main/appsec/api-spectral/scripts/parse_spectral_results.py
|
||||
chmod +x scripts/parse_spectral_results.py
|
||||
fi
|
||||
|
||||
python3 scripts/parse_spectral_results.py \
|
||||
--input reports/spectral-results.json \
|
||||
--output reports/spectral-report.html \
|
||||
--format html \
|
||||
--map-owasp
|
||||
|
||||
- name: Upload Spectral Reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: spectral-security-reports
|
||||
path: reports/
|
||||
retention-days: 30
|
||||
|
||||
- name: Check for Critical Issues
|
||||
run: |
|
||||
if [ -f "reports/spectral-results.json" ]; then
|
||||
CRITICAL_COUNT=$(jq '[.[] | select(.severity == 0)] | length' reports/spectral-results.json)
|
||||
echo "Critical security issues found: $CRITICAL_COUNT"
|
||||
|
||||
if [ "$CRITICAL_COUNT" -gt 0 ]; then
|
||||
echo "::error::Found $CRITICAL_COUNT critical security issues in API specifications"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Comment PR with Results
|
||||
if: github.event_name == 'pull_request' && always()
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
if (fs.existsSync('reports/spectral-results.json')) {
|
||||
const results = JSON.parse(fs.readFileSync('reports/spectral-results.json', 'utf8'));
|
||||
|
||||
const severityCounts = results.reduce((acc, finding) => {
|
||||
const severity = ['error', 'warn', 'info', 'hint'][finding.severity] || 'unknown';
|
||||
acc[severity] = (acc[severity] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const errorCount = severityCounts.error || 0;
|
||||
const warnCount = severityCounts.warn || 0;
|
||||
const infoCount = severityCounts.info || 0;
|
||||
|
||||
const summary = `## 🔒 API Security Lint Results
|
||||
|
||||
**Total Findings:** ${results.length}
|
||||
|
||||
| Severity | Count |
|
||||
|----------|-------|
|
||||
| 🔴 Error | ${errorCount} |
|
||||
| 🟡 Warning | ${warnCount} |
|
||||
| 🔵 Info | ${infoCount} |
|
||||
|
||||
${errorCount > 0 ? '⚠️ **Action Required:** Fix error-level security issues before merging.' : '✅ No critical security issues found.'}
|
||||
|
||||
📄 [View Detailed Report](../actions/runs/${context.runId})
|
||||
`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: summary
|
||||
});
|
||||
}
|
||||
|
||||
# Optional: Separate job for OWASP-specific validation
|
||||
owasp-validation:
|
||||
name: OWASP API Security Validation
|
||||
runs-on: ubuntu-latest
|
||||
needs: spectral-lint
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Spectral CLI
|
||||
run: npm install -g @stoplight/spectral-cli
|
||||
|
||||
- name: Validate Against OWASP Ruleset
|
||||
run: |
|
||||
# Use OWASP-specific ruleset if available
|
||||
if [ -f ".spectral-owasp.yaml" ]; then
|
||||
RULESET=".spectral-owasp.yaml"
|
||||
else
|
||||
# Download OWASP ruleset template
|
||||
curl -o .spectral-owasp.yaml \
|
||||
https://raw.githubusercontent.com/SecOpsAgentKit/skills/main/appsec/api-spectral/assets/spectral-owasp.yaml
|
||||
RULESET=".spectral-owasp.yaml"
|
||||
fi
|
||||
|
||||
spectral lint api-specs/**/*.{yaml,yml,json} \
|
||||
--ruleset "$RULESET" \
|
||||
--format stylish \
|
||||
--fail-severity warn
|
||||
|
||||
- name: Generate OWASP Compliance Report
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p reports
|
||||
spectral lint api-specs/**/*.{yaml,yml,json} \
|
||||
--ruleset .spectral-owasp.yaml \
|
||||
--format json \
|
||||
--output reports/owasp-validation.json || true
|
||||
|
||||
- name: Upload OWASP Report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: owasp-compliance-report
|
||||
path: reports/owasp-validation.json
|
||||
retention-days: 30
|
||||
355
skills/appsec/api-spectral/assets/rule-template.yaml
Normal file
355
skills/appsec/api-spectral/assets/rule-template.yaml
Normal file
@@ -0,0 +1,355 @@
|
||||
# Security Rule Template
|
||||
#
|
||||
# This template demonstrates how to structure security rules/policies.
|
||||
# Adapt this template to your specific security tool (Semgrep, OPA, etc.)
|
||||
#
|
||||
# Rule Structure Best Practices:
|
||||
# - Clear rule ID and metadata
|
||||
# - Severity classification
|
||||
# - Framework mappings (OWASP, CWE)
|
||||
# - Remediation guidance
|
||||
# - Example vulnerable and fixed code
|
||||
|
||||
rules:
|
||||
# Example Rule 1: SQL Injection Detection
|
||||
- id: sql-injection-string-concatenation
|
||||
metadata:
|
||||
name: "SQL Injection via String Concatenation"
|
||||
description: "Detects potential SQL injection vulnerabilities from string concatenation in SQL queries"
|
||||
severity: "HIGH"
|
||||
category: "security"
|
||||
subcategory: "injection"
|
||||
|
||||
# Security Framework Mappings
|
||||
owasp:
|
||||
- "A03:2021 - Injection"
|
||||
cwe:
|
||||
- "CWE-89: SQL Injection"
|
||||
mitre_attack:
|
||||
- "T1190: Exploit Public-Facing Application"
|
||||
|
||||
# Compliance Standards
|
||||
compliance:
|
||||
- "PCI-DSS 6.5.1: Injection flaws"
|
||||
- "NIST 800-53 SI-10: Information Input Validation"
|
||||
|
||||
# Confidence and Impact
|
||||
confidence: "HIGH"
|
||||
likelihood: "HIGH"
|
||||
impact: "HIGH"
|
||||
|
||||
# References
|
||||
references:
|
||||
- "https://owasp.org/www-community/attacks/SQL_Injection"
|
||||
- "https://cwe.mitre.org/data/definitions/89.html"
|
||||
- "https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html"
|
||||
|
||||
# Languages this rule applies to
|
||||
languages:
|
||||
- python
|
||||
- javascript
|
||||
- java
|
||||
- go
|
||||
|
||||
# Detection Pattern (example using Semgrep-style syntax)
|
||||
pattern-either:
|
||||
- pattern: |
|
||||
cursor.execute($SQL + $VAR)
|
||||
- pattern: |
|
||||
cursor.execute(f"... {$VAR} ...")
|
||||
- pattern: |
|
||||
cursor.execute("..." + $VAR + "...")
|
||||
|
||||
# What to report when found
|
||||
message: |
|
||||
Potential SQL injection vulnerability detected. SQL query is constructed using
|
||||
string concatenation or f-strings with user input. This allows attackers to
|
||||
inject malicious SQL code.
|
||||
|
||||
Use parameterized queries instead:
|
||||
- Python: cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
|
||||
- JavaScript: db.query("SELECT * FROM users WHERE id = $1", [userId])
|
||||
|
||||
See: https://owasp.org/www-community/attacks/SQL_Injection
|
||||
|
||||
# Suggested fix (auto-fix if supported)
|
||||
fix: |
|
||||
Use parameterized queries with placeholders
|
||||
|
||||
# Example vulnerable code
|
||||
examples:
|
||||
- vulnerable: |
|
||||
# Vulnerable: String concatenation
|
||||
user_id = request.GET['id']
|
||||
query = "SELECT * FROM users WHERE id = " + user_id
|
||||
cursor.execute(query)
|
||||
|
||||
- fixed: |
|
||||
# Fixed: Parameterized query
|
||||
user_id = request.GET['id']
|
||||
query = "SELECT * FROM users WHERE id = ?"
|
||||
cursor.execute(query, (user_id,))
|
||||
|
||||
# Example Rule 2: Hardcoded Secrets Detection
|
||||
- id: hardcoded-secret-credential
|
||||
metadata:
|
||||
name: "Hardcoded Secret or Credential"
|
||||
description: "Detects hardcoded secrets, API keys, passwords, or tokens in source code"
|
||||
severity: "CRITICAL"
|
||||
category: "security"
|
||||
subcategory: "secrets"
|
||||
|
||||
owasp:
|
||||
- "A07:2021 - Identification and Authentication Failures"
|
||||
cwe:
|
||||
- "CWE-798: Use of Hard-coded Credentials"
|
||||
- "CWE-259: Use of Hard-coded Password"
|
||||
|
||||
compliance:
|
||||
- "PCI-DSS 8.2.1: Use of strong cryptography"
|
||||
- "SOC 2 CC6.1: Logical access controls"
|
||||
- "GDPR Article 32: Security of processing"
|
||||
|
||||
confidence: "MEDIUM"
|
||||
likelihood: "HIGH"
|
||||
impact: "CRITICAL"
|
||||
|
||||
references:
|
||||
- "https://cwe.mitre.org/data/definitions/798.html"
|
||||
- "https://owasp.org/www-community/vulnerabilities/Use_of_hard-coded_password"
|
||||
|
||||
languages:
|
||||
- python
|
||||
- javascript
|
||||
- java
|
||||
- go
|
||||
- ruby
|
||||
|
||||
pattern-either:
|
||||
- pattern: |
|
||||
password = "..."
|
||||
- pattern: |
|
||||
api_key = "..."
|
||||
- pattern: |
|
||||
secret = "..."
|
||||
- pattern: |
|
||||
token = "..."
|
||||
|
||||
pattern-not: |
|
||||
$VAR = ""
|
||||
|
||||
message: |
|
||||
Potential hardcoded secret detected. Hardcoding credentials in source code
|
||||
is a critical security vulnerability that can lead to unauthorized access
|
||||
if the code is exposed.
|
||||
|
||||
Use environment variables or a secrets management system instead:
|
||||
- Python: os.environ.get('API_KEY')
|
||||
- Node.js: process.env.API_KEY
|
||||
- Secrets Manager: AWS Secrets Manager, HashiCorp Vault, etc.
|
||||
|
||||
See: https://cwe.mitre.org/data/definitions/798.html
|
||||
|
||||
examples:
|
||||
- vulnerable: |
|
||||
# Vulnerable: Hardcoded API key
|
||||
api_key = "sk-1234567890abcdef"
|
||||
api.authenticate(api_key)
|
||||
|
||||
- fixed: |
|
||||
# Fixed: Environment variable
|
||||
import os
|
||||
api_key = os.environ.get('API_KEY')
|
||||
if not api_key:
|
||||
raise ValueError("API_KEY environment variable not set")
|
||||
api.authenticate(api_key)
|
||||
|
||||
# Example Rule 3: XSS via Unsafe HTML Rendering
|
||||
- id: xss-unsafe-html-rendering
|
||||
metadata:
|
||||
name: "Cross-Site Scripting (XSS) via Unsafe HTML"
|
||||
description: "Detects unsafe HTML rendering that could lead to XSS vulnerabilities"
|
||||
severity: "HIGH"
|
||||
category: "security"
|
||||
subcategory: "xss"
|
||||
|
||||
owasp:
|
||||
- "A03:2021 - Injection"
|
||||
cwe:
|
||||
- "CWE-79: Cross-site Scripting (XSS)"
|
||||
- "CWE-80: Improper Neutralization of Script-Related HTML Tags"
|
||||
|
||||
compliance:
|
||||
- "PCI-DSS 6.5.7: Cross-site scripting"
|
||||
- "NIST 800-53 SI-10: Information Input Validation"
|
||||
|
||||
confidence: "HIGH"
|
||||
likelihood: "MEDIUM"
|
||||
impact: "HIGH"
|
||||
|
||||
references:
|
||||
- "https://owasp.org/www-community/attacks/xss/"
|
||||
- "https://cwe.mitre.org/data/definitions/79.html"
|
||||
- "https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html"
|
||||
|
||||
languages:
|
||||
- javascript
|
||||
- typescript
|
||||
- jsx
|
||||
- tsx
|
||||
|
||||
pattern-either:
|
||||
- pattern: |
|
||||
dangerouslySetInnerHTML={{__html: $VAR}}
|
||||
- pattern: |
|
||||
innerHTML = $VAR
|
||||
|
||||
message: |
|
||||
Potential XSS vulnerability detected. Setting HTML content directly from
|
||||
user input without sanitization can allow attackers to inject malicious
|
||||
JavaScript code.
|
||||
|
||||
Use one of these safe alternatives:
|
||||
- React: Use {userInput} for automatic escaping
|
||||
- DOMPurify: const clean = DOMPurify.sanitize(dirty);
|
||||
- Framework-specific sanitizers
|
||||
|
||||
See: https://owasp.org/www-community/attacks/xss/
|
||||
|
||||
examples:
|
||||
- vulnerable: |
|
||||
// Vulnerable: Unsanitized HTML
|
||||
function UserComment({ comment }) {
|
||||
return <div dangerouslySetInnerHTML={{__html: comment}} />;
|
||||
}
|
||||
|
||||
- fixed: |
|
||||
// Fixed: Sanitized with DOMPurify
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
function UserComment({ comment }) {
|
||||
const sanitized = DOMPurify.sanitize(comment);
|
||||
return <div dangerouslySetInnerHTML={{__html: sanitized}} />;
|
||||
}
|
||||
|
||||
# Example Rule 4: Insecure Cryptography
|
||||
- id: weak-cryptographic-algorithm
|
||||
metadata:
|
||||
name: "Weak Cryptographic Algorithm"
|
||||
description: "Detects use of weak or deprecated cryptographic algorithms"
|
||||
severity: "HIGH"
|
||||
category: "security"
|
||||
subcategory: "cryptography"
|
||||
|
||||
owasp:
|
||||
- "A02:2021 - Cryptographic Failures"
|
||||
cwe:
|
||||
- "CWE-327: Use of a Broken or Risky Cryptographic Algorithm"
|
||||
- "CWE-326: Inadequate Encryption Strength"
|
||||
|
||||
compliance:
|
||||
- "PCI-DSS 4.1: Use strong cryptography"
|
||||
- "NIST 800-53 SC-13: Cryptographic Protection"
|
||||
- "GDPR Article 32: Security of processing"
|
||||
|
||||
confidence: "HIGH"
|
||||
likelihood: "MEDIUM"
|
||||
impact: "HIGH"
|
||||
|
||||
references:
|
||||
- "https://cwe.mitre.org/data/definitions/327.html"
|
||||
- "https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/09-Testing_for_Weak_Cryptography/"
|
||||
|
||||
languages:
|
||||
- python
|
||||
- javascript
|
||||
- java
|
||||
|
||||
pattern-either:
|
||||
- pattern: |
|
||||
hashlib.md5(...)
|
||||
- pattern: |
|
||||
hashlib.sha1(...)
|
||||
- pattern: |
|
||||
crypto.createHash('md5')
|
||||
- pattern: |
|
||||
crypto.createHash('sha1')
|
||||
|
||||
message: |
|
||||
Weak cryptographic algorithm detected (MD5 or SHA1). These algorithms are
|
||||
considered cryptographically broken and should not be used for security purposes.
|
||||
|
||||
Use strong alternatives:
|
||||
- For hashing: SHA-256, SHA-384, or SHA-512
|
||||
- For password hashing: bcrypt, argon2, or PBKDF2
|
||||
- Python: hashlib.sha256()
|
||||
- Node.js: crypto.createHash('sha256')
|
||||
|
||||
See: https://cwe.mitre.org/data/definitions/327.html
|
||||
|
||||
examples:
|
||||
- vulnerable: |
|
||||
# Vulnerable: MD5 hash
|
||||
import hashlib
|
||||
hash_value = hashlib.md5(data).hexdigest()
|
||||
|
||||
- fixed: |
|
||||
# Fixed: SHA-256 hash
|
||||
import hashlib
|
||||
hash_value = hashlib.sha256(data).hexdigest()
|
||||
|
||||
# Rule Configuration
|
||||
configuration:
|
||||
# Global settings
|
||||
enabled: true
|
||||
severity_threshold: "MEDIUM" # Report findings at MEDIUM severity and above
|
||||
|
||||
# Performance tuning
|
||||
max_file_size_kb: 1024
|
||||
exclude_patterns:
|
||||
- "test/*"
|
||||
- "tests/*"
|
||||
- "node_modules/*"
|
||||
- "vendor/*"
|
||||
- "*.min.js"
|
||||
|
||||
# False positive reduction
|
||||
confidence_threshold: "MEDIUM" # Only report findings with MEDIUM confidence or higher
|
||||
|
||||
# Rule Metadata Schema
|
||||
# This section documents the expected structure for rules
|
||||
metadata_schema:
|
||||
required:
|
||||
- id: "Unique identifier for the rule (kebab-case)"
|
||||
- name: "Human-readable rule name"
|
||||
- description: "What the rule detects"
|
||||
- severity: "CRITICAL | HIGH | MEDIUM | LOW | INFO"
|
||||
- category: "security | best-practice | performance"
|
||||
|
||||
optional:
|
||||
- subcategory: "Specific type (injection, xss, secrets, etc.)"
|
||||
- owasp: "OWASP Top 10 mappings"
|
||||
- cwe: "CWE identifier(s)"
|
||||
- mitre_attack: "MITRE ATT&CK technique(s)"
|
||||
- compliance: "Compliance standard references"
|
||||
- confidence: "Detection confidence level"
|
||||
- likelihood: "Likelihood of exploitation"
|
||||
- impact: "Potential impact if exploited"
|
||||
- references: "External documentation links"
|
||||
|
||||
# Usage Instructions:
|
||||
#
|
||||
# 1. Copy this template when creating new security rules
|
||||
# 2. Update metadata fields with appropriate framework mappings
|
||||
# 3. Customize detection patterns for your tool (Semgrep, OPA, etc.)
|
||||
# 4. Provide clear remediation guidance in the message field
|
||||
# 5. Include both vulnerable and fixed code examples
|
||||
# 6. Test rules on real codebases before deployment
|
||||
#
|
||||
# Best Practices:
|
||||
# - Map to multiple frameworks (OWASP, CWE, MITRE ATT&CK)
|
||||
# - Include compliance standard references
|
||||
# - Provide actionable remediation guidance
|
||||
# - Show code examples (vulnerable vs. fixed)
|
||||
# - Tune confidence levels to reduce false positives
|
||||
# - Exclude test directories to reduce noise
|
||||
293
skills/appsec/api-spectral/assets/spectral-owasp.yaml
Normal file
293
skills/appsec/api-spectral/assets/spectral-owasp.yaml
Normal file
@@ -0,0 +1,293 @@
|
||||
# Comprehensive OWASP API Security Top 10 2023 Spectral Ruleset
|
||||
# This ruleset enforces OWASP API Security best practices for OpenAPI specifications
|
||||
|
||||
extends: ["spectral:oas"]
|
||||
|
||||
rules:
|
||||
# ============================================================================
|
||||
# API1:2023 - Broken Object Level Authorization
|
||||
# ============================================================================
|
||||
|
||||
operation-security-defined:
|
||||
description: All operations must have security requirements defined (OWASP API1)
|
||||
severity: error
|
||||
given: $.paths[*][get,post,put,patch,delete,head]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Operations must define security requirements to prevent unauthorized object access (OWASP API1:2023 - Broken Object Level Authorization)"
|
||||
|
||||
id-parameters-require-security:
|
||||
description: Operations with ID parameters must have security defined
|
||||
severity: error
|
||||
given: $.paths[?(@property =~ /(\/\{id\}|\/\{.*[_-]id\})/i)][get,put,patch,delete]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Operations with ID parameters require security to prevent IDOR vulnerabilities (OWASP API1:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API2:2023 - Broken Authentication
|
||||
# ============================================================================
|
||||
|
||||
security-schemes-required:
|
||||
description: API must define security schemes (OWASP API2)
|
||||
severity: error
|
||||
given: $.components
|
||||
then:
|
||||
- field: securitySchemes
|
||||
function: truthy
|
||||
message: "API must define security schemes to prevent authentication bypass (OWASP API2:2023 - Broken Authentication)"
|
||||
|
||||
no-http-basic-auth:
|
||||
description: HTTP Basic authentication is insecure for APIs
|
||||
severity: error
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
- field: scheme
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "^basic$"
|
||||
message: "HTTP Basic authentication transmits credentials in plain text - use OAuth2, API key, or JWT (OWASP API2:2023)"
|
||||
|
||||
bearer-format-specified:
|
||||
description: Bearer authentication should specify token format (JWT recommended)
|
||||
severity: warn
|
||||
given: $.components.securitySchemes[?(@.type == 'http' && @.scheme == 'bearer')]
|
||||
then:
|
||||
- field: bearerFormat
|
||||
function: truthy
|
||||
message: "Bearer authentication should specify token format (bearerFormat: JWT) for clarity (OWASP API2:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API3:2023 - Broken Object Property Level Authorization
|
||||
# ============================================================================
|
||||
|
||||
no-additional-properties:
|
||||
description: Prevent mass assignment by disabling additionalProperties
|
||||
severity: warn
|
||||
given: $.components.schemas[?(@.type == 'object')]
|
||||
then:
|
||||
- field: additionalProperties
|
||||
function: falsy
|
||||
message: "Set additionalProperties to false to prevent mass assignment vulnerabilities (OWASP API3:2023 - Broken Object Property Level Authorization)"
|
||||
|
||||
schemas-have-properties:
|
||||
description: Object schemas should explicitly define properties
|
||||
severity: warn
|
||||
given: $.components.schemas[?(@.type == 'object')]
|
||||
then:
|
||||
- field: properties
|
||||
function: truthy
|
||||
message: "Explicitly define object properties to control data exposure (OWASP API3:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API4:2023 - Unrestricted Resource Consumption
|
||||
# ============================================================================
|
||||
|
||||
rate-limit-headers-documented:
|
||||
description: API should document rate limiting headers
|
||||
severity: warn
|
||||
given: $.paths[*][get,post,put,patch,delete].responses[?(@property < '300')].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
anyOf:
|
||||
- required: [X-RateLimit-Limit]
|
||||
- required: [X-Rate-Limit-Limit]
|
||||
- required: [RateLimit-Limit]
|
||||
message: "Document rate limiting headers to communicate resource consumption limits (OWASP API4:2023 - Unrestricted Resource Consumption)"
|
||||
|
||||
pagination-parameters-present:
|
||||
description: List operations should support pagination
|
||||
severity: warn
|
||||
given: $.paths[*].get
|
||||
then:
|
||||
- field: parameters
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: array
|
||||
contains:
|
||||
anyOf:
|
||||
- properties:
|
||||
name:
|
||||
enum: [limit, per_page, page_size]
|
||||
- properties:
|
||||
name:
|
||||
enum: [offset, page, cursor]
|
||||
message: "List operations should support pagination (limit/offset or cursor) to prevent resource exhaustion (OWASP API4:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API5:2023 - Broken Function Level Authorization
|
||||
# ============================================================================
|
||||
|
||||
write-operations-require-security:
|
||||
description: Write operations must have security requirements
|
||||
severity: error
|
||||
given: $.paths[*][post,put,patch,delete]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Write operations must have security requirements to prevent unauthorized function access (OWASP API5:2023 - Broken Function Level Authorization)"
|
||||
|
||||
admin-paths-require-security:
|
||||
description: Admin endpoints must have strict security
|
||||
severity: error
|
||||
given: $.paths[?(@property =~ /admin/i)][*]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Admin endpoints require security requirements with appropriate scopes (OWASP API5:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API7:2023 - Server Side Request Forgery
|
||||
# ============================================================================
|
||||
|
||||
no-url-parameters:
|
||||
description: Avoid URL parameters to prevent SSRF attacks
|
||||
severity: warn
|
||||
given: $.paths[*][*].parameters[?(@.in == 'query' || @.in == 'body')][?(@.name =~ /(url|uri|link|callback|redirect|webhook)/i)]
|
||||
then:
|
||||
function: truthy
|
||||
message: "URL parameters can enable SSRF attacks - validate and whitelist destination URLs (OWASP API7:2023 - Server Side Request Forgery)"
|
||||
|
||||
# ============================================================================
|
||||
# API8:2023 - Security Misconfiguration
|
||||
# ============================================================================
|
||||
|
||||
servers-use-https:
|
||||
description: All API servers must use HTTPS
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^https://"
|
||||
message: "Server URLs must use HTTPS protocol for secure communication (OWASP API8:2023 - Security Misconfiguration)"
|
||||
|
||||
no-example-servers:
|
||||
description: Replace example server URLs with actual endpoints
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "example\\.com"
|
||||
message: "Replace example.com with actual production server URLs (OWASP API8:2023)"
|
||||
|
||||
security-headers-in-responses:
|
||||
description: Document security headers in responses
|
||||
severity: info
|
||||
given: $.paths[*][*].responses[*].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
anyOf:
|
||||
- required: [X-Content-Type-Options]
|
||||
- required: [X-Frame-Options]
|
||||
- required: [Strict-Transport-Security]
|
||||
- required: [Content-Security-Policy]
|
||||
message: "Consider documenting security headers (X-Content-Type-Options, X-Frame-Options, HSTS, CSP) (OWASP API8:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API9:2023 - Improper Inventory Management
|
||||
# ============================================================================
|
||||
|
||||
api-version-required:
|
||||
description: API specification must include version
|
||||
severity: error
|
||||
given: $.info
|
||||
then:
|
||||
- field: version
|
||||
function: truthy
|
||||
message: "API version must be specified for proper inventory management (OWASP API9:2023 - Improper Inventory Management)"
|
||||
|
||||
semantic-versioning-format:
|
||||
description: Use semantic versioning for API versions
|
||||
severity: warn
|
||||
given: $.info.version
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^\\d+\\.\\d+(\\.\\d+)?$"
|
||||
message: "Use semantic versioning format (MAJOR.MINOR.PATCH) for API versions (OWASP API9:2023)"
|
||||
|
||||
contact-info-required:
|
||||
description: API must include contact information
|
||||
severity: warn
|
||||
given: $.info
|
||||
then:
|
||||
- field: contact
|
||||
function: truthy
|
||||
message: "Include contact information for API support and security reporting (OWASP API9:2023)"
|
||||
|
||||
deprecated-endpoints-documented:
|
||||
description: Deprecated endpoints must document migration path
|
||||
severity: warn
|
||||
given: $.paths[*][*][?(@.deprecated == true)]
|
||||
then:
|
||||
- field: description
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "(deprecate|migrate|alternative|replacement|use instead)"
|
||||
message: "Deprecated endpoints must document migration path and timeline (OWASP API9:2023)"
|
||||
|
||||
# ============================================================================
|
||||
# API10:2023 - Unsafe Consumption of APIs
|
||||
# ============================================================================
|
||||
|
||||
validate-external-api-responses:
|
||||
description: Document validation of external API responses
|
||||
severity: info
|
||||
given: $.paths[*][*].responses[*].content[*].schema
|
||||
then:
|
||||
- field: description
|
||||
function: truthy
|
||||
message: "Document schema validation for all API responses, especially from external APIs (OWASP API10:2023 - Unsafe Consumption of APIs)"
|
||||
|
||||
# ============================================================================
|
||||
# Additional Security Best Practices
|
||||
# ============================================================================
|
||||
|
||||
no-pii-in-query-parameters:
|
||||
description: Prevent PII exposure in URL query parameters
|
||||
severity: error
|
||||
given: $.paths[*][*].parameters[?(@.in == 'query')].name
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "(?i)(ssn|social.?security|credit.?card|password|secret|token|api.?key|private|passport|driver.?license)"
|
||||
message: "Query parameters must not contain PII or sensitive data - use request body with HTTPS instead"
|
||||
|
||||
consistent-error-response-format:
|
||||
description: Error responses should follow consistent format
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[?(@property >= '400')].content.application/json.schema
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
required: [error, message]
|
||||
message: "Error responses should follow consistent format with 'error' and 'message' fields"
|
||||
|
||||
no-verbose-error-details:
|
||||
description: 5xx errors should not expose internal details
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[?(@property >= '500')].content[*].schema.properties
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
not:
|
||||
anyOf:
|
||||
- required: [stack_trace]
|
||||
- required: [stackTrace]
|
||||
- required: [debug_info]
|
||||
message: "5xx error responses should not expose stack traces or internal details in production"
|
||||
550
skills/appsec/api-spectral/references/EXAMPLE.md
Normal file
550
skills/appsec/api-spectral/references/EXAMPLE.md
Normal file
@@ -0,0 +1,550 @@
|
||||
# Reference Document Template
|
||||
|
||||
This file demonstrates how to structure detailed reference material that Claude loads on-demand.
|
||||
|
||||
**When to use this reference**: Include a clear statement about when Claude should consult this document.
|
||||
For example: "Consult this reference when analyzing Python code for security vulnerabilities and needing detailed remediation patterns."
|
||||
|
||||
**Document purpose**: Briefly explain what this reference provides that's not in SKILL.md.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
**For documents >100 lines, always include a table of contents** to help Claude navigate quickly.
|
||||
|
||||
- [When to Use References](#when-to-use-references)
|
||||
- [Document Organization](#document-organization)
|
||||
- [Detailed Technical Content](#detailed-technical-content)
|
||||
- [Security Framework Mappings](#security-framework-mappings)
|
||||
- [OWASP Top 10](#owasp-top-10)
|
||||
- [CWE Mappings](#cwe-mappings)
|
||||
- [MITRE ATT&CK](#mitre-attck)
|
||||
- [Remediation Patterns](#remediation-patterns)
|
||||
- [Advanced Configuration](#advanced-configuration)
|
||||
- [Examples and Code Samples](#examples-and-code-samples)
|
||||
|
||||
---
|
||||
|
||||
## When to Use References
|
||||
|
||||
**Move content from SKILL.md to references/** when:
|
||||
|
||||
1. **Content exceeds 100 lines** - Keep SKILL.md concise
|
||||
2. **Framework-specific details** - Detailed OWASP/CWE/MITRE mappings
|
||||
3. **Advanced user content** - Deep technical details for expert users
|
||||
4. **Lookup-oriented content** - Rule libraries, configuration matrices, comprehensive lists
|
||||
5. **Language-specific patterns** - Separate files per language/framework
|
||||
6. **Historical context** - Old patterns and deprecated approaches
|
||||
|
||||
**Keep in SKILL.md**:
|
||||
- Core workflows (top 3-5 use cases)
|
||||
- Decision points and branching logic
|
||||
- Quick start guidance
|
||||
- Essential security considerations
|
||||
|
||||
---
|
||||
|
||||
## Document Organization
|
||||
|
||||
### Structure for Long Documents
|
||||
|
||||
For references >100 lines:
|
||||
|
||||
```markdown
|
||||
# Title
|
||||
|
||||
**When to use**: Clear trigger statement
|
||||
**Purpose**: What this provides
|
||||
|
||||
## Table of Contents
|
||||
- Links to all major sections
|
||||
|
||||
## Quick Reference
|
||||
- Key facts or commands for fast lookup
|
||||
|
||||
## Detailed Content
|
||||
- Comprehensive information organized logically
|
||||
|
||||
## Framework Mappings
|
||||
- OWASP, CWE, MITRE ATT&CK references
|
||||
|
||||
## Examples
|
||||
- Code samples and patterns
|
||||
```
|
||||
|
||||
### Section Naming Conventions
|
||||
|
||||
- Use **imperative** or **declarative** headings
|
||||
- ✅ "Detecting SQL Injection" not "How to detect SQL Injection"
|
||||
- ✅ "Common Patterns" not "These are common patterns"
|
||||
- Make headings **searchable** and **specific**
|
||||
|
||||
---
|
||||
|
||||
## Detailed Technical Content
|
||||
|
||||
This section demonstrates the type of detailed content that belongs in references rather than SKILL.md.
|
||||
|
||||
### Example: Comprehensive Vulnerability Detection
|
||||
|
||||
#### SQL Injection Detection Patterns
|
||||
|
||||
**Pattern 1: String Concatenation in Queries**
|
||||
|
||||
```python
|
||||
# Vulnerable pattern
|
||||
query = "SELECT * FROM users WHERE id = " + user_id
|
||||
cursor.execute(query)
|
||||
|
||||
# Detection criteria:
|
||||
# - SQL keyword (SELECT, INSERT, UPDATE, DELETE)
|
||||
# - String concatenation operator (+, f-string)
|
||||
# - Variable user input (request params, form data)
|
||||
|
||||
# Severity: HIGH
|
||||
# CWE: CWE-89
|
||||
# OWASP: A03:2021 - Injection
|
||||
```
|
||||
|
||||
**Remediation**:
|
||||
```python
|
||||
# Fixed: Parameterized query
|
||||
query = "SELECT * FROM users WHERE id = ?"
|
||||
cursor.execute(query, (user_id,))
|
||||
|
||||
# OR using ORM
|
||||
user = User.objects.get(id=user_id)
|
||||
```
|
||||
|
||||
**Pattern 2: Unsafe String Formatting**
|
||||
|
||||
```python
|
||||
# Vulnerable patterns
|
||||
query = f"SELECT * FROM users WHERE name = '{username}'"
|
||||
query = "SELECT * FROM users WHERE name = '%s'" % username
|
||||
query = "SELECT * FROM users WHERE name = '{}'".format(username)
|
||||
|
||||
# All three patterns are vulnerable to SQL injection
|
||||
```
|
||||
|
||||
#### Cross-Site Scripting (XSS) Detection
|
||||
|
||||
**Pattern 1: Unescaped Output in Templates**
|
||||
|
||||
```javascript
|
||||
// Vulnerable: Direct HTML injection
|
||||
element.innerHTML = userInput;
|
||||
document.write(userInput);
|
||||
|
||||
// Vulnerable: React dangerouslySetInnerHTML
|
||||
<div dangerouslySetInnerHTML={{__html: userComment}} />
|
||||
|
||||
// Detection criteria:
|
||||
# - Direct DOM manipulation (innerHTML, document.write)
|
||||
# - React dangerouslySetInnerHTML with user data
|
||||
# - Template engines with autoescaping disabled
|
||||
|
||||
// Severity: HIGH
|
||||
// CWE: CWE-79
|
||||
// OWASP: A03:2021 - Injection
|
||||
```
|
||||
|
||||
**Remediation**:
|
||||
```javascript
|
||||
// Fixed: Escaped output
|
||||
element.textContent = userInput; // Auto-escapes
|
||||
|
||||
// Fixed: Sanitization library
|
||||
import DOMPurify from 'dompurify';
|
||||
const clean = DOMPurify.sanitize(userComment);
|
||||
<div dangerouslySetInnerHTML={{__html: clean}} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Framework Mappings
|
||||
|
||||
This section provides comprehensive security framework mappings for findings.
|
||||
|
||||
### OWASP Top 10
|
||||
|
||||
Map security findings to OWASP Top 10 (2021) categories:
|
||||
|
||||
| Category | Title | Common Vulnerabilities |
|
||||
|----------|-------|----------------------|
|
||||
| **A01:2021** | Broken Access Control | Authorization bypass, privilege escalation, IDOR |
|
||||
| **A02:2021** | Cryptographic Failures | Weak crypto, plaintext storage, insecure TLS |
|
||||
| **A03:2021** | Injection | SQL injection, XSS, command injection, LDAP injection |
|
||||
| **A04:2021** | Insecure Design | Missing security controls, threat modeling gaps |
|
||||
| **A05:2021** | Security Misconfiguration | Default configs, verbose errors, unnecessary features |
|
||||
| **A06:2021** | Vulnerable Components | Outdated libraries, unpatched dependencies |
|
||||
| **A07:2021** | Auth & Session Failures | Weak passwords, session fixation, missing MFA |
|
||||
| **A08:2021** | Software & Data Integrity | Unsigned updates, insecure CI/CD, deserialization |
|
||||
| **A09:2021** | Logging & Monitoring Failures | Insufficient logging, no alerting, log injection |
|
||||
| **A10:2021** | SSRF | Server-side request forgery, unvalidated redirects |
|
||||
|
||||
**Usage**: When reporting findings, map to primary OWASP category and reference the identifier (e.g., "A03:2021 - Injection").
|
||||
|
||||
### CWE Mappings
|
||||
|
||||
Map to relevant Common Weakness Enumeration categories for precise vulnerability classification:
|
||||
|
||||
#### Injection Vulnerabilities
|
||||
- **CWE-78**: OS Command Injection
|
||||
- **CWE-79**: Cross-site Scripting (XSS)
|
||||
- **CWE-89**: SQL Injection
|
||||
- **CWE-90**: LDAP Injection
|
||||
- **CWE-91**: XML Injection
|
||||
- **CWE-94**: Code Injection
|
||||
|
||||
#### Authentication & Authorization
|
||||
- **CWE-287**: Improper Authentication
|
||||
- **CWE-288**: Authentication Bypass Using Alternate Path
|
||||
- **CWE-290**: Authentication Bypass by Spoofing
|
||||
- **CWE-294**: Authentication Bypass by Capture-replay
|
||||
- **CWE-306**: Missing Authentication for Critical Function
|
||||
- **CWE-307**: Improper Restriction of Excessive Authentication Attempts
|
||||
- **CWE-352**: Cross-Site Request Forgery (CSRF)
|
||||
|
||||
#### Cryptographic Issues
|
||||
- **CWE-256**: Plaintext Storage of Password
|
||||
- **CWE-259**: Use of Hard-coded Password
|
||||
- **CWE-261**: Weak Encoding for Password
|
||||
- **CWE-321**: Use of Hard-coded Cryptographic Key
|
||||
- **CWE-326**: Inadequate Encryption Strength
|
||||
- **CWE-327**: Use of Broken or Risky Cryptographic Algorithm
|
||||
- **CWE-329**: Not Using a Random IV with CBC Mode
|
||||
- **CWE-798**: Use of Hard-coded Credentials
|
||||
|
||||
#### Input Validation
|
||||
- **CWE-20**: Improper Input Validation
|
||||
- **CWE-73**: External Control of File Name or Path
|
||||
- **CWE-434**: Unrestricted Upload of File with Dangerous Type
|
||||
- **CWE-601**: URL Redirection to Untrusted Site
|
||||
|
||||
#### Sensitive Data Exposure
|
||||
- **CWE-200**: Information Exposure
|
||||
- **CWE-209**: Information Exposure Through Error Message
|
||||
- **CWE-312**: Cleartext Storage of Sensitive Information
|
||||
- **CWE-319**: Cleartext Transmission of Sensitive Information
|
||||
- **CWE-532**: Information Exposure Through Log Files
|
||||
|
||||
**Usage**: Include CWE identifier in all vulnerability reports for standardized classification.
|
||||
|
||||
### MITRE ATT&CK
|
||||
|
||||
Reference relevant tactics and techniques for threat context:
|
||||
|
||||
#### Initial Access (TA0001)
|
||||
- **T1190**: Exploit Public-Facing Application
|
||||
- **T1133**: External Remote Services
|
||||
- **T1078**: Valid Accounts
|
||||
|
||||
#### Execution (TA0002)
|
||||
- **T1059**: Command and Scripting Interpreter
|
||||
- **T1203**: Exploitation for Client Execution
|
||||
|
||||
#### Persistence (TA0003)
|
||||
- **T1098**: Account Manipulation
|
||||
- **T1136**: Create Account
|
||||
- **T1505**: Server Software Component
|
||||
|
||||
#### Privilege Escalation (TA0004)
|
||||
- **T1068**: Exploitation for Privilege Escalation
|
||||
- **T1548**: Abuse Elevation Control Mechanism
|
||||
|
||||
#### Defense Evasion (TA0005)
|
||||
- **T1027**: Obfuscated Files or Information
|
||||
- **T1140**: Deobfuscate/Decode Files or Information
|
||||
- **T1562**: Impair Defenses
|
||||
|
||||
#### Credential Access (TA0006)
|
||||
- **T1110**: Brute Force
|
||||
- **T1555**: Credentials from Password Stores
|
||||
- **T1552**: Unsecured Credentials
|
||||
|
||||
#### Discovery (TA0007)
|
||||
- **T1083**: File and Directory Discovery
|
||||
- **T1046**: Network Service Scanning
|
||||
|
||||
#### Collection (TA0009)
|
||||
- **T1005**: Data from Local System
|
||||
- **T1114**: Email Collection
|
||||
|
||||
#### Exfiltration (TA0010)
|
||||
- **T1041**: Exfiltration Over C2 Channel
|
||||
- **T1567**: Exfiltration Over Web Service
|
||||
|
||||
**Usage**: When identifying vulnerabilities, consider which ATT&CK techniques an attacker could use to exploit them.
|
||||
|
||||
---
|
||||
|
||||
## Remediation Patterns
|
||||
|
||||
This section provides specific remediation guidance for common vulnerability types.
|
||||
|
||||
### SQL Injection Remediation
|
||||
|
||||
**Step 1: Identify vulnerable queries**
|
||||
- Search for string concatenation in SQL queries
|
||||
- Check for f-strings or format() with SQL keywords
|
||||
- Review all database interaction code
|
||||
|
||||
**Step 2: Apply parameterized queries**
|
||||
|
||||
```python
|
||||
# Python with sqlite3
|
||||
cursor.execute("SELECT * FROM users WHERE id = ?", (user_id,))
|
||||
|
||||
# Python with psycopg2 (PostgreSQL)
|
||||
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
||||
|
||||
# Python with SQLAlchemy (ORM)
|
||||
from sqlalchemy import text
|
||||
result = session.execute(text("SELECT * FROM users WHERE id = :id"), {"id": user_id})
|
||||
```
|
||||
|
||||
**Step 3: Validate and sanitize input** (defense in depth)
|
||||
```python
|
||||
import re
|
||||
|
||||
# Validate input format
|
||||
if not re.match(r'^\d+$', user_id):
|
||||
raise ValueError("Invalid user ID format")
|
||||
|
||||
# Use ORM query builders
|
||||
user = User.query.filter_by(id=user_id).first()
|
||||
```
|
||||
|
||||
**Step 4: Implement least privilege**
|
||||
- Database user should have minimum required permissions
|
||||
- Use read-only accounts for SELECT operations
|
||||
- Never use admin/root accounts for application queries
|
||||
|
||||
### XSS Remediation
|
||||
|
||||
**Step 1: Enable auto-escaping**
|
||||
- Most modern frameworks escape by default
|
||||
- Ensure auto-escaping is not disabled
|
||||
|
||||
**Step 2: Use framework-specific safe methods**
|
||||
|
||||
```javascript
|
||||
// React: Use JSX (auto-escapes)
|
||||
<div>{userInput}</div>
|
||||
|
||||
// Vue: Use template syntax (auto-escapes)
|
||||
<div>{{ userInput }}</div>
|
||||
|
||||
// Angular: Use property binding (auto-escapes)
|
||||
<div [textContent]="userInput"></div>
|
||||
```
|
||||
|
||||
**Step 3: Sanitize when HTML is required**
|
||||
|
||||
```javascript
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
// Sanitize HTML content
|
||||
const clean = DOMPurify.sanitize(userHTML, {
|
||||
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
|
||||
ALLOWED_ATTR: []
|
||||
});
|
||||
```
|
||||
|
||||
**Step 4: Content Security Policy (CSP)**
|
||||
|
||||
```html
|
||||
<!-- Add CSP header -->
|
||||
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
This section contains detailed configuration options and tuning parameters.
|
||||
|
||||
### Example: SAST Tool Configuration
|
||||
|
||||
```yaml
|
||||
# Advanced security scanner configuration
|
||||
scanner:
|
||||
# Severity threshold
|
||||
severity_threshold: MEDIUM
|
||||
|
||||
# Rule configuration
|
||||
rules:
|
||||
enabled:
|
||||
- sql-injection
|
||||
- xss
|
||||
- hardcoded-secrets
|
||||
disabled:
|
||||
- informational-only
|
||||
|
||||
# False positive reduction
|
||||
confidence_threshold: HIGH
|
||||
exclude_patterns:
|
||||
- "*/test/*"
|
||||
- "*/tests/*"
|
||||
- "*/node_modules/*"
|
||||
- "*.test.js"
|
||||
- "*.spec.ts"
|
||||
|
||||
# Performance tuning
|
||||
max_file_size_kb: 2048
|
||||
timeout_seconds: 300
|
||||
parallel_jobs: 4
|
||||
|
||||
# Output configuration
|
||||
output_format: json
|
||||
include_code_snippets: true
|
||||
max_snippet_lines: 10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Examples and Code Samples
|
||||
|
||||
This section provides comprehensive code examples for various scenarios.
|
||||
|
||||
### Example 1: Secure API Authentication
|
||||
|
||||
```python
|
||||
# Secure API key handling
|
||||
import os
|
||||
from functools import wraps
|
||||
from flask import Flask, request, jsonify
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Load API key from environment (never hardcode)
|
||||
VALID_API_KEY = os.environ.get('API_KEY')
|
||||
if not VALID_API_KEY:
|
||||
raise ValueError("API_KEY environment variable not set")
|
||||
|
||||
def require_api_key(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
api_key = request.headers.get('X-API-Key')
|
||||
|
||||
if not api_key:
|
||||
return jsonify({'error': 'API key required'}), 401
|
||||
|
||||
# Constant-time comparison to prevent timing attacks
|
||||
import hmac
|
||||
if not hmac.compare_digest(api_key, VALID_API_KEY):
|
||||
return jsonify({'error': 'Invalid API key'}), 403
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
@app.route('/api/secure-endpoint')
|
||||
@require_api_key
|
||||
def secure_endpoint():
|
||||
return jsonify({'message': 'Access granted'})
|
||||
```
|
||||
|
||||
### Example 2: Secure Password Hashing
|
||||
|
||||
```python
|
||||
# Secure password storage with bcrypt
|
||||
import bcrypt
|
||||
|
||||
def hash_password(password: str) -> str:
|
||||
"""Hash a password using bcrypt."""
|
||||
# Generate salt and hash password
|
||||
salt = bcrypt.gensalt(rounds=12) # Cost factor: 12 (industry standard)
|
||||
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
|
||||
return hashed.decode('utf-8')
|
||||
|
||||
def verify_password(password: str, hashed: str) -> bool:
|
||||
"""Verify a password against a hash."""
|
||||
return bcrypt.checkpw(
|
||||
password.encode('utf-8'),
|
||||
hashed.encode('utf-8')
|
||||
)
|
||||
|
||||
# Usage
|
||||
stored_hash = hash_password("user_password")
|
||||
is_valid = verify_password("user_password", stored_hash) # True
|
||||
```
|
||||
|
||||
### Example 3: Secure File Upload
|
||||
|
||||
```python
|
||||
# Secure file upload with validation
|
||||
import os
|
||||
import magic
|
||||
from werkzeug.utils import secure_filename
|
||||
|
||||
ALLOWED_EXTENSIONS = {'pdf', 'png', 'jpg', 'jpeg'}
|
||||
ALLOWED_MIME_TYPES = {
|
||||
'application/pdf',
|
||||
'image/png',
|
||||
'image/jpeg'
|
||||
}
|
||||
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB
|
||||
|
||||
def is_allowed_file(filename: str, file_content: bytes) -> bool:
|
||||
"""Validate file extension and MIME type."""
|
||||
# Check extension
|
||||
if '.' not in filename:
|
||||
return False
|
||||
|
||||
ext = filename.rsplit('.', 1)[1].lower()
|
||||
if ext not in ALLOWED_EXTENSIONS:
|
||||
return False
|
||||
|
||||
# Check MIME type (prevent extension spoofing)
|
||||
mime = magic.from_buffer(file_content, mime=True)
|
||||
if mime not in ALLOWED_MIME_TYPES:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def handle_upload(file):
|
||||
"""Securely handle file upload."""
|
||||
# Check file size
|
||||
file.seek(0, os.SEEK_END)
|
||||
size = file.tell()
|
||||
file.seek(0)
|
||||
|
||||
if size > MAX_FILE_SIZE:
|
||||
raise ValueError("File too large")
|
||||
|
||||
# Read content for validation
|
||||
content = file.read()
|
||||
file.seek(0)
|
||||
|
||||
# Validate file type
|
||||
if not is_allowed_file(file.filename, content):
|
||||
raise ValueError("Invalid file type")
|
||||
|
||||
# Sanitize filename
|
||||
filename = secure_filename(file.filename)
|
||||
|
||||
# Generate unique filename to prevent overwrite attacks
|
||||
import uuid
|
||||
unique_filename = f"{uuid.uuid4()}_{filename}"
|
||||
|
||||
# Save to secure location (outside web root)
|
||||
upload_path = os.path.join('/secure/uploads', unique_filename)
|
||||
file.save(upload_path)
|
||||
|
||||
return unique_filename
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices for Reference Documents
|
||||
|
||||
1. **Start with "When to use"** - Help Claude know when to load this reference
|
||||
2. **Include table of contents** - For documents >100 lines
|
||||
3. **Use concrete examples** - Code samples with vulnerable and fixed versions
|
||||
4. **Map to frameworks** - OWASP, CWE, MITRE ATT&CK for context
|
||||
5. **Provide remediation** - Don't just identify issues, show how to fix them
|
||||
6. **Organize logically** - Group related content, use clear headings
|
||||
7. **Keep examples current** - Use modern patterns and current framework versions
|
||||
8. **Be concise** - Even in references, challenge every sentence
|
||||
253
skills/appsec/api-spectral/references/WORKFLOW_CHECKLIST.md
Normal file
253
skills/appsec/api-spectral/references/WORKFLOW_CHECKLIST.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# Workflow Checklist Template
|
||||
|
||||
This template demonstrates workflow patterns for security operations. Copy and adapt these checklists to your specific skill needs.
|
||||
|
||||
## Pattern 1: Sequential Workflow Checklist
|
||||
|
||||
Use this pattern for operations that must be completed in order, step-by-step.
|
||||
|
||||
### Security Assessment Workflow
|
||||
|
||||
Progress:
|
||||
[ ] 1. Identify application entry points and attack surface
|
||||
[ ] 2. Map authentication and authorization flows
|
||||
[ ] 3. Identify data flows and sensitive data handling
|
||||
[ ] 4. Review existing security controls
|
||||
[ ] 5. Document findings with framework references (OWASP, CWE)
|
||||
[ ] 6. Prioritize findings by severity (CVSS scores)
|
||||
[ ] 7. Generate report with remediation recommendations
|
||||
|
||||
Work through each step systematically. Check off completed items.
|
||||
|
||||
---
|
||||
|
||||
## Pattern 2: Conditional Workflow
|
||||
|
||||
Use this pattern when the workflow branches based on findings or conditions.
|
||||
|
||||
### Vulnerability Remediation Workflow
|
||||
|
||||
1. Identify vulnerability type
|
||||
- If SQL Injection → See [sql-injection-remediation.md](sql-injection-remediation.md)
|
||||
- If XSS (Cross-Site Scripting) → See [xss-remediation.md](xss-remediation.md)
|
||||
- If Authentication flaw → See [auth-remediation.md](auth-remediation.md)
|
||||
- If Authorization flaw → See [authz-remediation.md](authz-remediation.md)
|
||||
- If Cryptographic issue → See [crypto-remediation.md](crypto-remediation.md)
|
||||
|
||||
2. Assess severity using CVSS calculator
|
||||
- If CVSS >= 9.0 → Priority: Critical (immediate action)
|
||||
- If CVSS 7.0-8.9 → Priority: High (action within 24h)
|
||||
- If CVSS 4.0-6.9 → Priority: Medium (action within 1 week)
|
||||
- If CVSS < 4.0 → Priority: Low (action within 30 days)
|
||||
|
||||
3. Apply appropriate remediation pattern
|
||||
4. Validate fix with security testing
|
||||
5. Document changes and update security documentation
|
||||
|
||||
---
|
||||
|
||||
## Pattern 3: Iterative Workflow
|
||||
|
||||
Use this pattern for operations that repeat across multiple targets or items.
|
||||
|
||||
### Code Security Review Workflow
|
||||
|
||||
For each file in the review scope:
|
||||
1. Identify security-sensitive operations (auth, data access, crypto, input handling)
|
||||
2. Check against secure coding patterns for the language
|
||||
3. Flag potential vulnerabilities with severity rating
|
||||
4. Map findings to CWE and OWASP categories
|
||||
5. Suggest specific remediation approaches
|
||||
6. Document finding with code location and fix priority
|
||||
|
||||
Continue until all files in scope have been reviewed.
|
||||
|
||||
---
|
||||
|
||||
## Pattern 4: Feedback Loop Workflow
|
||||
|
||||
Use this pattern when validation and iteration are required.
|
||||
|
||||
### Secure Configuration Generation Workflow
|
||||
|
||||
1. Generate initial security configuration based on requirements
|
||||
2. Run validation script: `./scripts/validate_config.py config.yaml`
|
||||
3. Review validation output:
|
||||
- Note all errors (must fix)
|
||||
- Note all warnings (should fix)
|
||||
- Note all info items (consider)
|
||||
4. Fix identified issues in configuration
|
||||
5. Repeat steps 2-4 until validation passes with zero errors
|
||||
6. Review warnings and determine if they should be addressed
|
||||
7. Apply configuration once validation is clean
|
||||
|
||||
**Validation Loop**: Run validator → Fix errors → Repeat until clean
|
||||
|
||||
---
|
||||
|
||||
## Pattern 5: Parallel Analysis Workflow
|
||||
|
||||
Use this pattern when multiple independent analyses can run concurrently.
|
||||
|
||||
### Comprehensive Security Scan Workflow
|
||||
|
||||
Run these scans in parallel:
|
||||
|
||||
**Static Analysis**:
|
||||
[ ] 1a. Run SAST scan (Semgrep/Bandit)
|
||||
[ ] 1b. Run dependency vulnerability scan (Safety/npm audit)
|
||||
[ ] 1c. Run secrets detection (Gitleaks/TruffleHog)
|
||||
[ ] 1d. Run license compliance check
|
||||
|
||||
**Dynamic Analysis**:
|
||||
[ ] 2a. Run DAST scan (ZAP/Burp)
|
||||
[ ] 2b. Run API security testing
|
||||
[ ] 2c. Run authentication/authorization testing
|
||||
|
||||
**Infrastructure Analysis**:
|
||||
[ ] 3a. Run infrastructure-as-code scan (Checkov/tfsec)
|
||||
[ ] 3b. Run container image scan (Trivy/Grype)
|
||||
[ ] 3c. Run configuration review
|
||||
|
||||
**Consolidation**:
|
||||
[ ] 4. Aggregate all findings
|
||||
[ ] 5. Deduplicate and correlate findings
|
||||
[ ] 6. Prioritize by risk (CVSS + exploitability + business impact)
|
||||
[ ] 7. Generate unified security report
|
||||
|
||||
---
|
||||
|
||||
## Pattern 6: Research and Documentation Workflow
|
||||
|
||||
Use this pattern for security research and documentation tasks.
|
||||
|
||||
### Threat Modeling Workflow
|
||||
|
||||
Research Progress:
|
||||
[ ] 1. Identify system components and boundaries
|
||||
[ ] 2. Map data flows between components
|
||||
[ ] 3. Identify trust boundaries
|
||||
[ ] 4. Enumerate assets (data, services, credentials)
|
||||
[ ] 5. Apply STRIDE framework to each component:
|
||||
- Spoofing threats
|
||||
- Tampering threats
|
||||
- Repudiation threats
|
||||
- Information disclosure threats
|
||||
- Denial of service threats
|
||||
- Elevation of privilege threats
|
||||
[ ] 6. Map threats to MITRE ATT&CK techniques
|
||||
[ ] 7. Identify existing mitigations
|
||||
[ ] 8. Document residual risks
|
||||
[ ] 9. Recommend additional security controls
|
||||
[ ] 10. Generate threat model document
|
||||
|
||||
Work through each step systematically. Check off completed items.
|
||||
|
||||
---
|
||||
|
||||
## Pattern 7: Compliance Validation Workflow
|
||||
|
||||
Use this pattern for compliance checks against security standards.
|
||||
|
||||
### Security Compliance Audit Workflow
|
||||
|
||||
**SOC 2 Controls Review**:
|
||||
[ ] 1. Review access control policies (CC6.1, CC6.2, CC6.3)
|
||||
[ ] 2. Verify logical access controls implementation (CC6.1)
|
||||
[ ] 3. Review authentication mechanisms (CC6.1)
|
||||
[ ] 4. Verify encryption implementation (CC6.1, CC6.7)
|
||||
[ ] 5. Review audit logging configuration (CC7.2)
|
||||
[ ] 6. Verify security monitoring (CC7.2, CC7.3)
|
||||
[ ] 7. Review incident response procedures (CC7.3, CC7.4)
|
||||
[ ] 8. Verify backup and recovery processes (A1.2, A1.3)
|
||||
|
||||
**Evidence Collection**:
|
||||
[ ] 9. Collect policy documents
|
||||
[ ] 10. Collect configuration screenshots
|
||||
[ ] 11. Collect audit logs
|
||||
[ ] 12. Document control gaps
|
||||
[ ] 13. Generate compliance report
|
||||
|
||||
---
|
||||
|
||||
## Pattern 8: Incident Response Workflow
|
||||
|
||||
Use this pattern for security incident handling.
|
||||
|
||||
### Security Incident Response Workflow
|
||||
|
||||
**Detection and Analysis**:
|
||||
[ ] 1. Confirm security incident (rule out false positive)
|
||||
[ ] 2. Determine incident severity (SEV1/2/3/4)
|
||||
[ ] 3. Identify affected systems and data
|
||||
[ ] 4. Preserve evidence (logs, memory dumps, network captures)
|
||||
|
||||
**Containment**:
|
||||
[ ] 5. Isolate affected systems (network segmentation)
|
||||
[ ] 6. Disable compromised accounts
|
||||
[ ] 7. Block malicious indicators (IPs, domains, hashes)
|
||||
[ ] 8. Implement temporary compensating controls
|
||||
|
||||
**Eradication**:
|
||||
[ ] 9. Identify root cause
|
||||
[ ] 10. Remove malicious artifacts (malware, backdoors, webshells)
|
||||
[ ] 11. Patch vulnerabilities exploited
|
||||
[ ] 12. Reset compromised credentials
|
||||
|
||||
**Recovery**:
|
||||
[ ] 13. Restore systems from clean backups (if needed)
|
||||
[ ] 14. Re-enable systems with monitoring
|
||||
[ ] 15. Verify system integrity
|
||||
[ ] 16. Resume normal operations
|
||||
|
||||
**Post-Incident**:
|
||||
[ ] 17. Document incident timeline
|
||||
[ ] 18. Identify lessons learned
|
||||
[ ] 19. Update security controls to prevent recurrence
|
||||
[ ] 20. Update incident response procedures
|
||||
[ ] 21. Communicate with stakeholders
|
||||
|
||||
---
|
||||
|
||||
## Usage Guidelines
|
||||
|
||||
### When to Use Workflow Checklists
|
||||
|
||||
✅ **Use checklists for**:
|
||||
- Complex multi-step operations
|
||||
- Operations requiring specific order
|
||||
- Security assessments and audits
|
||||
- Incident response procedures
|
||||
- Compliance validation tasks
|
||||
|
||||
❌ **Don't use checklists for**:
|
||||
- Simple single-step operations
|
||||
- Highly dynamic exploratory work
|
||||
- Operations that vary significantly each time
|
||||
|
||||
### Adapting This Template
|
||||
|
||||
1. **Copy relevant pattern** to your skill's SKILL.md or create new reference file
|
||||
2. **Customize steps** to match your specific security tool or process
|
||||
3. **Add framework references** (OWASP, CWE, NIST) where applicable
|
||||
4. **Include tool-specific commands** for automation
|
||||
5. **Add decision points** where manual judgment is required
|
||||
|
||||
### Checklist Best Practices
|
||||
|
||||
- **Be specific**: "Run semgrep --config=auto ." not "Scan the code"
|
||||
- **Include success criteria**: "Validation passes with 0 errors"
|
||||
- **Reference standards**: Link to OWASP, CWE, NIST where relevant
|
||||
- **Show progress**: Checkbox format helps track completion
|
||||
- **Provide escape hatches**: "If validation fails, see troubleshooting.md"
|
||||
|
||||
### Integration with Feedback Loops
|
||||
|
||||
Combine checklists with validation scripts for maximum effectiveness:
|
||||
|
||||
1. Create checklist for the workflow
|
||||
2. Provide validation script that checks quality
|
||||
3. Include "run validator" step in checklist
|
||||
4. Loop: Complete step → Validate → Fix issues → Re-validate
|
||||
|
||||
This pattern dramatically improves output quality through systematic validation.
|
||||
553
skills/appsec/api-spectral/references/custom_rules_guide.md
Normal file
553
skills/appsec/api-spectral/references/custom_rules_guide.md
Normal file
@@ -0,0 +1,553 @@
|
||||
# Spectral Custom Rules Development Guide
|
||||
|
||||
This guide covers creating custom security rules for Spectral to enforce organization-specific API security standards.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Rule Structure](#rule-structure)
|
||||
- [JSONPath Expressions](#jsonpath-expressions)
|
||||
- [Built-in Functions](#built-in-functions)
|
||||
- [Security Rule Examples](#security-rule-examples)
|
||||
- [Testing Custom Rules](#testing-custom-rules)
|
||||
- [Best Practices](#best-practices)
|
||||
|
||||
## Rule Structure
|
||||
|
||||
Every Spectral rule consists of:
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
rule-name:
|
||||
description: Human-readable description
|
||||
severity: error|warn|info|hint
|
||||
given: JSONPath expression targeting specific parts of spec
|
||||
then:
|
||||
- field: property to check (optional)
|
||||
function: validation function
|
||||
functionOptions: function-specific options
|
||||
message: Error message shown when rule fails
|
||||
```
|
||||
|
||||
### Severity Levels
|
||||
|
||||
- **error**: Critical security issues that must be fixed
|
||||
- **warn**: Important security recommendations
|
||||
- **info**: Best practices and suggestions
|
||||
- **hint**: Style guide and documentation improvements
|
||||
|
||||
## JSONPath Expressions
|
||||
|
||||
### Basic Path Selection
|
||||
|
||||
```yaml
|
||||
# Target all paths
|
||||
given: $.paths[*]
|
||||
|
||||
# Target all GET operations
|
||||
given: $.paths[*].get
|
||||
|
||||
# Target all HTTP methods
|
||||
given: $.paths[*][get,post,put,patch,delete]
|
||||
|
||||
# Target security schemes
|
||||
given: $.components.securitySchemes[*]
|
||||
|
||||
# Target all schemas
|
||||
given: $.components.schemas[*]
|
||||
```
|
||||
|
||||
### Advanced Filters
|
||||
|
||||
```yaml
|
||||
# Filter by property value
|
||||
given: $.paths[*][?(@.security)]
|
||||
|
||||
# Filter objects by type
|
||||
given: $.components.schemas[?(@.type == 'object')]
|
||||
|
||||
# Filter parameters by location
|
||||
given: $.paths[*][*].parameters[?(@.in == 'query')]
|
||||
|
||||
# Regular expression matching
|
||||
given: $.paths[*][*].parameters[?(@.name =~ /^(id|.*_id)$/i)]
|
||||
|
||||
# Nested property access
|
||||
given: $.paths[*][*].responses[?(@property >= 400)]
|
||||
```
|
||||
|
||||
## Built-in Functions
|
||||
|
||||
### truthy / falsy
|
||||
|
||||
Check if field exists or doesn't exist:
|
||||
|
||||
```yaml
|
||||
# Require field to exist
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
|
||||
# Require field to not exist
|
||||
then:
|
||||
- field: additionalProperties
|
||||
function: falsy
|
||||
```
|
||||
|
||||
### pattern
|
||||
|
||||
Match string against regex pattern:
|
||||
|
||||
```yaml
|
||||
# Match HTTPS URLs
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^https://"
|
||||
|
||||
# Ensure no sensitive terms
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "(password|secret|api[_-]?key)"
|
||||
```
|
||||
|
||||
### enumeration
|
||||
|
||||
Restrict to specific values:
|
||||
|
||||
```yaml
|
||||
# Require specific auth types
|
||||
then:
|
||||
field: type
|
||||
function: enumeration
|
||||
functionOptions:
|
||||
values: [apiKey, oauth2, openIdConnect]
|
||||
```
|
||||
|
||||
### length
|
||||
|
||||
Validate string/array length:
|
||||
|
||||
```yaml
|
||||
# Minimum description length
|
||||
then:
|
||||
field: description
|
||||
function: length
|
||||
functionOptions:
|
||||
min: 10
|
||||
max: 500
|
||||
```
|
||||
|
||||
### schema
|
||||
|
||||
Validate against JSON Schema:
|
||||
|
||||
```yaml
|
||||
# Require specific object structure
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
required: [error, message]
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
```
|
||||
|
||||
### alphabetical
|
||||
|
||||
Ensure alphabetical ordering:
|
||||
|
||||
```yaml
|
||||
# Require alphabetically sorted tags
|
||||
then:
|
||||
field: tags
|
||||
function: alphabetical
|
||||
```
|
||||
|
||||
## Security Rule Examples
|
||||
|
||||
### Prevent PII in URL Parameters
|
||||
|
||||
```yaml
|
||||
no-pii-in-query-params:
|
||||
description: Query parameters must not contain PII
|
||||
severity: error
|
||||
given: $.paths[*][*].parameters[?(@.in == 'query')].name
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "(?i)(ssn|social.?security|credit.?card|password|passport|driver.?license|tax.?id|national.?id)"
|
||||
message: "Query parameter names suggest PII - use request body instead"
|
||||
```
|
||||
|
||||
### Require API Key for Authentication
|
||||
|
||||
```yaml
|
||||
require-api-key-security:
|
||||
description: APIs must use API key authentication
|
||||
severity: error
|
||||
given: $.components.securitySchemes
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
minProperties: 1
|
||||
patternProperties:
|
||||
".*":
|
||||
anyOf:
|
||||
- properties:
|
||||
type:
|
||||
const: apiKey
|
||||
- properties:
|
||||
type:
|
||||
const: oauth2
|
||||
- properties:
|
||||
type:
|
||||
const: openIdConnect
|
||||
message: "API must define apiKey, OAuth2, or OpenID Connect security"
|
||||
```
|
||||
|
||||
### Enforce Rate Limiting Headers
|
||||
|
||||
```yaml
|
||||
rate-limit-headers-present:
|
||||
description: Responses should include rate limit headers
|
||||
severity: warn
|
||||
given: $.paths[*][get,post,put,patch,delete].responses[?(@property == '200' || @property == '201')].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
anyOf:
|
||||
- required: [X-RateLimit-Limit]
|
||||
- required: [X-Rate-Limit-Limit]
|
||||
message: "Include rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining) in success responses"
|
||||
```
|
||||
|
||||
### Detect Missing Authorization for Sensitive Operations
|
||||
|
||||
```yaml
|
||||
sensitive-operations-require-security:
|
||||
description: Sensitive operations must have security requirements
|
||||
severity: error
|
||||
given: $.paths[*][post,put,patch,delete]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Write operations must have security requirements defined"
|
||||
```
|
||||
|
||||
### Prevent Verbose Error Messages
|
||||
|
||||
```yaml
|
||||
no-verbose-error-responses:
|
||||
description: Error responses should not expose internal details
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[?(@property >= 500)].content.application/json.schema.properties
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
not:
|
||||
anyOf:
|
||||
- required: [stack_trace]
|
||||
- required: [stackTrace]
|
||||
- required: [debug_info]
|
||||
- required: [internal_message]
|
||||
message: "5xx error responses should not expose stack traces or internal details"
|
||||
```
|
||||
|
||||
### Require Audit Fields in Schemas
|
||||
|
||||
```yaml
|
||||
require-audit-fields:
|
||||
description: Data models should include audit fields
|
||||
severity: info
|
||||
given: $.components.schemas[?(@.type == 'object' && @.properties)]
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
properties:
|
||||
type: object
|
||||
anyOf:
|
||||
- required: [created_at, updated_at]
|
||||
- required: [createdAt, updatedAt]
|
||||
message: "Consider adding audit fields (created_at, updated_at) to data models"
|
||||
```
|
||||
|
||||
### Detect Insecure Content Types
|
||||
|
||||
```yaml
|
||||
no-insecure-content-types:
|
||||
description: Avoid insecure content types
|
||||
severity: warn
|
||||
given: $.paths[*][*].requestBody.content
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
not:
|
||||
required: [text/html, text/xml, application/x-www-form-urlencoded]
|
||||
message: "Prefer application/json over HTML, XML, or form-encoded content types"
|
||||
```
|
||||
|
||||
### Validate JWT Security Configuration
|
||||
|
||||
```yaml
|
||||
jwt-proper-configuration:
|
||||
description: JWT bearer authentication should be properly configured
|
||||
severity: error
|
||||
given: $.components.securitySchemes[?(@.type == 'http' && @.scheme == 'bearer')]
|
||||
then:
|
||||
- field: bearerFormat
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^JWT$"
|
||||
message: "Bearer authentication should specify 'JWT' as bearerFormat"
|
||||
```
|
||||
|
||||
### Require CORS Documentation
|
||||
|
||||
```yaml
|
||||
cors-options-documented:
|
||||
description: CORS preflight endpoints should be documented
|
||||
severity: warn
|
||||
given: $.paths[*]
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
if:
|
||||
properties:
|
||||
get:
|
||||
type: object
|
||||
then:
|
||||
properties:
|
||||
options:
|
||||
type: object
|
||||
required: [responses]
|
||||
message: "Document OPTIONS method for CORS preflight requests"
|
||||
```
|
||||
|
||||
### Prevent Numeric IDs in URLs
|
||||
|
||||
```yaml
|
||||
prefer-uuid-over-numeric-ids:
|
||||
description: Use UUIDs instead of numeric IDs to prevent enumeration
|
||||
severity: info
|
||||
given: $.paths.*~
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "\\{id\\}|\\{.*_id\\}"
|
||||
message: "Consider using UUIDs instead of numeric IDs to prevent enumeration attacks"
|
||||
```
|
||||
|
||||
## Testing Custom Rules
|
||||
|
||||
### Create Test Specifications
|
||||
|
||||
```yaml
|
||||
# test-specs/valid-auth.yaml
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Valid API
|
||||
version: 1.0.0
|
||||
components:
|
||||
securitySchemes:
|
||||
apiKey:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: X-API-Key
|
||||
security:
|
||||
- apiKey: []
|
||||
```
|
||||
|
||||
```yaml
|
||||
# test-specs/invalid-auth.yaml
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Invalid API
|
||||
version: 1.0.0
|
||||
components:
|
||||
securitySchemes:
|
||||
basicAuth:
|
||||
type: http
|
||||
scheme: basic
|
||||
security:
|
||||
- basicAuth: []
|
||||
```
|
||||
|
||||
### Test Rules
|
||||
|
||||
```bash
|
||||
# Test custom ruleset
|
||||
spectral lint test-specs/valid-auth.yaml --ruleset .spectral-custom.yaml
|
||||
|
||||
# Expected: No errors
|
||||
|
||||
spectral lint test-specs/invalid-auth.yaml --ruleset .spectral-custom.yaml
|
||||
|
||||
# Expected: Error about HTTP Basic auth
|
||||
```
|
||||
|
||||
### Automated Testing Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# test-rules.sh - Test custom Spectral rules
|
||||
|
||||
RULESET=".spectral-custom.yaml"
|
||||
TEST_DIR="test-specs"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
for spec in "$TEST_DIR"/*.yaml; do
|
||||
echo "Testing: $spec"
|
||||
|
||||
if spectral lint "$spec" --ruleset "$RULESET" > /dev/null 2>&1; then
|
||||
if [[ "$spec" == *"valid"* ]]; then
|
||||
echo " ✓ PASS (correctly validated)"
|
||||
((PASS++))
|
||||
else
|
||||
echo " ✗ FAIL (should have detected issues)"
|
||||
((FAIL++))
|
||||
fi
|
||||
else
|
||||
if [[ "$spec" == *"invalid"* ]]; then
|
||||
echo " ✓ PASS (correctly detected issues)"
|
||||
((PASS++))
|
||||
else
|
||||
echo " ✗ FAIL (false positive)"
|
||||
((FAIL++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Results: $PASS passed, $FAIL failed"
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Start with Built-in Rules
|
||||
|
||||
Extend existing rulesets instead of starting from scratch:
|
||||
|
||||
```yaml
|
||||
extends: ["spectral:oas", "spectral:asyncapi"]
|
||||
|
||||
rules:
|
||||
# Add custom rules here
|
||||
custom-security-rule:
|
||||
# ...
|
||||
```
|
||||
|
||||
### 2. Use Descriptive Names
|
||||
|
||||
Rule names should clearly indicate what they check:
|
||||
|
||||
```yaml
|
||||
# Good
|
||||
no-pii-in-query-params:
|
||||
require-https-servers:
|
||||
jwt-bearer-format-required:
|
||||
|
||||
# Bad
|
||||
check-params:
|
||||
security-rule-1:
|
||||
validate-auth:
|
||||
```
|
||||
|
||||
### 3. Provide Actionable Messages
|
||||
|
||||
```yaml
|
||||
# Good
|
||||
message: "Query parameters must not contain PII (ssn, credit_card) - use request body instead"
|
||||
|
||||
# Bad
|
||||
message: "Invalid parameter"
|
||||
```
|
||||
|
||||
### 4. Choose Appropriate Severity
|
||||
|
||||
```yaml
|
||||
# error - Must fix (security vulnerabilities)
|
||||
severity: error
|
||||
|
||||
# warn - Should fix (security best practices)
|
||||
severity: warn
|
||||
|
||||
# info - Consider fixing (recommendations)
|
||||
severity: info
|
||||
|
||||
# hint - Nice to have (style guide)
|
||||
severity: hint
|
||||
```
|
||||
|
||||
### 5. Document Rule Rationale
|
||||
|
||||
```yaml
|
||||
rules:
|
||||
no-numeric-ids:
|
||||
description: |
|
||||
Use UUIDs instead of auto-incrementing numeric IDs in URLs to prevent
|
||||
enumeration attacks where attackers can guess valid IDs sequentially.
|
||||
This follows OWASP API Security best practices for API1:2023.
|
||||
severity: warn
|
||||
# ...
|
||||
```
|
||||
|
||||
### 6. Use Rule Overrides for Exceptions
|
||||
|
||||
```yaml
|
||||
# Allow specific paths to violate rules
|
||||
overrides:
|
||||
- files: ["**/internal-api.yaml"]
|
||||
rules:
|
||||
require-https-servers: off
|
||||
|
||||
- files: ["**/admin-api.yaml"]
|
||||
rules:
|
||||
no-http-basic-auth: warn # Downgrade to warning
|
||||
```
|
||||
|
||||
### 7. Organize Rules by Category
|
||||
|
||||
```yaml
|
||||
# .spectral.yaml - Main ruleset
|
||||
extends:
|
||||
- .spectral-auth.yaml # Authentication rules
|
||||
- .spectral-authz.yaml # Authorization rules
|
||||
- .spectral-data.yaml # Data protection rules
|
||||
- .spectral-owasp.yaml # OWASP mappings
|
||||
```
|
||||
|
||||
### 8. Version Control Your Rulesets
|
||||
|
||||
```bash
|
||||
# Track ruleset evolution
|
||||
git log -p .spectral.yaml
|
||||
|
||||
# Tag stable ruleset versions
|
||||
git tag -a ruleset-v1.0 -m "Production-ready security ruleset"
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Spectral Rulesets Documentation](https://docs.stoplight.io/docs/spectral/docs/getting-started/rulesets.md)
|
||||
- [JSONPath Online Evaluator](https://jsonpath.com/)
|
||||
- [Custom Functions Guide](./custom_functions.md)
|
||||
- [OWASP API Security Mappings](./owasp_api_mappings.md)
|
||||
472
skills/appsec/api-spectral/references/owasp_api_mappings.md
Normal file
472
skills/appsec/api-spectral/references/owasp_api_mappings.md
Normal file
@@ -0,0 +1,472 @@
|
||||
# OWASP API Security Top 10 2023 - Spectral Rule Mappings
|
||||
|
||||
This reference provides comprehensive Spectral rule mappings to OWASP API Security Top 10 2023, including custom rule examples for detecting each category of vulnerability.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [API1:2023 - Broken Object Level Authorization](#api12023---broken-object-level-authorization)
|
||||
- [API2:2023 - Broken Authentication](#api22023---broken-authentication)
|
||||
- [API3:2023 - Broken Object Property Level Authorization](#api32023---broken-object-property-level-authorization)
|
||||
- [API4:2023 - Unrestricted Resource Consumption](#api42023---unrestricted-resource-consumption)
|
||||
- [API5:2023 - Broken Function Level Authorization](#api52023---broken-function-level-authorization)
|
||||
- [API6:2023 - Unrestricted Access to Sensitive Business Flows](#api62023---unrestricted-access-to-sensitive-business-flows)
|
||||
- [API7:2023 - Server Side Request Forgery](#api72023---server-side-request-forgery)
|
||||
- [API8:2023 - Security Misconfiguration](#api82023---security-misconfiguration)
|
||||
- [API9:2023 - Improper Inventory Management](#api92023---improper-inventory-management)
|
||||
- [API10:2023 - Unsafe Consumption of APIs](#api102023---unsafe-consumption-of-apis)
|
||||
|
||||
---
|
||||
|
||||
## API1:2023 - Broken Object Level Authorization
|
||||
|
||||
**Description**: APIs tend to expose endpoints that handle object identifiers, creating a wide attack surface Level Access Control issue. Object level authorization checks should be considered in every function that accesses a data source using an input from the user.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api1.yaml
|
||||
rules:
|
||||
# Require security on all operations
|
||||
operation-security-defined:
|
||||
description: All operations must have security requirements (OWASP API1)
|
||||
severity: error
|
||||
given: $.paths[*][get,post,put,patch,delete]
|
||||
then:
|
||||
- field: security
|
||||
function: truthy
|
||||
message: "Operations must define security requirements to prevent unauthorized object access (OWASP API1:2023)"
|
||||
|
||||
# Detect ID parameters without authorization checks
|
||||
id-parameter-requires-security:
|
||||
description: Operations with ID parameters must have security defined
|
||||
severity: error
|
||||
given: $.paths[*][*].parameters[?(@.name =~ /^(id|.*[_-]id)$/i)]
|
||||
then:
|
||||
function: falsy
|
||||
message: "Path contains ID parameter - ensure operation has security requirements (OWASP API1:2023)"
|
||||
|
||||
# Require authorization scopes for CRUD operations
|
||||
crud-requires-authorization-scope:
|
||||
description: CRUD operations should specify authorization scopes
|
||||
severity: warn
|
||||
given: $.paths[*][get,post,put,patch,delete].security[*]
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
minProperties: 1
|
||||
message: "CRUD operations should specify authorization scopes (OWASP API1:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Implement object-level authorization checks in API specification security requirements
|
||||
- Define per-operation security schemes with appropriate scopes
|
||||
- Document which user roles can access which objects
|
||||
- Consider using OAuth 2.0 with fine-grained scopes
|
||||
|
||||
---
|
||||
|
||||
## API2:2023 - Broken Authentication
|
||||
|
||||
**Description**: Authentication mechanisms are often implemented incorrectly, allowing attackers to compromise authentication tokens or exploit implementation flaws to assume other users' identities.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api2.yaml
|
||||
rules:
|
||||
# Require security schemes definition
|
||||
security-schemes-required:
|
||||
description: API must define security schemes (OWASP API2)
|
||||
severity: error
|
||||
given: $.components
|
||||
then:
|
||||
- field: securitySchemes
|
||||
function: truthy
|
||||
message: "API must define security schemes to prevent authentication bypass (OWASP API2:2023)"
|
||||
|
||||
# Prohibit HTTP Basic authentication
|
||||
no-http-basic-auth:
|
||||
description: HTTP Basic auth is insecure for APIs
|
||||
severity: error
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
- field: scheme
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "^basic$"
|
||||
message: "HTTP Basic authentication transmits credentials in plain text (OWASP API2:2023)"
|
||||
|
||||
# Require bearer token format specification
|
||||
bearer-format-required:
|
||||
description: Bearer authentication should specify token format (JWT recommended)
|
||||
severity: warn
|
||||
given: $.components.securitySchemes[?(@.type == 'http' && @.scheme == 'bearer')]
|
||||
then:
|
||||
- field: bearerFormat
|
||||
function: truthy
|
||||
message: "Bearer authentication should specify token format, preferably JWT (OWASP API2:2023)"
|
||||
|
||||
# Require OAuth2 flow for authentication
|
||||
oauth2-recommended:
|
||||
description: OAuth2 provides secure authentication flows
|
||||
severity: info
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
- field: type
|
||||
function: enumeration
|
||||
functionOptions:
|
||||
values: [oauth2, openIdConnect, http]
|
||||
message: "Consider using OAuth2 or OpenID Connect for robust authentication (OWASP API2:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Use OAuth 2.0 or OpenID Connect for authentication
|
||||
- Implement JWT with proper expiration and signature validation
|
||||
- Avoid HTTP Basic authentication for production APIs
|
||||
- Document authentication flows and token refresh mechanisms
|
||||
|
||||
---
|
||||
|
||||
## API3:2023 - Broken Object Property Level Authorization
|
||||
|
||||
**Description**: This category combines API3:2019 Excessive Data Exposure and API6:2019 Mass Assignment, focusing on the root cause: the lack of or improper authorization validation at the object property level.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api3.yaml
|
||||
rules:
|
||||
# Prohibit additionalProperties for security
|
||||
no-additional-properties:
|
||||
description: Prevent mass assignment by disabling additionalProperties
|
||||
severity: warn
|
||||
given: $.components.schemas[*]
|
||||
then:
|
||||
- field: additionalProperties
|
||||
function: falsy
|
||||
message: "Set additionalProperties to false to prevent mass assignment vulnerabilities (OWASP API3:2023)"
|
||||
|
||||
# Require explicit property definitions
|
||||
schema-properties-required:
|
||||
description: Schemas should explicitly define all properties
|
||||
severity: warn
|
||||
given: $.components.schemas[?(@.type == 'object')]
|
||||
then:
|
||||
- field: properties
|
||||
function: truthy
|
||||
message: "Explicitly define all object properties to control data exposure (OWASP API3:2023)"
|
||||
|
||||
# Warn on write-only properties
|
||||
detect-write-only-properties:
|
||||
description: Document write-only properties to prevent data exposure
|
||||
severity: info
|
||||
given: $.components.schemas[*].properties[*]
|
||||
then:
|
||||
- field: writeOnly
|
||||
function: truthy
|
||||
message: "Ensure write-only properties are properly handled (OWASP API3:2023)"
|
||||
|
||||
# Require read-only for sensitive computed fields
|
||||
computed-fields-read-only:
|
||||
description: Computed fields should be marked as readOnly
|
||||
severity: warn
|
||||
given: $.components.schemas[*].properties[?(@.description =~ /calculated|computed|derived/i)]
|
||||
then:
|
||||
- field: readOnly
|
||||
function: truthy
|
||||
message: "Mark computed/calculated fields as readOnly (OWASP API3:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Set `additionalProperties: false` in schemas to prevent mass assignment
|
||||
- Use `readOnly` for properties that shouldn't be modified by clients
|
||||
- Use `writeOnly` for sensitive input properties (passwords, tokens)
|
||||
- Document which properties are accessible to which user roles
|
||||
|
||||
---
|
||||
|
||||
## API4:2023 - Unrestricted Resource Consumption
|
||||
|
||||
**Description**: Satisfying API requests requires resources such as network bandwidth, CPU, memory, and storage. Sometimes required resources are made available by service providers via API integrations, and paid for per request, such as sending emails/SMS/phone calls, biometrics validation, etc.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api4.yaml
|
||||
rules:
|
||||
# Require rate limit documentation
|
||||
rate-limit-headers-documented:
|
||||
description: API should document rate limiting headers
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[*].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
X-RateLimit-Limit:
|
||||
type: object
|
||||
X-RateLimit-Remaining:
|
||||
type: object
|
||||
message: "Document rate limiting headers (X-RateLimit-*) to communicate consumption limits (OWASP API4:2023)"
|
||||
|
||||
# Detect pagination parameters
|
||||
pagination-required:
|
||||
description: List operations should support pagination
|
||||
severity: warn
|
||||
given: $.paths[*].get.parameters
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: array
|
||||
contains:
|
||||
anyOf:
|
||||
- properties:
|
||||
name:
|
||||
const: limit
|
||||
- properties:
|
||||
name:
|
||||
const: offset
|
||||
message: "List operations should support pagination (limit/offset or cursor) to prevent resource exhaustion (OWASP API4:2023)"
|
||||
|
||||
# Maximum response size documentation
|
||||
response-size-limits:
|
||||
description: Document maximum response sizes
|
||||
severity: info
|
||||
given: $.paths[*][*].responses[*]
|
||||
then:
|
||||
- field: description
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "(maximum|max|limit).*(size|length|count)"
|
||||
message: "Consider documenting maximum response sizes (OWASP API4:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Implement rate limiting and document limits in API specification
|
||||
- Use pagination for all list operations (limit/offset or cursor-based)
|
||||
- Document maximum request/response sizes
|
||||
- Implement request timeout and maximum execution time limits
|
||||
|
||||
---
|
||||
|
||||
## API8:2023 - Security Misconfiguration
|
||||
|
||||
**Description**: APIs and the systems supporting them typically contain complex configurations, meant to make the APIs more customizable. Software and DevOps engineers can miss these configurations, or don't follow security best practices when it comes to configuration, opening the door for different types of attacks.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api8.yaml
|
||||
rules:
|
||||
# Require HTTPS for all servers
|
||||
servers-use-https:
|
||||
description: All API servers must use HTTPS
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^https://"
|
||||
message: "Server URLs must use HTTPS protocol for secure communication (OWASP API8:2023)"
|
||||
|
||||
# Detect example.com in server URLs
|
||||
no-example-servers:
|
||||
description: Replace example server URLs with actual endpoints
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "example\\.com"
|
||||
message: "Replace example.com with actual server URL (OWASP API8:2023)"
|
||||
|
||||
# Require security headers documentation
|
||||
security-headers-documented:
|
||||
description: Document security headers in responses
|
||||
severity: warn
|
||||
given: $.paths[*][*].responses[*].headers
|
||||
then:
|
||||
function: schema
|
||||
functionOptions:
|
||||
schema:
|
||||
type: object
|
||||
anyOf:
|
||||
- required: [X-Content-Type-Options]
|
||||
- required: [X-Frame-Options]
|
||||
- required: [Strict-Transport-Security]
|
||||
message: "Document security headers (X-Content-Type-Options, X-Frame-Options, HSTS) in responses (OWASP API8:2023)"
|
||||
|
||||
# CORS configuration review
|
||||
cors-documented:
|
||||
description: CORS should be properly configured and documented
|
||||
severity: info
|
||||
given: $.paths[*].options
|
||||
then:
|
||||
- field: responses
|
||||
function: truthy
|
||||
message: "Ensure CORS is properly configured - review Access-Control-* headers (OWASP API8:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Use HTTPS for all API endpoints
|
||||
- Configure and document security headers (HSTS, X-Content-Type-Options, X-Frame-Options)
|
||||
- Properly configure CORS with specific origins (avoid wildcard in production)
|
||||
- Disable unnecessary HTTP methods
|
||||
- Remove verbose error messages in production
|
||||
|
||||
---
|
||||
|
||||
## API9:2023 - Improper Inventory Management
|
||||
|
||||
**Description**: APIs tend to expose more endpoints than traditional web applications, making proper and updated documentation highly important. A proper inventory of hosts and deployed API versions also are important to mitigate issues such as deprecated API versions and exposed debug endpoints.
|
||||
|
||||
### Spectral Rules
|
||||
|
||||
```yaml
|
||||
# .spectral-api9.yaml
|
||||
rules:
|
||||
# Require API version
|
||||
api-version-required:
|
||||
description: API specification must include version
|
||||
severity: error
|
||||
given: $.info
|
||||
then:
|
||||
- field: version
|
||||
function: truthy
|
||||
message: "API version must be specified for proper inventory management (OWASP API9:2023)"
|
||||
|
||||
# Version format validation
|
||||
semantic-versioning:
|
||||
description: Use semantic versioning for API versions
|
||||
severity: warn
|
||||
given: $.info.version
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^\\d+\\.\\d+\\.\\d+"
|
||||
message: "Use semantic versioning (MAJOR.MINOR.PATCH) for API versions (OWASP API9:2023)"
|
||||
|
||||
# Require contact information
|
||||
contact-info-required:
|
||||
description: API must include contact information
|
||||
severity: warn
|
||||
given: $.info
|
||||
then:
|
||||
- field: contact
|
||||
function: truthy
|
||||
message: "Include contact information for API support and security issues (OWASP API9:2023)"
|
||||
|
||||
# Require terms of service or license
|
||||
legal-info-required:
|
||||
description: API should include legal information
|
||||
severity: info
|
||||
given: $.info
|
||||
then:
|
||||
- field: license
|
||||
function: truthy
|
||||
message: "Include license or terms of service for API usage (OWASP API9:2023)"
|
||||
|
||||
# Deprecation documentation
|
||||
deprecated-endpoints-documented:
|
||||
description: Deprecated endpoints must be clearly marked
|
||||
severity: warn
|
||||
given: $.paths[*][*][?(@.deprecated == true)]
|
||||
then:
|
||||
- field: description
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "(deprecate|migrate|alternative|replacement)"
|
||||
message: "Document deprecation details and migration path (OWASP API9:2023)"
|
||||
```
|
||||
|
||||
### Remediation
|
||||
|
||||
- Maintain up-to-date API specification with version information
|
||||
- Use semantic versioning for API versions
|
||||
- Document all endpoints, including internal and deprecated ones
|
||||
- Include contact information for security issues
|
||||
- Implement API inventory management and discovery tools
|
||||
- Remove or properly secure debug/admin endpoints in production
|
||||
|
||||
---
|
||||
|
||||
## Complete OWASP Ruleset Example
|
||||
|
||||
```yaml
|
||||
# .spectral-owasp-complete.yaml
|
||||
extends: ["spectral:oas"]
|
||||
|
||||
rules:
|
||||
# API1: Broken Object Level Authorization
|
||||
operation-security-defined:
|
||||
severity: error
|
||||
message: "All operations must have security defined (OWASP API1:2023)"
|
||||
|
||||
# API2: Broken Authentication
|
||||
no-http-basic-auth:
|
||||
description: Prohibit HTTP Basic authentication
|
||||
severity: error
|
||||
given: $.components.securitySchemes[*]
|
||||
then:
|
||||
field: scheme
|
||||
function: pattern
|
||||
functionOptions:
|
||||
notMatch: "^basic$"
|
||||
message: "HTTP Basic auth is insecure (OWASP API2:2023)"
|
||||
|
||||
# API3: Broken Object Property Level Authorization
|
||||
no-additional-properties:
|
||||
description: Prevent mass assignment
|
||||
severity: warn
|
||||
given: $.components.schemas[?(@.type == 'object')]
|
||||
then:
|
||||
field: additionalProperties
|
||||
function: falsy
|
||||
message: "Set additionalProperties to false (OWASP API3:2023)"
|
||||
|
||||
# API4: Unrestricted Resource Consumption
|
||||
pagination-for-lists:
|
||||
description: List operations should support pagination
|
||||
severity: warn
|
||||
given: $.paths[*].get
|
||||
then:
|
||||
function: truthy
|
||||
message: "Implement pagination for list operations (OWASP API4:2023)"
|
||||
|
||||
# API8: Security Misconfiguration
|
||||
servers-use-https:
|
||||
description: All servers must use HTTPS
|
||||
severity: error
|
||||
given: $.servers[*].url
|
||||
then:
|
||||
function: pattern
|
||||
functionOptions:
|
||||
match: "^https://"
|
||||
message: "Server URLs must use HTTPS (OWASP API8:2023)"
|
||||
|
||||
# API9: Improper Inventory Management
|
||||
api-version-required:
|
||||
description: API must specify version
|
||||
severity: error
|
||||
given: $.info
|
||||
then:
|
||||
field: version
|
||||
function: truthy
|
||||
message: "API version is required (OWASP API9:2023)"
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [OWASP API Security Top 10 2023](https://owasp.org/API-Security/editions/2023/en/0x11-t10/)
|
||||
- [Spectral Rulesets Documentation](https://docs.stoplight.io/docs/spectral/docs/getting-started/rulesets.md)
|
||||
- [OpenAPI Security Best Practices](https://swagger.io/docs/specification/authentication/)
|
||||
Reference in New Issue
Block a user