Patch Artifact Specification

Definition

A Patch is a structured remediation document that transforms a confirmed vulnerability into durable security improvements. Patches follow the 4V methodology: Verify, Validate, Vaccinate, Valuate.

The 4V methodology ensures that fixes are not just quick patches but systematic improvements:

  • Verify: Confirm the fix works by re-running explorations
  • Validate: Ensure completeness and no regressions
  • Vaccinate: Apply systemic changes to prevent similar issues
  • Valuate: Assess the security improvement's value and capture lessons

Schema: patch.schema.yaml


Required Fields

FieldTypeDescription
idPatchIDUnique identifier following pattern PATCH-<SYSTEM>-<NNN>
finding_refFindingReferenceReference to the finding(s) being patched
root_causeRootCauseAnalysis of the underlying implementation issue
fix_descriptionstringPlain-language description of the changes made
verificationVerification4V Phase 1: How the fix was verified to work

Optional Fields

FieldTypeDefaultDescription
titlestring-Short description of the patch
code_changesCodeChange[]-Specific code changes made
validationValidation-4V Phase 2: Broader validation and regression testing
vaccinationVaccination-4V Phase 3: Systemic changes to prevent recurrence
valuationValuation-4V Phase 4: Value assessment and lessons learned
related_invariantsInvariantID[]-Invariants affected by this patch
statusPatchStatusDRAFTCurrent lifecycle status
created_atdatetime-When the patch was created
completed_atdatetime-When all 4V phases completed

The 4V Methodology

Verify (Phase 1) - REQUIRED

Confirm the fix actually works.

ElementDescription
Re-run explorationsRun the original failing exploration(s) against patched code
Before/after resultsDocument VIOLATED -> HOLDS transition
Additional variationsTest variations of the original exploit
Verified by/atRecord who verified and when

A patch without verification is just a hope.

Validate (Phase 2)

Ensure completeness and no regressions.

ElementDescription
Regression testsTests to prevent reintroduction
Edge casesBoundary conditions and special cases
Integration testsTests across component boundaries
Code reviewReviewers who validated the fix

Vaccinate (Phase 3)

Apply systemic changes that prevent similar vulnerabilities.

Change TypeExample
middlewareCentralized authorization middleware
libraryShared ownership check library
frameworkFramework-level security defaults
patternDocumented secure coding pattern
configurationSecurity-hardened default config
lintingStatic analysis rules
trainingDeveloper security training
noneSingle instance, no systemic fix needed

Vaccination turns individual fixes into organizational learning.

Valuate (Phase 4)

Assess the security improvement's value.

ElementDescription
MetricsQuantitative measures (coverage, blocked attempts)
Status overlay updatesUpdate invariant enforcement status
Lessons learnedWhat we learned from this vulnerability
RecommendationsFuture prevention strategies
Business impactValue delivered to the organization

Field Details

finding_ref

Links the patch to the original finding:

yaml
finding_ref:
  finding_id: FD-SHOP-AUTHZ-001
  invariant: INV-SHOP-OWNER-DELETE
  scenario: S-SHOP-IDOR-DELETE-001
  exploration: E-SHOP-IDOR-DELETE-001-01
  impact: "Any authenticated user could delete items belonging to other users"

root_cause

Explains WHY the vulnerability exists:

yaml
root_cause:
  issue: |
    The delete endpoint extracted item_id from the URL but did not verify
    that the authenticated user owned the item before deletion. The ownership
    check was accidentally removed during refactoring in commit abc123.
  code_locations:
    - file: "src/api/items.py"
      line: 42
      function: "delete_item"
      snippet: "item = Item.query.get(item_id)  # Missing: check user == item.owner"
  pattern: "Missing authorization check on resource operations"
  contributing_factors:
    - "No unit test for ownership verification"
    - "Code review did not catch missing check"
    - "Authorization logic not centralized"

verification

The critical first phase of 4V:

yaml
verification:
  explorations_rerun:
    - exploration_id: E-SHOP-IDOR-DELETE-001-01
      result_before: VIOLATED
      result_after: HOLDS
      notes: "UserB can no longer delete UserA's items"
    - exploration_id: E-SHOP-IDOR-DELETE-001-02
      result_before: VIOLATED
      result_after: HOLDS
      notes: "Verified with admin user as well"
  additional_tests:
    - "Tested with edge case: owner deleting own item (should succeed)"
    - "Tested with non-existent item_id (should 404, not leak info)"
  verified_by: "security-team"
  verified_at: "2024-01-15T14:30:00Z"

Key Patterns

  • Root cause, not symptoms. Describe why the vulnerability exists, not what the vulnerability is. "Missing ownership check" is better than "IDOR vulnerability."

  • Verification is mandatory. Every patch must include re-run exploration results. Without verification, the patch is just a hypothesis.

  • Vaccination amplifies value. Individual fixes have linear value; systemic fixes have multiplicative value. Always consider vaccination.

  • Update status overlay. When a patch completes, update the invariant status overlay to reflect the new enforcement status.


Common Mistakes

MistakeProblemFix
[ ] No verificationCannot confirm fix actually worksAlways re-run explorations, document before/after
[ ] Symptom-level root cause"There was a bug" - not actionableExplain why the bug existed, what allowed it
[ ] Missing code locationsOthers cannot find or verify the fixInclude specific file:line references
[ ] No vaccinationSame bug will recur elsewhereConsider systemic fixes even if fix is local
[ ] Empty valuationMiss learning opportunityCapture lessons learned, update metrics
[ ] Status overlay not updatedStale enforcement status misleads teamsUpdate overlay when fix is verified

Example: PATCH-SHOP-001

yaml
id: PATCH-SHOP-001
title: "Fix ownership checks on item delete()"
 
