Standards

SOC 2 Technical Controls: What Engineering Teams Must Implement

Common Criteria CC6–CC8 explained — logical access code security and change management for SaaS teams seeking SOC 2 Type II

What Is SOC 2 and Why It Matters

SOC 2 (Service Organization Control 2) is an auditing framework developed by the American Institute of CPAs (AICPA) for service organizations — primarily SaaS companies — that store or process customer data. A SOC 2 Type II report certifies that the organization's security controls were not only designed effectively (Type I) but operated effectively over a sustained audit period, typically 6–12 months.

SOC 2 is built around five Trust Service Criteria (TSC): Security, Availability, Processing Integrity, Confidentiality, and Privacy. The Security criterion (also called Common Criteria or CC) is required in every audit. The others are optional based on business context.

For engineering teams, SOC 2 directly governs code security practices. Enterprise buyers increasingly require SOC 2 Type II reports as a prerequisite for vendor contracts — particularly in financial services, healthcare, and government. A SOC 2 Type II report signals to customers that security is not an afterthought but a documented, audited practice.

Common Criteria Relevant to Engineering

The Common Criteria (CC) categories most relevant to engineering teams are CC6, CC7, and CC8:

  • CC6: Logical and Physical Access Controls — Controls over who can access systems, code repositories, secrets, and production environments
  • CC7: System Operations — Security monitoring, incident detection, and response processes
  • CC8: Change Management — Controls over how code changes reach production — reviews, testing, authorization

CC9 (Risk Mitigation) and CC1–CC5 (organizational controls) are primarily addressed by policy and governance, not engineering implementation. CC6, CC7, and CC8 require technical evidence that auditors verify by inspecting systems, configurations, and reports.

CC6: Logical and Physical Access Controls

CC6 governs who can access systems and data. For engineering teams, the key CC6 controls are:

CC6.1 — Logical access security measures

Secrets management is a primary CC6.1 control. Credentials must be stored in a secrets manager, not in source code or environment files committed to repositories.

# NON-COMPLIANT: Credentials in code (fails CC6.1)
DATABASE_URL = "postgresql://user:password123@prod-db.example.com/app"
API_KEY = "sk-prod-abc123"

# COMPLIANT: Credentials injected at runtime from secrets manager
import boto3

def get_secret(secret_name: str) -> str:
    client = boto3.client('secretsmanager', region_name='eu-west-1')
    response = client.get_secret_value(SecretId=secret_name)
    return response['SecretString']

DATABASE_URL = get_secret('prod/database/url')

CC6.3 — Role-based access controls

Application code must enforce authorization at every sensitive operation. Missing authorization checks (IDOR vulnerabilities) directly violate CC6.3.

// NON-COMPLIANT: No ownership check (fails CC6.3)
app.get('/api/reports/:id', authenticate, (req, res) => {
  const report = db.reports.findById(req.params.id);
  res.json(report);  // Any authenticated user can read any report
});

// COMPLIANT: Ownership verified before returning data
app.get('/api/reports/:id', authenticate, async (req, res) => {
  const report = await db.reports.findById(req.params.id);
  if (!report || report.ownerId !== req.user.id) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  res.json(report);
});

CC7: System Operations and Monitoring

CC7 requires that security events are detected and responded to. For engineering teams:

CC7.2 — Monitoring of system components

Security event logging must be implemented in the application layer. Auditors look for evidence that authentication failures, authorization violations, and anomalous access patterns are logged.

// COMPLIANT: Security event logging for CC7.2
function logSecurityEvent(event: {
  type: 'auth_failure' | 'authz_failure' | 'suspicious_request';
  userId?: string;
  resource?: string;
  ip: string;
}) {
  console.error(JSON.stringify({
    ...event,
    timestamp: new Date().toISOString(),
    service: 'api',
    severity: 'WARN',
  }));
}

app.post('/api/login', async (req, res) => {
  const user = await authenticate(req.body);
  if (!user) {
    logSecurityEvent({ type: 'auth_failure', ip: req.ip });
    return res.status(401).json({ error: 'Invalid credentials' });
  }
});

CC7.4 — Security incident identification

Dependency scanning and SAST scanning provide evidence that the organization proactively identifies vulnerabilities before they become incidents. Scan reports with timestamps demonstrate ongoing monitoring.

CC8: Change Management

CC8 governs how changes to production systems are authorized and implemented. The primary CC8 controls are:

CC8.1 — Authorization of infrastructure and software changes

Every production code change must be reviewed, approved, and tested before deployment. Auditors verify this through:

  • Pull request approval requirements (branch protection rules requiring at least one reviewer)
  • Automated test passage requirements before merge
  • Deployment pipeline configurations that prevent direct pushes to main

CC8.1 — Security testing in change management

When CodeSlick's GitHub App runs on every pull request, it creates a documented record in GitHub's Security Tab showing which commits were scanned, which findings were identified, whether the pull request passed or failed security gates, and when findings were remediated.

This timestamped record satisfies CC8.1's requirement for documented evidence that security testing is part of the change management process. SOC 2 auditors can review GitHub pull request history and SARIF reports to verify that security checks ran continuously across the audit period.

How SAST Evidence Supports SOC 2 Audits

SOC 2 Type II auditors assess whether controls operated effectively over the audit period. SAST provides three categories of evidence:

  1. Process evidence: GitHub App configuration showing security scans are required on every PR; branch protection rules blocking merges when security gates fail
  2. Operational evidence: SARIF reports and GitHub Security Tab history showing which findings were identified and when they were resolved across the audit period
  3. Completeness evidence: Coverage of OWASP Top 10 categories demonstrating broad vulnerability detection

CodeSlick provides 308 security checks across JavaScript, TypeScript, Python, Java, and Go. All findings include OWASP Top 10 mapping, CWE classification, and CVSS severity — the taxonomy auditors recognize. The GitHub App runs automatically on every pull request with no manual intervention, satisfying the "operating effectively" standard required for SOC 2 Type II.

Frequently Asked Questions

Related Guides