# Security Workflow Patterns: A Technical Deep Dive

*Common patterns and architectures for implementing Developer Security Orchestration*

## Introduction

Security workflows, like software architecture patterns, follow repeatable structures that can be codified, tested, and reused. This guide explores the technical patterns that make security automation reliable, scalable, and maintainable.

## Core Workflow Patterns

### 1. The Assessment-Action Pattern

**Problem**: Security events require intelligent triage before action can be taken.

**Pattern Structure**:
```yaml
workflow: assessment_action_pattern
trigger: security_event
steps:
  - name: assess
    type: analysis
    inputs: [event_data, context_data]
    outputs: [risk_level, recommended_actions, confidence_score]

  - name: decide
    type: conditional
    conditions:
      - if: risk_level == "critical" && confidence_score > 0.9
        then: execute_immediate_action
      - if: risk_level == "high" && confidence_score > 0.7
        then: execute_with_approval
      - else: escalate_for_human_review

  - name: act
    type: dynamic
    action: ${decision_output}

  - name: verify
    type: validation
    checks: [security_improvement, no_regression, compliance_maintained]
```

**Implementation Example**:
```javascript
class SecurityAssessmentPattern {
  async execute(securityEvent) {
    // Assessment phase
    const assessment = await this.assessRisk({
      event: securityEvent,
      context: await this.gatherContext(securityEvent),
      history: await this.getHistoricalData(securityEvent.type)
    });

    // Decision phase
    const decision = this.makeDecision(assessment);

    // Action phase
    const result = await this.executeAction(decision, securityEvent);

    // Verification phase
    await this.verifyResult(result, assessment.expectedOutcome);

    return {
      assessment,
      decision,
      result,
      auditTrail: this.generateAuditTrail()
    };
  }

  assessRisk({ event, context, history }) {
    return {
      riskLevel: this.calculateRiskScore(event, context),
      impact: this.assessBusinessImpact(event, context),
      urgency: this.calculateUrgency(event, history),
      recommendedActions: this.generateRecommendations(event),
      confidence: this.calculateConfidence(event, context, history)
    };
  }
}
```

**Use Cases**:
- Vulnerability response workflows
- Incident triage and response
- Compliance violation handling
- Security configuration changes

### 2. The Compensating Controls Pattern

**Problem**: Some security issues can't be immediately fixed but need temporary mitigation.

**Pattern Structure**:
```yaml
workflow: compensating_controls_pattern
trigger: unfixable_security_issue
steps:
  - name: analyze_constraints
    type: analysis
    outputs: [fix_blockers, acceptable_risk_level, business_requirements]

  - name: design_compensating_controls
    type: planning
    inputs: [vulnerability_details, constraints, risk_tolerance]
    outputs: [control_options, effectiveness_rating, implementation_cost]

  - name: implement_controls
    type: parallel
    actions:
      - deploy_waf_rules
      - enable_additional_monitoring
      - restrict_access_controls
      - add_detection_rules

  - name: validate_effectiveness
    type: testing
    tests: [penetration_test, compliance_check, monitoring_validation]

  - name: schedule_permanent_fix
    type: planning
    outputs: [remediation_timeline, resource_requirements, success_criteria]
```

**Real-world Example**:
```javascript
// Compensating controls for unpatchable legacy system
const legacySystemProtection = {
  trigger: {
    type: 'vulnerability_detected',
    conditions: {
      system_type: 'legacy',
      patch_availability: false,
      business_criticality: 'high'
    }
  },

  compensating_controls: [
    {
      type: 'network_segmentation',
      implementation: async () => {
        await deployFirewallRules({
          source: 'any',
          destination: 'legacy_system',
          action: 'deny_except_required_ports'
        });
      }
    },
    {
      type: 'enhanced_monitoring',
      implementation: async () => {
        await enableDetailedLogging('legacy_system');
        await deployBehaviorAnalytics('legacy_system');
        await createAlertRules('legacy_system_anomalies');
      }
    },
    {
      type: 'access_restriction',
      implementation: async () => {
        await requireMFAForAccess('legacy_system');
        await implementPrivilegedAccessManagement('legacy_system');
        await enableSessionRecording('legacy_system');
      }
    }
  ]
};
```

