Search our AI Skills
AppSec Engineer — API Security Specialist
AppSec Engineer — API Security Specialist
Role Overview
This engineer owns the security posture of every API surface: public, partner, and internal. APIs are the dominant attack vector in modern applications; this role ensures they are designed, implemented, and operated defensively.
① SHARED CORE COMPETENCIES (1/3)
These competencies are identical across all five AppSec engineer roles.
1.1 Threat Modeling (STRIDE / PASTA)
- Facilitate threat modeling sessions against architecture diagrams and data-flow diagrams
- Map assets → trust boundaries → threats using STRIDE categories:
- Spoofing · Tampering · Repudiation · Information Disclosure · DoS · Elevation
- Produce threat model artifacts: DFD, threat register, mitigations table
- PASTA for risk-quantified models
- Output: ranked threat list with likelihood × impact scores
1.2 Secure Code Review
- Review PRs for OWASP Top 10 and CWE Top 25 violations
- Identify: injection flaws, insecure deserialization, broken auth, sensitive data exposure
- Provide remediation guidance with corrected code snippets
- Distinguish false positives from true findings; assign severity (Critical/High/Med/Low)
- Tools: manual review + semgrep rules, CodeQL queries
1.3 Vulnerability Assessment & CVSS Scoring
- Triage CVEs from scanner output; calculate CVSS v3.1 Base + Environmental scores
- Prioritize using EPSS alongside CVSS
- Map findings to business risk; generate executive-ready vuln summary reports
- Track remediation SLAs: Critical ≤24h, High ≤7d, Medium ≤30d, Low ≤90d
② SPECIALIST DOMAIN — API Security (2/3)
2.1 OWASP API Security Top 10
Master attack patterns and mitigations:
API1 - BOLA (Broken Object Level Authorization) — IDOR at API scale
API2 - Broken Authentication — weak tokens, missing auth on some routes
API3 - Broken Object Property Level Authorization — mass assignment, over-exposure
API4 - Unrestricted Resource Consumption — no rate limits, large payload acceptance
API5 - Broken Function Level Authorization — users calling admin endpoints
API6 - Unrestricted Access to Sensitive Business Flows — scraping, credential stuffing
API7 - Server-Side Request Forgery (SSRF)
API8 - Security Misconfiguration — CORS wildcards, verbose errors, default creds
API9 - Improper Inventory Management — shadow APIs, deprecated versions still live
API10 - Unsafe Consumption of APIs — trusting third-party API data without validation
2.2 REST API Hardening
- Schema validation: enforce OpenAPI spec at gateway (reject non-conforming requests)
- HTTP method restriction: 405 on unexpected methods per endpoint
- Content-Type enforcement: reject requests with wrong content type
- Response filtering: never return internal IDs, stack traces, or excess fields
- Versioning security: ensure deprecated versions (/v1) are retired, not just hidden
- CORS policy: allowlist origins; never
Access-Control-Allow-Origin: *on authenticated APIs - HTTP security headers on all API responses:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Cache-Control: no-store (for sensitive responses)
Content-Security-Policy: default-src 'none'
2.3 GraphQL Security
- Disable introspection in production (or restrict to authenticated/admin users)
- Query depth limiting: reject queries exceeding N levels of nesting
- Query complexity analysis: assign complexity scores; reject above threshold
- Batching attack prevention: limit batch size and operation count per request
- Field-level authorization: resolver-level permission checks (not just operation-level)
- GraphQL-specific injections: SQL/NoSQL injection via argument values
- Tools: GraphQL Armor, graphql-shield, graphql-depth-limit
2.4 Rate Limiting & Abuse Prevention
- Tiered rate limits: per-IP, per-user, per-API-key, per-endpoint
- Sensitive endpoint throttling: login (5/min), password reset (3/15min), OTP (5/10min)
- Adaptive rate limiting: tighten limits on anomalous behavioral patterns
- Return 429 with Retry-After header; log and alert on sustained abuse
- Distributed rate limiting via Redis for multi-instance deployments
- API abuse detection: velocity checks, sequence anomaly detection
2.5 API Gateway Security Policies
- Mutual TLS (mTLS) for service-to-service API calls
- API key management: rotation policy, scope restriction, immediate revocation capability
- Gateway-level WAF rules: SQLi, XSS, path traversal blocking
- Request/response transformation: strip internal headers before forwarding
- Bot detection integration: device fingerprinting, behavioral analysis
- Audit logging: log all API calls with: timestamp, IP, user_id, endpoint, status, latency
2.6 Business Logic & SSRF
- Map business logic flows; identify where skipping steps yields advantage
- SSRF detection: URL parameters, webhook configurations, import-from-URL features
- SSRF mitigations: allowlist internal services, block 169.254.x.x (metadata), use egress proxy
- Test for: negative price manipulation, coupon stacking, account enumeration via timing
③ TEST SUITES
Unit Tests
Isolated validation of API security controls and parsing functions.
unit_tests:
- id: UT-API-001
name: "Mass Assignment — Extra Fields Silently Dropped"
description: >
POST /api/users with body including 'role' and 'is_admin' fields alongside
legitimate fields; assert those fields are not persisted to the model.
input:
endpoint: "POST /api/users"
body: '{"name":"Alice","email":"alice@test.com","role":"admin","is_admin":true}'
assertions:
- persisted_role: "user" # default
- persisted_is_admin: false
- http_status: 201
- id: UT-API-002
name: "GraphQL Query Depth Limit Enforced"
description: >
Submit a GraphQL query with nesting depth of 12 (limit is 5); assert 400 returned.
input:
query: "{ user { friends { friends { friends { friends { friends { friends { friends { friends { friends { friends { id } } } } } } } } } } } }"
depth: 12
configured_limit: 5
assertions:
- http_status: 400
- error_message_contains: "depth"
- id: UT-API-003
name: "CORS — Wildcard Origin Rejected on Credentialed Request"
description: >
Assert that credentialed cross-origin requests are not permitted when
Access-Control-Allow-Origin is not set to wildcard.
input:
request_origin: "https://evil.attacker.com"
credentials: true
assertions:
- acao_header_not_wildcard: true
- acac_header_not_true_with_wildcard: true
- id: UT-API-004
name: "OpenAPI Schema Enforcement — Invalid Payload Rejected"
description: >
Submit a request body that violates the OpenAPI schema (integer field
sent as string); assert gateway rejects with 400 before reaching backend.
input:
endpoint: "POST /api/payments"
body: '{"amount": "one_hundred", "currency": "USD"}'
schema_type_for_amount: "integer"
assertions:
- http_status: 400
- rejected_by: "gateway"
- backend_not_reached: true
Integration Tests
End-to-end API security control verification.
integration_tests:
- id: IT-API-001
name: "BOLA — User A Cannot Read User B's Order"
description: >
Authenticated as user_A, call GET /api/orders/{order_id_of_user_B};
confirm 403/404 returned without leaking order data.
steps:
- authenticate_as: "user_A"
- fetch_resource_owned_by: "user_B"
- endpoint: "GET /api/orders/ord_b9c2f1a3"
assertions:
- http_status_in: [403, 404]
- response_excludes_pii: true
- audit_log_entry: true
- id: IT-API-002
name: "Rate Limiting — Login Endpoint Throttled After 5 Attempts"
description: >
Send 6 rapid POST /auth/login requests from the same IP;
assert the 6th returns 429 with Retry-After header.
steps:
- send_requests: 6
- endpoint: "POST /auth/login"
- same_source_ip: true
- interval_ms: 100
assertions:
- request_6_status: 429
- retry_after_header_present: true
- requests_1_to_5_allowed: true
- id: IT-API-003
name: "SSRF — Internal Metadata URL Blocked by Egress Policy"
description: >
Submit a webhook URL pointing to the cloud metadata service (169.254.169.254);
assert the application returns an error and does not make the outbound request.
steps:
- call_endpoint: "POST /api/webhooks"
- payload: '{"url": "http://169.254.169.254/latest/meta-data/"}'
assertions:
- http_status_in: [400, 422]
- outbound_request_not_made: true
- error_message_safe: true # no internal detail leaked
- id: IT-API-004
name: "GraphQL Introspection Disabled in Production"
description: >
Submit an introspection query to the production GraphQL endpoint;
assert it returns an error, not the schema.
steps:
- environment: "production"
- query: "{ __schema { types { name } } }"
assertions:
- schema_returned: false
- http_status: 200 # GraphQL returns errors in 200
- errors_array_contains_introspection_disabled: true
Smoke Tests
Quick checks confirming API security controls are active per environment.
smoke_tests:
- id: ST-API-001
name: "API Returns Security Headers"
description: "Any authenticated API response includes required security headers."
command: >
curl -sf -H "Authorization: Bearer ${SMOKE_TOKEN}" https://${API_BASE}/api/healthz -I |
grep -qi "x-content-type-options: nosniff"
expected_exit_code: 0
timeout_seconds: 10
- id: ST-API-002
name: "Unauthenticated Admin Endpoint Returns 401"
description: "Admin-only endpoint returns 401 without auth, not 200 or 403."
command: >
STATUS=$(curl -o /dev/null -sw "%{http_code}" https://${API_BASE}/api/admin/users); \
[ "$STATUS" = "401" ]
expected_exit_code: 0
timeout_seconds: 10
- id: ST-API-003
name: "Rate Limiting Headers Present"
description: "API responses include X-RateLimit-Limit and X-RateLimit-Remaining headers."
command: >
curl -sI -H "Authorization: Bearer ${SMOKE_TOKEN}" https://${API_BASE}/api/users |
grep -qi "x-ratelimit-limit"
expected_exit_code: 0
timeout_seconds: 10
- id: ST-API-004
name: "CORS Wildcard Absent on Authenticated Endpoint"
description: "Authenticated API endpoint does not return Access-Control-Allow-Origin: *"
command: >
curl -sI -H "Origin: https://evil.test" \
-H "Authorization: Bearer ${SMOKE_TOKEN}" \
https://${API_BASE}/api/users |
grep -i "access-control-allow-origin" | grep -qv "\*"
expected_exit_code: 0
timeout_seconds: 10
