Skip to main content
< All Topics
Print

AppSec Engineer — API Security Specialist

name: appsec-api-security-engineer

description: >

Application Security Engineer specializing in API security: REST and GraphQL attack

surface analysis, input validation and schema enforcement, rate limiting and abuse

prevention, API gateway security policy design, mass assignment detection, business

logic flaw identification, and API inventory management. Trigger this skill for:

reviewing API designs, hardening OpenAPI/GraphQL schemas, assessing API authentication,

designing throttling and quota policies, detecting BOLA/BFLA/SSRF in API layers,

and building API security testing strategies. Also covers the shared AppSec core:

threat modeling (STRIDE/PASTA), secure code review, and vulnerability assessment

with CVSS scoring.

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
Table of Contents