### 3. The Progressive Remediation Pattern

**Problem**: Complex security issues need staged fixes with validation at each step.

**Pattern Structure**:
```yaml
workflow: progressive_remediation_pattern
phases:
  - name: immediate_containment
    priority: critical
    timeout: 5_minutes
    actions: [isolate_threat, stop_data_flow, alert_team]
    rollback: automated

  - name: impact_assessment
    priority: high
    timeout: 30_minutes
    actions: [assess_damage, identify_affected_systems, gather_evidence]
    rollback: manual

  - name: tactical_fixes
    priority: medium
    timeout: 2_hours
    actions: [patch_critical_vulnerabilities, harden_configurations, update_access_controls]
    rollback: automated

  - name: strategic_improvements
    priority: low
    timeout: 1_week
    actions: [architecture_changes, process_improvements, tool_upgrades]
    rollback: manual
```

**Implementation Pattern**:
```javascript
class ProgressiveRemediationPattern {
  constructor(incident) {
    this.phases = [
      new ImmediateContainmentPhase(incident),
      new ImpactAssessmentPhase(incident),
      new TacticalFixesPhase(incident),
      new StrategicImprovementsPhase(incident)
    ];
  }

  async execute() {
    const results = [];

    for (const phase of this.phases) {
      try {
        const phaseResult = await this.executePhase(phase);
        results.push(phaseResult);

        // Validate phase completion before moving to next
        if (!await this.validatePhaseSuccess(phase, phaseResult)) {
          throw new Error(`Phase ${phase.name} validation failed`);
        }

        // Create checkpoint for potential rollback
        await this.createCheckpoint(phase, phaseResult);

      } catch (error) {
        await this.handlePhaseFailure(phase, error);
        break; // Stop progression on failure
      }
    }

    return results;
  }

  async executePhase(phase) {
    const startTime = Date.now();

    // Set timeout for phase
    const timeoutPromise = new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Phase timeout')), phase.timeout)
    );

    // Execute phase actions
    const executionPromise = Promise.all(
      phase.actions.map(action => this.executeAction(action))
    );

    return await Promise.race([executionPromise, timeoutPromise]);
  }
}
```

### 4. The Compliance Workflow Pattern

**Problem**: Security actions need to generate audit trails and compliance evidence automatically.

**Pattern Structure**:
```yaml
workflow: compliance_workflow_pattern
every_step:
  pre_execution:
    - log_intent_and_authorization
    - validate_compliance_requirements
    - check_change_approval_if_required

  during_execution:
    - stream_execution_events
    - capture_evidence_artifacts
    - maintain_chain_of_custody

  post_execution:
    - validate_compliance_outcome
    - generate_audit_evidence
    - update_compliance_dashboards
    - trigger_required_notifications

framework_specific:
  SOC2:
    evidence_types: [access_logs, change_records, security_configurations]
    retention_period: 7_years
    attestation_required: true

  HIPAA:
    evidence_types: [access_logs, phi_handling_records, security_incidents]
    retention_period: 6_years
    encryption_required: true

  GDPR:
    evidence_types: [data_processing_records, consent_management, breach_notifications]
    retention_period: varies_by_purpose
    privacy_impact_assessment: required
```

**Implementation Example**:
```javascript
class ComplianceWorkflowPattern {
  constructor(complianceFrameworks) {
    this.frameworks = complianceFrameworks;
    this.evidenceCollector = new EvidenceCollector();
    this.auditLogger = new AuditLogger();
  }

  async executeWithCompliance(workflow, context) {
    const complianceContext = await this.setupComplianceContext(workflow, context);

    try {
      // Pre-execution compliance checks
      await this.validateComplianceRequirements(workflow, complianceContext);

      // Execute with evidence collection
      const result = await this.executeWithEvidence(workflow, complianceContext);

      // Post-execution compliance validation
      await this.validateComplianceOutcome(result, complianceContext);

      // Generate compliance artifacts
      await this.generateComplianceEvidence(result, complianceContext);

      return result;

    } catch (error) {
      await this.handleComplianceFailure(error, complianceContext);
      throw error;
    }
  }

  async generateComplianceEvidence(result, context) {
    const evidence = {
      execution_id: context.executionId,
      timestamp: new Date().toISOString(),
      user: context.user,
      workflow: context.workflow,
      actions_performed: result.actions,
      outcomes: result.outcomes,
      security_impact: result.securityImpact,
      data_processed: result.dataProcessed,
      approvals: context.approvals,
      attestations: await this.generateAttestations(result, context)
    };

    for (const framework of this.frameworks) {
      await this.storeFrameworkEvidence(framework, evidence);
    }

    return evidence;
  }
}
```

