Security Testing Fundamentals — OWASP Top 10 and the QA Role in AppSec

Security is not just a penetration tester’s job. Every QA engineer interacts with the application’s attack surface daily — forms that accept user input, authentication flows, APIs that return sensitive data, and file upload features. The OWASP Top 10 catalogues the most critical web application security risks, and many of these risks can be detected through targeted QA test cases. Understanding these vulnerabilities transforms a QA engineer from someone who verifies features into someone who protects users.

OWASP Top 10 — The Security Risks QA Must Know

The OWASP Top 10 is updated periodically. The 2021 edition (current through 2025-2026) identifies these risks.

# OWASP Top 10 (2021) with QA testing relevance

OWASP_TOP_10 = [
    {
        "rank": "A01",
        "name": "Broken Access Control",
        "description": "Users can act outside their intended permissions",
        "qa_test": "Log in as a regular user, try accessing admin URLs directly (/admin/users). "
                   "Try modifying another user's data by changing IDs in API requests.",
        "example": "Change /api/orders/123 to /api/orders/456 — can you see another user's order?",
    },
    {
        "rank": "A02",
        "name": "Cryptographic Failures",
        "description": "Sensitive data exposed due to weak or missing encryption",
        "qa_test": "Check if passwords are visible in API responses. Verify HTTPS is enforced. "
                   "Check if sensitive data appears in URL query strings or browser history.",
        "example": "Does the login API response include the password? Is the session token in the URL?",
    },
    {
        "rank": "A03",
        "name": "Injection",
        "description": "Untrusted data sent to an interpreter (SQL, OS, LDAP)",
        "qa_test": "Enter SQL injection payloads in form fields and search bars. "
                   "Check if the application sanitises special characters.",
        "example": "Type ' OR 1=1 -- in the login username field. Does it bypass authentication?",
    },
    {
        "rank": "A04",
        "name": "Insecure Design",
        "description": "Missing or ineffective security controls in the design",
        "qa_test": "Check for rate limiting on login (can you brute force?). "
                   "Verify password complexity requirements. Check account lockout.",
        "example": "Submit 100 login attempts in 10 seconds — does the application throttle or lock?",
    },
    {
        "rank": "A05",
        "name": "Security Misconfiguration",
        "description": "Default configs, verbose errors, unnecessary features enabled",
        "qa_test": "Check error pages for stack traces. Look for default credentials. "
                   "Verify that debug endpoints are disabled in production.",
        "example": "Does a 500 error show the full stack trace with file paths and database names?",
    },
    {
        "rank": "A06",
        "name": "Vulnerable and Outdated Components",
        "description": "Using libraries with known security vulnerabilities",
        "qa_test": "Run npm audit or pip audit on the project. Check for CVEs in dependencies.",
        "example": "Is the project using a version of log4j with the known RCE vulnerability?",
    },
    {
        "rank": "A07",
        "name": "Identification and Authentication Failures",
        "description": "Weak authentication, session management, or credential handling",
        "qa_test": "Test session expiry. Check if sessions persist after logout. "
                   "Verify password reset flow does not leak information.",
        "example": "After logout, press browser back button — can you still see the dashboard?",
    },
    {
        "rank": "A08",
        "name": "Software and Data Integrity Failures",
        "description": "Code or data integrity not verified (insecure CI/CD, deserialization)",
        "qa_test": "Verify that critical data changes (price, quantity) cannot be manipulated client-side.",
        "example": "Modify the price field in a POST /api/orders request — does the server validate it?",
    },
    {
        "rank": "A09",
        "name": "Security Logging and Monitoring Failures",
        "description": "Insufficient logging of security events, no alerting",
        "qa_test": "Trigger failed login attempts — verify they appear in security logs. "
                   "Check if admin actions are logged with user identity and timestamp.",
        "example": "After 10 failed logins, is there a log entry? Is the security team alerted?",
    },
    {
        "rank": "A10",
        "name": "Server-Side Request Forgery (SSRF)",
        "description": "Application fetches a remote resource without validating the URL",
        "qa_test": "If the app has a 'fetch URL' feature, try internal URLs (http://localhost, http://169.254.169.254).",
        "example": "Can you make the server request its own metadata endpoint via a URL input field?",
    },
]

print("OWASP Top 10 — QA Testing Guide")
print("=" * 65)
for item in OWASP_TOP_10:
    print(f"\n  {item['rank']}: {item['name']}")
    print(f"    Risk: {item['description']}")
    print(f"    QA test: {item['qa_test']}")
    print(f"    Example: {item['example']}")
Note: QA engineers are not expected to perform full penetration testing — that requires specialised security expertise and dedicated tools. However, QA engineers interact with every form field, every API endpoint, and every authentication flow during functional testing. Adding basic security awareness to that testing — trying a SQL injection string in a search field, checking if admin URLs are accessible as a regular user, verifying session expiry — catches low-hanging security fruit that functional tests miss entirely. This “security-aware QA” approach catches 20-30% of common vulnerabilities at zero additional cost.
Tip: Add a “security checklist” section to your test case templates. For every feature, ask: “What happens if the user manipulates the input?”, “What happens if the user accesses URLs they should not?”, “What happens if the user replays or modifies API requests?” These three questions surface the majority of access control and injection vulnerabilities that QA can detect.
Warning: Never run security tests against production systems without explicit written authorisation. SQL injection attempts, brute force login tests, and vulnerability scans can trigger security alerts, lock accounts, and potentially cause data corruption. Always test against staging or dedicated security testing environments. Unauthorised security testing — even with good intentions — can violate computer fraud laws.

Common Mistakes

Mistake 1 — Assuming security is only the security team’s responsibility

❌ Wrong: “Security testing is handled by the pen testers. QA only does functional testing.”

✅ Correct: “QA incorporates security-aware testing into functional test cases — checking access control, input validation, and session management during every sprint. Dedicated pen testers perform deeper security audits quarterly.”

Mistake 2 — Testing only happy-path inputs without adversarial data

❌ Wrong: Testing a search field with “laptop” but never with <script>alert(1)</script> or ' OR 1=1 --.

✅ Correct: Including adversarial inputs — HTML tags, SQL fragments, JavaScript payloads, excessively long strings — in every input field test to verify the application handles them safely.

🧠 Test Yourself

You log in as a regular user and change the URL from /api/orders/123 (your order) to /api/orders/456 (another user’s order) — and the API returns the other user’s data. Which OWASP Top 10 vulnerability is this?