Search our AI Skills
AppSec Engineer — Security Testing & Incident Response Specialist
AppSec Engineer — Security Testing & Incident Response Specialist
Role Overview
This engineer finds what others miss by attacking systems deliberately, and contains damage when attackers find it first. They bridge offensive security techniques with defensive operations — making testing rigorous and incident response surgical.
① 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 — Security Testing & Incident Response (2/3)
2.1 Penetration Testing Methodology
- Phases: Reconnaissance → Enumeration → Exploitation → Post-Exploitation → Reporting
- Scope documentation: rules of engagement, IP ranges, excluded systems, emergency contacts
- Web application pen test checklist (OWASP WSTG coverage):
Auth testing: default creds, brute force, account lockout, MFA bypass
Session: session fixation, token entropy, concurrent sessions
Input: SQLi, XSS (reflected/stored/DOM), XXE, SSTI, SSRF
Access control: IDOR, privilege escalation, forced browsing, CORS
Cryptography: weak cipher, self-signed cert, mixed content
Config: directory listing, error disclosure, HTTP methods
- Automated + manual: Burp Suite Pro, Nuclei templates, custom exploit scripts
- Purple team exercises: structured attack scenarios with blue team detection validation
2.2 Fuzzing & Property-Based Testing
- Coverage-guided fuzzing: AFL++, libFuzzer for C/C++; Atheris for Python; go-fuzz for Go
- Smart fuzzing: Boofuzz for protocol fuzzing; RESTler for REST API stateful fuzzing
- Corpus building: extract real-world inputs from logs, documentation, production traffic samples
- Crash triage: deduplicate by stack trace; prioritize reachable crashes; assess exploitability
- Property-based testing: Hypothesis (Python), fast-check (JS), proptest (Rust)
- Define invariants: “no user can read data of a different tenant”, “output is always sanitized”
- Generate edge-case inputs: null bytes, Unicode boundary characters, max-length strings
2.3 DAST & Continuous Security Testing
- OWASP ZAP: baseline scan in CI, full scan in staging, authenticated scan for protected paths
- Burp Suite Enterprise: scheduled scans, API scan, CI/CD integration via REST API
- Nuclei: community and custom templates; run on every deploy for high-signal checks
- Security regression suite: after every fix, write a test case that would have caught the bug
- Test coverage tracking: map OWASP Top 10 categories to test coverage %; surface gaps
2.4 Application Security Incident Response
Triage protocol (first 15 minutes):
1. Classify: Is this exploitation in progress, post-exploitation, or reconnaissance?
2. Scope: Which endpoints/users/data affected? Estimated blast radius?
3. Contain: Can we block the attacker IP/token/session without impacting legit users?
4. Preserve: Capture logs, memory dumps, network captures before rollback/restart
5. Notify: Trigger security incident runbook; loop in legal/privacy if PII involved
Evidence preservation:
- Application logs: request logs, error logs, auth logs with full headers
- Infrastructure: VPC flow logs, WAF logs, load balancer access logs
- Correlation: stitch together attacker session across services using request IDs
Containment options by attack type:
Credential stuffing: block IP ranges, enforce CAPTCHA, force password reset
SQL injection: WAF virtual patch, block specific payload patterns
Account takeover: invalidate all sessions for affected users, MFA enforcement
Data exfiltration: block egress to attacker IPs, rate-limit data export endpoints
2.5 Forensics & Root Cause Analysis
- Reconstruct attack timeline from logs: first probe → exploitation → exfiltration
- Identify: initial access vector, credential access, lateral movement, persistence mechanisms
- Determine: was data accessed or exfiltrated? What specific records?
- Forensic artifacts: HTTP request reconstruction, database query logs, file access logs
- Root cause categories: design flaw, implementation bug, configuration error, missing control
2.6 Threat Hunting in Application Logs
- Hunt for: authentication anomalies, unusual API call sequences, encoding obfuscation
- Detection patterns:
SQLi patterns: ' OR 1=1, UNION SELECT, SLEEP(), BENCHMARK()
XSS attempts: <script, onerror=, javascript:, data:text/html
Path traversal: ../../../, %2e%2e%2f, ..%5c
SSRF probes: 169.254., 127.0.0.1, internal.corp DNS names in URL params
- Build detection rules: Splunk SPL, Elastic ESQL, Datadog log monitors
- Baseline normal behavior; alert on statistically significant deviations
③ TEST SUITES
Unit Tests
Isolated verification of security test logic, detection functions, and parsers.
unit_tests:
- id: UT-STIR-001
name: "SQLi Detection Regex — True Positive / True Negative"
description: >
The SQL injection detection function must flag canonical attack strings
and NOT flag legitimate query parameters.
input:
true_positive_payloads:
- "' OR '1'='1"
- "1; DROP TABLE users--"
- "' UNION SELECT null,null,null--"
true_negative_payloads:
- "John O'Brien" # legitimate apostrophe
- "SELECT all items" # natural language
- "1000"
assertions:
- all_true_positives_detected: true
- false_positive_count: 0
- id: UT-STIR-002
name: "CVSS Temporal Score with Exploit Code Maturity"
description: >
Given a Critical base score and 'Proof-of-Concept' exploit code maturity,
assert that the temporal score is correctly downgraded from base.
input:
base_vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"
temporal_vector: "E:P/RL:O/RC:C"
assertions:
- temporal_score_lt_base_score: true
- temporal_score_in_range: [8.0, 9.0]
- id: UT-STIR-003
name: "Fuzzer Corpus Deduplication by Stack Trace"
description: >
Given 10 crash reports where 7 share identical stack traces,
the deduplication function returns 3 unique crash buckets.
input:
crash_reports: "tests/fixtures/crash_corpus_10.json"
assertions:
- unique_buckets: 3
- deduplication_method: "stack_trace_hash"
- id: UT-STIR-004
name: "Log Parser — Attack Timeline Reconstruction"
description: >
Given a fixture log file containing a simulated SQLi attack sequence,
the parser must identify all attacker requests in correct chronological order.
input:
log_fixture: "tests/fixtures/sqli_attack_log.json"
attacker_ip: "198.51.100.7"
assertions:
- events_detected: 14
- first_event_type: "reconnaissance"
- last_event_type: "data_extraction"
- timeline_in_order: true
Integration Tests
End-to-end verification of detection pipelines and IR workflows.
integration_tests:
- id: IT-STIR-001
name: "WAF Rule Blocks Known SQLi Payload"
description: >
Send a GET request with a known SQL injection payload in the query string;
assert the WAF intercepts and returns 403 before the request reaches the app.
steps:
- endpoint: "GET /api/search?q=1'+OR+'1'%3D'1"
- bypass_app_directly: false
assertions:
- http_status: 403
- waf_block_header_present: true
- backend_request_count: 0
- waf_log_entry_created: true
environment: "staging-with-waf"
- id: IT-STIR-002
name: "Security Incident Runbook — Session Invalidation Flow"
description: >
Simulate a compromised user session; trigger the incident runbook;
assert all active sessions for that user are invalidated within 60 seconds.
steps:
- create_test_sessions: 5
- trigger_incident_runbook: "compromised_account"
- target_user: "test_victim@example.com"
- wait_seconds: 60
assertions:
- active_sessions_after: 0
- audit_log_records_invalidation: true
- user_notified_via_email: true
- id: IT-STIR-003
name: "RESTler Fuzzer — No 500 Errors on Discovered Paths"
description: >
Run RESTler in BFS mode against the staging API for 10 minutes;
assert zero 500 responses are returned (unhandled errors = potential vuln).
steps:
- tool: "RESTler"
- mode: "BFS"
- target: "https://api-staging.internal/api"
- duration_minutes: 10
- openapi_spec: "docs/openapi.yaml"
assertions:
- http_500_count: 0
- unhandled_exception_count: 0
- coverage_percentage_gte: 70
- id: IT-STIR-004
name: "XSS Detection Rule Fires in SIEM"
description: >
Send a request containing an XSS payload to the application; assert that
within 2 minutes a SIEM alert is generated and tagged correctly.
steps:
- send_request_with_payload: '<script>alert(1)</script>'
- endpoint: "POST /api/comments"
- wait_for_siem_alert_minutes: 2
assertions:
- alert_generated: true
- alert_category: "web_attack_xss"
- alert_severity_gte: "medium"
Smoke Tests
Rapid verification that security testing infrastructure and alerting are operational.
smoke_tests:
- id: ST-STIR-001
name: "Nuclei Scanner Operational and Templates Current"
description: "Nuclei CLI responds, templates are ≤7 days old, and critical templates load."
command: >
nuclei -version && \
find ~/.local/nuclei-templates -newer ~/.local/nuclei-templates/.git/FETCH_HEAD \
-name "*.yaml" | wc -l | awk '{if($1>0) exit 0; else exit 1}'
expected_exit_code: 0
timeout_seconds: 30
- id: ST-STIR-002
name: "SIEM Webhook Alert Delivery Working"
description: >
Post a test security event to the SIEM ingest endpoint; assert it appears
in the log stream within 60 seconds.
command: >
EVENT_ID="smoke-test-$(date +%s)"; \
curl -sf -X POST ${SIEM_INGEST_URL} \
-H "Authorization: Bearer ${SIEM_TOKEN}" \
-d "{\"event_type\":\"smoke_test\",\"id\":\"${EVENT_ID}\"}"; \
sleep 10; \
curl -sf "${SIEM_SEARCH_URL}?q=${EVENT_ID}" | jq '.total > 0'
expected_output: "true"
timeout_seconds: 60
- id: ST-STIR-003
name: "WAF Is in Blocking Mode (Not Detection-Only)"
description: >
Submit a request with a test WAF bypass string; assert 403 returned
(detection-only mode would return 200).
command: >
STATUS=$(curl -o /dev/null -sw "%{http_code}" \
"https://${APP_BASE}/api/search?q=<script>"); \
[ "$STATUS" = "403" ]
expected_exit_code: 0
timeout_seconds: 10
- id: ST-STIR-004
name: "Incident Runbook Endpoint Reachable"
description: "The security incident automation webhook is reachable and authenticated."
command: >
curl -sf -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${IR_WEBHOOK_TOKEN}" \
${IR_WEBHOOK_URL}/health
expected_output: "200"
timeout_seconds: 10