finding_ref:
  finding_id: FD-SHOP-AUTHZ-001
  invariant: INV-SHOP-OWNER-DELETE
  scenario: S-SHOP-IDOR-DELETE-001
  exploration: E-SHOP-IDOR-DELETE-001-01
  impact: "Any authenticated user could delete items belonging to other users"
 
root_cause:
  issue: |
    The delete_item endpoint extracted item_id from the URL path but did not
    verify that the authenticated user owned the item before deletion. The
    ownership check was present in the update endpoint but missing from delete.
  code_locations:
    - file: "src/api/items.py"
      line: 42
      function: "delete_item"
      snippet: |
        @app.route('/items/<item_id>', methods=['DELETE'])
        def delete_item(item_id):
            item = Item.query.get(item_id)
            # BUG: Missing ownership check here
            db.session.delete(item)
  pattern: "Missing authorization check on destructive operations"
  contributing_factors:
    - "Copy-paste from read endpoint without auth check"
    - "No integration test for ownership on delete"
 
fix_description: |
  Added ownership verification to the delete_item endpoint. Before deleting,
  the endpoint now checks that the authenticated user's ID matches the item's
  owner_id. Returns 403 Forbidden if the user is not the owner.
 
code_changes:
  - file: "src/api/items.py"
    description: "Added ownership check before delete"
    change_type: modified
    commit: "abc123def456"
    pull_request: "https://github.com/example/shop/pull/42"
  - file: "tests/test_items.py"
    description: "Added integration test for ownership on delete"
    change_type: modified
 
verification:
  explorations_rerun:
    - exploration_id: E-SHOP-IDOR-DELETE-001-01
      result_before: VIOLATED
      result_after: HOLDS
      notes: "UserB receives 403 when trying to delete UserA's items"
    - exploration_id: E-SHOP-IDOR-DELETE-001-02
      result_before: VIOLATED
      result_after: HOLDS
      notes: "Admin user also cannot delete non-owned items"
  additional_tests:
    - "Owner successfully deletes own item"
    - "Non-existent item returns 404"
    - "Unauthenticated request returns 401"
  verified_by: "security-team"
  verified_at: "2024-01-15T14:30:00Z"
 
validation:
  regression_tests:
    - "test_delete_own_item_succeeds"
    - "test_delete_other_user_item_forbidden"
    - "test_delete_nonexistent_item_not_found"
  edge_cases:
    - "Item with no owner field (legacy data)"
    - "Concurrent delete requests"
  reviewed_by:
    - "alice@example.com"
    - "bob@example.com"
 
vaccination:
  change_type: middleware
  description: |
    Created centralized @require_ownership decorator that can be applied to
    any endpoint that operates on owned resources. This decorator extracts
    the resource ID, loads the resource, and verifies ownership before
    allowing the request to proceed.
  new_invariants: []
  strengthened_invariants:
    - INV-SHOP-OWNER-DELETE
  automation:
    - "Added linting rule to flag endpoints without @require_auth or @require_ownership"
  scope: "All shop resource endpoints"
 
valuation:
  metrics:
    blocked_exploit_attempts: 0
    test_coverage_increase: "15%"
    endpoints_protected: 12
  status_overlay_updates:
    - invariant: INV-SHOP-OWNER-DELETE
      scope: "/api/items/*"
      previous_status: KNOWN_MISSING
      new_status: KNOWN_PRESENT
      evidence: "E-SHOP-IDOR-DELETE-001-01 now passes"
  lessons_learned:
    - "Destructive operations need explicit ownership checks"
    - "Copy-paste of endpoints should trigger auth review"
    - "Centralized auth middleware prevents omission"
  recommendations:
    - "Require ownership decorator for all CRUD operations"
    - "Add pre-commit hook for auth decorator linting"
 
related_invariants:
  - INV-SHOP-OWNER-DELETE
  - INV-SHOP-AUTH-REQUIRED
 
status: COMPLETE
created_at: "2024-01-14T10:00:00Z"
completed_at: "2024-01-16T09:00:00Z"

Validation Criteria

A valid patch artifact MUST:

  1. Have a unique ID matching pattern PATCH-<SYSTEM>-<NNN>
  2. Reference a finding with at minimum finding_id and invariant
  3. Have a root cause with a non-empty issue description
  4. Have a fix description explaining what was changed
  5. Have verification with at least one exploration result showing before/after

Verification Requirements

RequirementValidInvalid
Has explorations_rerunArray with 1+ itemsEmpty array or missing
Before stateVIOLATED or UNKNOWNHOLDS (wasn't broken?)
After stateHOLDSVIOLATED (fix didn't work)

Patch Lifecycle

code
DRAFT -> IN_PROGRESS -> VERIFICATION -> VALIDATION -> VACCINATION -> VALUATION -> COMPLETE
                              |               |             |             |
                              v               v             v             v
                           Verify          Validate     Vaccinate      Valuate
                        (Required)        (Optional)   (Recommended)  (Recommended)
  1. DRAFT: Patch document created, not yet started
  2. IN_PROGRESS: Fix being implemented
  3. VERIFICATION: Re-running explorations (4V Phase 1)
  4. VALIDATION: Regression testing and code review (4V Phase 2)
  5. VACCINATION: Applying systemic fixes (4V Phase 3)
  6. VALUATION: Assessing value and lessons (4V Phase 4)
  7. COMPLETE: All applicable phases finished
  8. REJECTED: Patch superseded or rejected


Common Pitfalls

  • Claiming a patch fixed a finding without re-running the exploration and recording verification evidence.
  • Narrow fixes that don’t generalize (“vaccinate”); update invariants/generators when appropriate.
  • Leaving regression risk unaddressed (no tests, no invariant reasoning, no guardrails).