## Advanced Patterns

### 5. The Circuit Breaker Pattern for Security

**Problem**: Security automation can cause cascading failures if not properly controlled.

```javascript
class SecurityCircuitBreaker {
  constructor(options = {}) {
    this.failureThreshold = options.failureThreshold || 5;
    this.resetTimeout = options.resetTimeout || 60000;
    this.monitoringWindow = options.monitoringWindow || 300000;

    this.state = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
    this.failures = [];
    this.lastFailureTime = null;
  }

  async execute(securityAction, context) {
    if (this.state === 'OPEN') {
      if (this.shouldAttemptReset()) {
        this.state = 'HALF_OPEN';
      } else {
        throw new Error('Security circuit breaker is OPEN - automation disabled');
      }
    }

    try {
      const result = await securityAction(context);
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure(error);
      throw error;
    }
  }

  onSuccess() {
    this.failures = [];
    this.state = 'CLOSED';
  }

  onFailure(error) {
    this.failures.push({
      timestamp: Date.now(),
      error: error.message
    });

    // Clean old failures outside monitoring window
    const cutoff = Date.now() - this.monitoringWindow;
    this.failures = this.failures.filter(f => f.timestamp > cutoff);

    if (this.failures.length >= this.failureThreshold) {
      this.state = 'OPEN';
      this.lastFailureTime = Date.now();

      // Escalate to humans when automation is disabled
      this.escalateToHuman({
        reason: 'Security automation circuit breaker opened',
        failureCount: this.failures.length,
        recentFailures: this.failures
      });
    }
  }
}
```

### 6. The Saga Pattern for Distributed Security Operations

**Problem**: Security workflows often span multiple systems and need coordinated rollback.

```javascript
class SecuritySaga {
  constructor(sagaId) {
    this.sagaId = sagaId;
    this.steps = [];
    this.compensations = [];
    this.currentStep = 0;
  }

  addStep(action, compensation) {
    this.steps.push(action);
    this.compensations.unshift(compensation); // Reverse order for rollback
  }

  async execute() {
    try {
      for (let i = 0; i < this.steps.length; i++) {
        this.currentStep = i;
        await this.steps[i]();

        // Create checkpoint after each successful step
        await this.saveCheckpoint(i);
      }

      return { status: 'completed', sagaId: this.sagaId };

    } catch (error) {
      await this.rollback();
      throw error;
    }
  }

  async rollback() {
    // Execute compensations for completed steps only
    for (let i = 0; i < this.currentStep; i++) {
      try {
        await this.compensations[i]();
      } catch (compensationError) {
        // Log but don't throw - best effort rollback
        console.error(`Compensation failed for step ${i}:`, compensationError);
      }
    }
  }
}

// Example: Multi-system vulnerability remediation
const vulnerabilityRemediationSaga = new SecuritySaga('vuln_fix_001');

vulnerabilityRemediationSaga.addStep(
  // Forward action: Update application dependencies
  async () => await updateDependencies(['lodash@4.17.21']),
  // Compensation: Rollback dependencies
  async () => await updateDependencies(['lodash@4.17.20'])
);

vulnerabilityRemediationSaga.addStep(
  // Forward action: Deploy security patches
  async () => await deploySecurityPatches(['CVE-2024-1234']),
  // Compensation: Rollback patches
  async () => await rollbackSecurityPatches(['CVE-2024-1234'])
);

vulnerabilityRemediationSaga.addStep(
  // Forward action: Update WAF rules
  async () => await updateWAFRules({ block: ['malicious_pattern_v2'] }),
  // Compensation: Restore old WAF rules
  async () => await updateWAFRules({ block: ['malicious_pattern_v1'] })
);
```

## Pattern Selection Guide

### Choose Assessment-Action for:
- ✅ Vulnerability response workflows
- ✅ Security alert triage
- ✅ Compliance violation handling
- ❌ Time-critical incident response
- ❌ Simple, deterministic fixes

### Choose Compensating Controls for:
- ✅ Legacy system protection
- ✅ Unpatchable vulnerabilities
- ✅ Regulatory requirement gaps
- ❌ Temporary security measures
- ❌ Quick fixes available

### Choose Progressive Remediation for:
- ✅ Complex security incidents
- ✅ Multi-phase recovery plans
- ✅ High-stakes security changes
- ❌ Simple vulnerability fixes
- ❌ Time-critical responses

### Choose Compliance Workflow for:
- ✅ Regulated industry operations
- ✅ Audit preparation workflows
- ✅ Evidence collection requirements
- ❌ Development environment changes
- ❌ Internal tool workflows

## Anti-Patterns to Avoid

### 1. The "Alert Fatigue" Anti-Pattern
```javascript
// DON'T: Generate alerts for everything
securityEvent.forEach(event => {
  sendAlert(event);
  createTicket(event);
  updateDashboard(event);
});

// DO: Intelligent filtering and aggregation
const significantEvents = securityEvents
  .filter(event => isSignificant(event))
  .reduce(aggregateRelatedEvents);

significantEvents.forEach(processIntelligently);
```

### 2. The "Manual Automation" Anti-Pattern
```javascript
// DON'T: Require human approval for every automated action
async function automatedSecurityFix() {
  const fix = generateSecurityFix();
  const approval = await requestHumanApproval(fix); // Defeats the purpose
  if (approval.approved) {
    await applyFix(fix);
  }
}

// DO: Automate safe actions, escalate complex ones
async function intelligentSecurityFix() {
  const fix = generateSecurityFix();
  const riskAssessment = assessRiskOfFix(fix);

  if (riskAssessment.isLowRisk) {
    await applyFixWithRollback(fix);
  } else {
    await escalateToHuman(fix, riskAssessment);
  }
}
```

### 3. The "Perfect Solution" Anti-Pattern
```javascript
// DON'T: Try to automate everything perfectly from the start
const perfectSecurityWorkflow = {
  handleAllVulnerabilityTypes: true,
  zeroFalsePositives: true,
  perfectRiskAssessment: true,
  handleAllEdgeCases: true
};

// DO: Start simple, improve incrementally
const pragmaticSecurityWorkflow = {
  handleCommonCases: true,
  improveOverTime: true,
  escalateComplexCases: true,
  learnFromMistakes: true
};
```

## Best Practices

### 1. **Start with Observable Actions**
Before automating, ensure you can observe and measure the current manual process.

### 2. **Implement Circuit Breakers**
Always include failure detection and automatic fallback to manual processes.

### 3. **Design for Rollback**
Every automated security action should have a rollback plan.

### 4. **Generate Audit Trails**
Security automation without audit trails creates compliance problems.

### 5. **Test Failure Scenarios**
Test what happens when automation fails, not just when it succeeds.

### 6. **Gradual Automation**
Start with read-only automation, then low-risk actions, then complex scenarios.

## Conclusion

Security workflow patterns provide reusable solutions to common automation challenges. By implementing these patterns thoughtfully, teams can build reliable, scalable security automation that improves both security posture and developer productivity.

The key is matching the right pattern to your specific use case and organizational constraints, then implementing with proper error handling, observability, and rollback capabilities.

**Next Steps:**
1. Identify your most painful security workflows
2. Map them to appropriate patterns
3. Implement incrementally with safety measures
4. Measure and improve continuously

---

*Want to see these patterns in action? Check out the [Vaultace CLI workflow templates](https://github.com/vaultace/vaultace-cli/tree/main/src/workflows/templates) for real-world implementations.*