Przejdź do treści głównej

Application Security Best Practices 2025

Did you know that 87% of organizations experienced an application security breach in the past 12 months? Comprehensive guide to application security and data protection 2025 - from OWASP Top 10 through DevSecOps, automated security testing, web application security to GDPR/SOC2/ISO27001 compliance. Practical solutions for your production environment.

Author: Michał Wojciechowski··15 min read
Cybersecurity and application protection concept

Why is application security critical in 2025?

Imagine you wake up in the morning and see that your application has been hacked - customer data leaked, and social media is already broadcasting the fact. This isn't science fiction. In 2024, the average cost of a single data breach was $4.45 million according to the IBM Security Report.

What's worse - 43% of cyber attacks target small and medium businesses. Even Microsoft, Tesla, and SolarWinds fell victim to advanced attacks. 60% of companies affected by a serious breach close within 6 months. Application security and cybersecurity are no longer optional - it's a business necessity for your organization.

In 2025, the security landscape is changing radically. Supply chain attacks increased by 742% (Sonatype 2024), AI-powered threats are becoming mainstream, and regulatory requirements (GDPR, NIS2, DORA) have real enforcement with penalties reaching millions of euros. You must transition from reactive patching to proactive security-first approach.

Key areas of application security 2025:

  • OWASP Top 10 2025 – new vulnerabilities: Insecure Design, Supply Chain, SSRF
  • DevSecOps integration – security in every CI/CD stage, shift-left approach
  • Automated security testing – SAST/DAST/SCA in pipeline, continuous vulnerability scanning
  • API security – authentication, rate limiting, input validation, OAuth 2.1/OIDC
  • Compliance frameworks – GDPR, SOC2, ISO27001 requirements and automated auditing

This article is based on OWASP official guidelines, NIST Cybersecurity Framework, CIS Benchmarks, and industry reports from Gartner, Forrester, and Verizon DBIR. If you're interested in web application security in the context of cloud infrastructure, check out our cloud solutions. For system architecture, I also recommend the article about microservices vs monolith and Kubernetes for beginners.

OWASP Top 10 2025 - Changes and new threats

OWASP Top 10 is the industry standard for web application security that you should follow in your organization. The 2025 version introduces significant changes - new vulnerability categories and priority reorganization based on real-world data breach analysis from thousands of companies. Let's see what exactly changed and how you can secure your application.

A01:2025 - Broken Access Control

Remains #1. As many as 94% of applications tested in 2024 had access control vulnerabilities. This means nearly every application is vulnerable! Attackers gain unauthorized access to other users' data - imagine anyone can see your private documents just by changing the ID in the URL.

Here's a practical example of the problem and its solution in Node.js:

// ❌ Vulnerable - no proper authorization check
app.get('/api/users/:id/salary', (req, res) => {
  const salary = db.getSalary(req.params.id);
  res.json({ salary }); // anyone can see anyone's salary!
});

// ✅ Secure - proper authorization
app.get('/api/users/:id/salary', authenticate, (req, res) => {
  if (req.user.id !== req.params.id && !req.user.isAdmin) {
    return res.status(403).json({ error: 'Forbidden' });
  }
  const salary = db.getSalary(req.params.id);
  res.json({ salary });
});

Mitigation: Implement role-based access control (RBAC), deny by default, validate ownership, audit access logs.

A02:2025 - Cryptographic Failures

Formerly "Sensitive Data Exposure". Weak encryption, hardcoded secrets, cleartext transmission - these mistakes can cost you millions in GDPR fines. Data protection isn't just a legal requirement, it's your customers' trust.

Here's how NOT to secure passwords (I still see this in 2025!) and how to do it correctly:

// ❌ Vulnerable - MD5 is not cryptographically secure
const crypto = require('crypto');
const hash = crypto.createHash('md5').update(password).digest('hex');

// ✅ Secure - bcrypt with proper salt rounds
const bcrypt = require('bcrypt');
const saltRounds = 12;
const hash = await bcrypt.hash(password, saltRounds);

// ✅ Encryption at rest (AES-256-GCM)
const algorithm = 'aes-256-gcm';
const key = crypto.randomBytes(32); // from Key Vault in production
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);

Standards: TLS 1.3, AES-256-GCM, bcrypt/Argon2, Azure Key Vault/AWS KMS for key management.

A03:2025 - Injection

SQL Injection, NoSQL Injection, Command Injection - classics that still work. Drops from #1 (2021) to #3 thanks to the popularization of ORMs and parameterized queries. However, if you're still using string concatenation in SQL queries - this is a problem you need to fix IMMEDIATELY.

See how easy it is to create a vulnerability and how equally easy to fix it:

// ❌ Vulnerable - SQL Injection
const query = `SELECT * FROM users WHERE email = '${userInput}'`;
// userInput: ' OR '1'='1' --

// ✅ Secure - Parameterized query (Node.js/pg)
const query = 'SELECT * FROM users WHERE email = $1';
const result = await pool.query(query, [userInput]);

// ✅ Secure - ORM (TypeORM)
const user = await userRepository.findOne({
  where: { email: userInput }
});

// ✅ Command Injection prevention
const { exec } = require('child_process');
// ❌ exec(`ping ${userInput}`); // Dangerous!
// ✅ Use allowlist validation
if (!/^[0-9.]+$/.test(userInput)) {
  throw new Error('Invalid IP address');
}

A04:2025 - Insecure Design (NEW)

This is a NEW category in OWASP Top 10! Fundamental security flaws already in the architecture phase. Lack of threat modeling, insecure by design. No patch will help here - you need a complete system redesign. It's like building a house without foundations - you can paint the walls all you want, but the house will collapse.

Example: unsecured password reset process (I've seen this in production!):

// ❌ Insecure Design - unlimited password reset attempts
app.post('/reset-password', async (req, res) => {
  const { email, code, newPassword } = req.body;
  if (await verifyResetCode(email, code)) {
    await updatePassword(email, newPassword);
  }
}); // Brute force attack possible!

// ✅ Secure Design - rate limiting + account lockout
const rateLimit = require('express-rate-limit');
const resetLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 5, // 5 attempts
  skipSuccessfulRequests: true
});

app.post('/reset-password', resetLimiter, async (req, res) => {
  const { email, code, newPassword } = req.body;
  const attempts = await getResetAttempts(email);
  if (attempts >= 3) {
    await lockAccount(email, '1 hour');
    return res.status(429).json({ error: 'Too many attempts' });
  }
  // ... verification logic
});

Prevention: Threat modeling (STRIDE/DREAD), security requirements in design phase, peer review.

A08:2025 - Software and Data Integrity Failures (NEW)

Supply chain attacks, insecure deserialization, unsigned updates. SolarWinds, Log4Shell fall here.

// package.json - dependency verification
{
  "dependencies": {
    "express": "^4.18.2"
  },
  "overrides": {
    "express": {
      "qs": "6.11.0" // Force specific version with security fix
    }
  }
}

// ✅ npm audit in CI/CD
npm audit --production --audit-level=high

// ✅ Dependency scanning (Snyk/Dependabot)
// .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 10
    allow:
      - dependency-type: "all"

// ✅ Subresource Integrity for CDN
<script
  src="https://cdn.example.com/lib.js"
  integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/ux..."
  crossorigin="anonymous">
</script>

A10:2025 - Server-Side Request Forgery (NEW)

SSRF attacks allow attackers to execute requests from the server to internal resources. Cloud metadata endpoints (AWS/Azure) are often targets.

// ❌ Vulnerable - no URL validation
app.get('/fetch-url', async (req, res) => {
  const url = req.query.url;
  const response = await fetch(url); // SSRF!
  // url = http://169.254.169.254/latest/meta-data/iam/security-credentials/
  res.send(await response.text());
});

// ✅ Secure - URL allowlist + validation
const ALLOWED_DOMAINS = ['api.trusted-domain.com'];

app.get('/fetch-url', async (req, res) => {
  const url = new URL(req.query.url);

  // Block internal IPs
  if (url.hostname === 'localhost' ||
      url.hostname === '127.0.0.1' ||
      url.hostname.startsWith('192.168.') ||
      url.hostname.startsWith('10.') ||
      url.hostname === '169.254.169.254') { // AWS metadata
    return res.status(403).json({ error: 'Forbidden' });
  }

  // Allowlist check
  if (!ALLOWED_DOMAINS.includes(url.hostname)) {
    return res.status(403).json({ error: 'Domain not allowed' });
  }

  const response = await fetch(url.toString());
  res.send(await response.text());
});

Pro Tip: OWASP ZAP automated scanning

OWASP ZAP (Zed Attack Proxy) is a free open-source DAST tool. CI/CD pipeline integration: Docker image owasp/zap2docker-stable, baseline scan in every PR, full scan weekly. Detects 90%+ OWASP Top 10 vulnerabilities automatically.

DevSecOps integration and automation

DevSecOps - Security in CI/CD pipeline

Remember when security was only checked before production? That was a disaster - finding critical vulnerabilities the day before release. DevSecOps changes everything.

DevSecOps is a shift-left approach - you test web application security at every stage of development, not as an afterthought. Gartner report 2024 shows the numbers: organizations with mature DevSecOps practices have 60% fewer security incidents and 50% faster remediation time. That's real savings of your money and time.

Let's get specific now - how to implement security automation in your pipeline:

Security gates in GitHub Actions

If you're using GitHub Actions, you can add automatic security checks to every pull request. Here's a ready workflow you can copy to your project:

name: Security Checks
on: [pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      # SAST - Static code analysis
      - name: Run Semgrep
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten
            p/ci

      # SCA - Dependency vulnerability scan
      - name: Run Snyk
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high

      # Secret scanning
      - name: Gitleaks scan
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Container scanning
      - name: Trivy container scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:latest'
          severity: 'CRITICAL,HIGH'
          exit-code: '1' # Fail pipeline on vulnerabilities

Azure DevOps security pipeline

Multi-stage security validation:

stages:
- stage: SecurityScan
  jobs:
  - job: SAST
    steps:
    - task: CredScan@3 # Microsoft Credential Scanner
      inputs:
        outputFormat: 'pre'

    - task: SonarCloudPrepare@1
      inputs:
        SonarCloud: 'SonarCloud-Connection'
        organization: 'my-org'
        projectKey: 'my-project'

    - task: DotNetCoreCLI@2
      inputs:
        command: 'build'

    - task: SonarCloudAnalyze@1

    - task: SonarCloudPublish@1
      inputs:
        pollingTimeoutSec: '300'

  - job: DependencyScan
    steps:
    - task: NuGetCommand@2
      inputs:
        command: 'restore'

    - task: WhiteSource@21 # Mend SCA
      inputs:
        cwd: '$(System.DefaultWorkingDirectory)'
        projectName: 'MyApp'

  - job: ContainerScan
    steps:
    - task: Docker@2
      inputs:
        command: 'build'
        Dockerfile: '**/Dockerfile'

    - task: AquaScanner@4
      inputs:
        image: 'myapp:latest'
        scanner: 'aqua'
        connection: 'AquaConnection'

Security policy as code

OPA (Open Policy Agent) for infrastructure security:

# policy.rego - Kubernetes security policies
package kubernetes.admission

deny[msg] {
  input.request.kind.kind == "Pod"
  not input.request.object.spec.securityContext.runAsNonRoot
  msg := "Containers must not run as root"
}

deny[msg] {
  input.request.kind.kind == "Pod"
  container := input.request.object.spec.containers[_]
  not container.securityContext.readOnlyRootFilesystem
  msg := sprintf("Container %v must use read-only root filesystem", [container.name])
}

deny[msg] {
  input.request.kind.kind == "Service"
  input.request.object.spec.type == "LoadBalancer"
  not input.request.object.metadata.annotations["service.beta.kubernetes.io/azure-load-balancer-internal"]
  msg := "LoadBalancer services must be internal only"
}

# Test policies in CI/CD
opa test policy.rego policy_test.rego
opa exec --decision kubernetes/admission --bundle policy/ kubernetes-manifest.yaml

Infrastructure as Code security scanning

Checkov for Terraform/CloudFormation/Kubernetes:

# .github/workflows/iac-security.yml
name: IaC Security Scan
on: [push]

jobs:
  checkov:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Run Checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform/
          framework: terraform
          output_format: cli
          soft_fail: false # Fail build on security issues

      - name: tfsec scan
        uses: aquasecurity/tfsec-action@v1.0.0
        with:
          working_directory: terraform/

      # Example Terraform security check results:
      # ❌ CRITICAL: S3 bucket encryption not enabled
      # ❌ HIGH: Security group allows 0.0.0.0/0 ingress
      # ❌ MEDIUM: IAM policy allows wildcard actions

Shift-Left Metrics

Forrester research shows: fixing a vulnerability in production costs 30x more than fixing it in the development phase. DevSecOps ROI: average 40% reduction in security incidents, 50% faster remediation time, 70% reduction in compliance audit effort.

Automated Security Testing - SAST, DAST, SCA

You're asking yourself: "Which security testing tool should I choose?" The answer is: all three. Comprehensive security testing requires three complementary approaches: SAST (code analysis), DAST (runtime testing), SCA (dependency scanning). Each detects different types of vulnerabilities - using only one leaves huge holes in your defense.

If you're interested in TypeScript, also read my article about TypeScript vs JavaScript - type safety is also part of cybersecurity.

SAST - Static Analysis

Analyzes source code without execution. Fast, early detection.

# Semgrep - SAST for multiple languages
semgrep --config=auto src/

# SonarQube
sonar-scanner \
  -Dsonar.projectKey=myapp \
  -Dsonar.sources=. \
  -Dsonar.host.url=http://sonar \
  -Dsonar.login=${SONAR_TOKEN}

# ESLint security plugins
npm install --save-dev \
  eslint-plugin-security \
  eslint-plugin-no-secrets

Detects: Injection flaws, hardcoded secrets, crypto issues.

DAST - Dynamic Analysis

Tests running application like a real attacker.

# OWASP ZAP baseline scan
docker run -t owasp/zap2docker-stable \
  zap-baseline.py \
  -t https://staging.example.com \
  -r zap-report.html

# Burp Suite API scan
burp --project-file=project.burp \
  --unpause-spider-and-scanner \
  --config=config.json

# Nuclei vulnerability scanner
nuclei -u https://example.com \
  -t cves/ -t vulnerabilities/

Detects: Runtime issues, auth bypasses, config errors.

SCA - Dependency Scanning

Identifies vulnerabilities in third-party dependencies.

# npm audit
npm audit --audit-level=high

# Snyk
snyk test --severity-threshold=high
snyk monitor # Continuous monitoring

# OWASP Dependency-Check
dependency-check.sh \
  --project "MyApp" \
  --scan ./lib \
  --format HTML \
  --failOnCVSS 7

Detects: Known CVEs, license issues, outdated deps.

IAST - Interactive Testing

Combines SAST+DAST, instruments code in runtime.

# Contrast Security IAST agent
java -javaagent:contrast.jar \
  -Dcontrast.api.key=${API_KEY} \
  -jar myapp.jar

# Seeker IAST
dotnet add package Seeker.Agent
export SEEKER_SERVER_URL="https://..."
dotnet run

Advantage: Low false positives, code-level context.

Complete security testing pipeline

Integration of all testing types:

# .gitlab-ci.yml
stages:
  - build
  - sast
  - test
  - dast
  - deploy

sast_scan:
  stage: sast
  image: returntocorp/semgrep
  script:
    - semgrep --config=auto --json --output=semgrep.json src/
  artifacts:
    reports:
      sast: semgrep.json

dependency_scan:
  stage: sast
  image: node:18
  script:
    - npm audit --json > npm-audit.json
    - snyk test --json > snyk.json
  artifacts:
    reports:
      dependency_scanning: snyk.json

container_scan:
  stage: test
  image: aquasec/trivy
  script:
    - trivy image --severity HIGH,CRITICAL myapp:latest

dast_scan:
  stage: dast
  image: owasp/zap2docker-stable
  script:
    - zap-baseline.py -t ${STAGING_URL} -r zap-report.html
  artifacts:
    paths:
      - zap-report.html
  only:
    - staging
    - production

security_gate:
  stage: deploy
  script:
    - |
      if [ $(jq '.vulnerabilities | map(select(.severity=="CRITICAL")) | length' snyk.json) -gt 0 ]; then
        echo "CRITICAL vulnerabilities found, blocking deployment"
        exit 1
      fi

Tool Selection Strategy

Open source start: Semgrep (SAST), OWASP ZAP (DAST), npm audit (SCA). Enterprise scale: Snyk/Checkmarx/Veracode for comprehensive coverage, lower false positives, compliance reporting. Average organization uses 3-5 security tools in pipeline.

API Security Best Practices

Your API is the gateway to all data in the system. In 2025, APIs are the primary attack vector - 83% of network traffic is API calls (Cloudflare 2024). Every unsecured endpoint is a potential data leak. OWASP API Security Top 10 defines specific threats for REST and GraphQL APIs that you must address.

Authentication & Authorization

OAuth 2.1 + OpenID Connect as industry standard:

// Node.js - JWT verification with proper validation
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const client = jwksClient({
  jwksUri: 'https://auth.example.com/.well-known/jwks.json',
  cache: true,
  rateLimit: true
});

function getKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    const signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

function authenticateToken(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'No token provided' });
  }

  jwt.verify(token, getKey, {
    algorithms: ['RS256'],
    audience: 'api.example.com',
    issuer: 'https://auth.example.com',
    maxAge: '1h' // Token expiration
  }, (err, decoded) => {
    if (err) {
      return res.status(403).json({ error: 'Invalid token' });
    }
    req.user = decoded;
    next();
  });
}

// Scope-based authorization
function requireScope(scope) {
  return (req, res, next) => {
    if (!req.user.scope.includes(scope)) {
      return res.status(403).json({ error: 'Insufficient permissions' });
    }
    next();
  };
}

app.get('/api/admin/users',
  authenticateToken,
  requireScope('admin:read'),
  (req, res) => {
    // Handler
  }
);

Rate Limiting & Throttling

Prevent brute force, DDoS, API abuse:

// Express rate limiting (sliding window)
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const Redis = require('ioredis');

const redis = new Redis({
  host: process.env.REDIS_HOST,
  password: process.env.REDIS_PASSWORD
});

// Global rate limit
const globalLimiter = rateLimit({
  store: new RedisStore({
    client: redis,
    prefix: 'rl:global:'
  }),
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  standardHeaders: true,
  legacyHeaders: false,
  handler: (req, res) => {
    res.status(429).json({
      error: 'Too many requests',
      retryAfter: req.rateLimit.resetTime
    });
  }
});

// Endpoint-specific limits
const authLimiter = rateLimit({
  store: new RedisStore({ client: redis, prefix: 'rl:auth:' }),
  windowMs: 15 * 60 * 1000,
  max: 5, // Stricter limit for auth endpoints
  skipSuccessfulRequests: true // Only count failed attempts
});

// User-specific rate limiting
const userLimiter = rateLimit({
  store: new RedisStore({ client: redis, prefix: 'rl:user:' }),
  windowMs: 60 * 1000,
  max: 60,
  keyGenerator: (req) => req.user.id // Per-user limit
});

app.use('/api/', globalLimiter);
app.post('/api/auth/login', authLimiter);
app.use('/api/user/*', authenticateToken, userLimiter);

Input Validation & Sanitization

Validate all inputs against strict schemas:

// Zod schema validation
const { z } = require('zod');

const UserSchema = z.object({
  email: z.string().email().max(255),
  password: z.string()
    .min(12, 'Password must be at least 12 characters')
    .regex(/[A-Z]/, 'Must contain uppercase')
    .regex(/[a-z]/, 'Must contain lowercase')
    .regex(/[0-9]/, 'Must contain number')
    .regex(/[^A-Za-z0-9]/, 'Must contain special char'),
  age: z.number().int().min(18).max(120),
  role: z.enum(['user', 'admin', 'moderator'])
});

app.post('/api/users', async (req, res) => {
  try {
    const validatedData = UserSchema.parse(req.body);

    // Additional business logic validation
    const existingUser = await db.users.findOne({
      email: validatedData.email
    });
    if (existingUser) {
      return res.status(409).json({ error: 'Email already exists' });
    }

    // Sanitize HTML inputs
    const sanitizeHtml = require('sanitize-html');
    if (validatedData.bio) {
      validatedData.bio = sanitizeHtml(validatedData.bio, {
        allowedTags: ['b', 'i', 'em', 'strong'],
        allowedAttributes: {}
      });
    }

    const user = await createUser(validatedData);
    res.json({ id: user.id });

  } catch (error) {
    if (error instanceof z.ZodError) {
      return res.status(400).json({
        errors: error.errors
      });
    }
    throw error;
  }
});

API Gateway Security

Centralized security policies in API Gateway:

# Kong API Gateway configuration
services:
  - name: user-service
    url: http://users:8080
    routes:
      - name: users-route
        paths:
          - /api/users
    plugins:
      # Rate limiting
      - name: rate-limiting
        config:
          minute: 60
          policy: redis

      # JWT authentication
      - name: jwt
        config:
          key_claim_name: kid
          secret_is_base64: false

      # Request validation
      - name: request-validator
        config:
          body_schema: |
            {
              "type": "object",
              "properties": {
                "email": {"type": "string", "format": "email"}
              },
              "required": ["email"]
            }

      # CORS
      - name: cors
        config:
          origins:
            - https://app.example.com
          credentials: true
          max_age: 3600

      # IP restriction
      - name: ip-restriction
        config:
          allow:
            - 10.0.0.0/8
            - 172.16.0.0/12

      # Bot detection
      - name: bot-detection
        config:
          allow:
            - Googlebot
          deny:
            - BadBot

GraphQL Security

Specific protections for GraphQL APIs:

const { ApolloServer } = require('apollo-server');
const depthLimit = require('graphql-depth-limit');
const { createComplexityLimitRule } = require('graphql-validation-complexity');

const server = new ApolloServer({
  typeDefs,
  resolvers,

  // Query depth limiting (prevent deeply nested queries)
  validationRules: [
    depthLimit(7), // Max 7 levels deep
    createComplexityLimitRule(1000, {
      scalarCost: 1,
      objectCost: 10,
      listFactor: 20
    })
  ],

  // Query cost analysis
  plugins: [{
    requestDidStart() {
      return {
        didResolveOperation({ request, operation }) {
          const complexity = calculateComplexity({
            query: request.query,
            variables: request.variables
          });

          if (complexity > 1000) {
            throw new Error('Query too complex');
          }
        }
      };
    }
  }],

  // Disable introspection in production
  introspection: process.env.NODE_ENV !== 'production',

  // Context authentication
  context: ({ req }) => {
    const token = req.headers.authorization || '';
    const user = verifyToken(token);
    return { user };
  }
});

// Field-level authorization
const resolvers = {
  User: {
    email: (parent, args, context) => {
      if (context.user.id !== parent.id && !context.user.isAdmin) {
        throw new Error('Unauthorized');
      }
      return parent.email;
    }
  }
};

OWASP API Security Top 10 2025

Top threats: API1:2025 Broken Object Level Authorization, API2:2025 Broken Authentication, API3:2025 Broken Object Property Level Authorization, API4:2025 Unrestricted Resource Consumption, API5:2025 Broken Function Level Authorization. Each requires specific mitigation strategies.

Compliance and regulatory frameworks

Compliance - GDPR, SOC2, ISO27001

"GDPR is just a checkbox, right?" No. In 2024, GDPR fines exceeded €2.5 billion. Amazon paid €746 million, Meta €1.2 billion. These aren't numbers to ignore.

Regulatory compliance isn't optional - it's a legal requirement with real financial consequences for your company. Automated compliance monitoring and documentation are the foundation for audits and protection against penalties. Let's see how to implement technical requirements.

GDPR Technical Requirements

Data Protection by Design and Default - technical implementation:

Encryption at rest: AES-256-GCM for personal data, managed keys in Azure Key Vault/AWS KMS
Encryption in transit: TLS 1.3 minimum, HSTS headers, certificate pinning
Access logging: Audit trail of all access to personal data, retention 12 months
Data minimization: Collect only necessary data, automated data retention policies
Right to erasure: Automated data deletion process, verification within 30 days
Data portability: Export user data in machine-readable format (JSON/CSV)
Breach detection: Automated monitoring, alert within 72h requirement
// GDPR-compliant data handling
class GDPRCompliantUserService {
  async createUser(data) {
    // Data minimization - only required fields
    const user = {
      email: data.email,
      hashedPassword: await bcrypt.hash(data.password, 12),
      consentGiven: data.consent, // Explicit consent required
      consentDate: new Date(),
      dataRetentionDate: addYears(new Date(), 2) // Auto-deletion after 2 years
    };

    // Audit log
    await auditLog.create({
      action: 'USER_CREATED',
      userId: user.id,
      timestamp: new Date(),
      ipAddress: req.ip
    });

    return user;
  }

  async exportUserData(userId) {
    // Right to data portability (Art. 20)
    const user = await db.users.findById(userId);
    const orders = await db.orders.find({ userId });
    const logs = await auditLog.find({ userId });

    return {
      personalData: {
        email: user.email,
        createdAt: user.createdAt,
        consent: user.consentGiven
      },
      transactionHistory: orders,
      accessLog: logs
    };
  }

  async deleteUser(userId) {
    // Right to erasure (Art. 17)
    await db.users.update(userId, {
      email: 'deleted@deleted.com',
      hashedPassword: null,
      deletedAt: new Date(),
      deletionReason: 'USER_REQUEST'
    });

    // Pseudonymize instead of hard delete for compliance
    await auditLog.create({
      action: 'USER_DELETED',
      userId,
      timestamp: new Date()
    });
  }
}

SOC2 Type II Controls

Security, Availability, Confidentiality controls for SaaS:

CC6.1Logical Access: MFA enforcement, SSO integration, role-based access, session management
CC6.6Encryption: TLS 1.3, AES-256, key rotation policies, HSM for sensitive keys
CC7.2Change Management: Code review requirements, deployment approvals, rollback procedures
CC8.1Incident Response: Automated detection, response playbooks, communication procedures
# Infrastructure as Code - SOC2 compliant AWS setup
resource "aws_s3_bucket" "data" {
  bucket = "company-data"

  # CC6.6 - Encryption at rest
  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        sse_algorithm = "aws:kms"
        kms_master_key_id = aws_kms_key.data.arn
      }
    }
  }

  # CC6.1 - Access logging
  logging {
    target_bucket = aws_s3_bucket.logs.id
    target_prefix = "s3-access-logs/"
  }

  # Versioning for data integrity
  versioning {
    enabled = true
  }
}

# CC7.2 - Automated compliance monitoring
resource "aws_config_rule" "s3_encryption_check" {
  name = "s3-bucket-server-side-encryption-enabled"

  source {
    owner = "AWS"
    source_identifier = "S3_BUCKET_SERVER_SIDE_ENCRYPTION_ENABLED"
  }

  depends_on = [aws_config_configuration_recorder.main]
}

# CC8.1 - Security monitoring
resource "aws_cloudwatch_metric_alarm" "unauthorized_api_calls" {
  alarm_name = "unauthorized-api-calls"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods = "1"
  metric_name = "UnauthorizedAPICalls"
  namespace = "CloudTrailMetrics"
  period = "300"
  statistic = "Sum"
  threshold = "5"
  alarm_actions = [aws_sns_topic.security_alerts.arn]
}

ISO27001 Information Security Controls

Annex A controls implementation - technical measures:

A.8.2Classification: Data classification labels (Public/Internal/Confidential/Secret), automated enforcement
A.9.2User Access: Formal access provisioning, regular access reviews, automated deprovisioning
A.10.1Cryptography: Approved algorithms (AES-256, RSA-2048+), key management policy
A.12.6Vulnerability Management: Regular scanning, patch management, penetration testing annual
A.14.2Secure SDLC: Security requirements phase, code review, security testing
A.16.1Incident Management: Detection, response, recovery procedures, post-incident review

Automated Compliance Monitoring

Cloud-native compliance automation tools:

# Azure Policy - automated compliance enforcement
resource "azurerm_policy_assignment" "gdpr_compliance" {
  name = "gdpr-compliance"
  scope = azurerm_resource_group.main.id
  policy_definition_id = "/providers/Microsoft.Authorization/policySetDefinitions/GDPR"

  parameters = jsonencode({
    effect = { value = "Audit" }
  })
}

# AWS Security Hub - continuous compliance
resource "aws_securityhub_account" "main" {}

resource "aws_securityhub_standards_subscription" "cis" {
  standards_arn = "arn:aws:securityhub:region::standards/cis-aws-foundations-benchmark/v/1.4.0"
}

resource "aws_securityhub_standards_subscription" "pci" {
  standards_arn = "arn:aws:securityhub:region::standards/pci-dss/v/3.2.1"
}

# Compliance-as-Code - Terraform Sentinel policies
policy "encryption_at_rest" {
  enforcement_level = "hard-mandatory"
}

rule "s3_encryption_required" {
  condition = all s3_buckets as bucket {
    bucket.server_side_encryption_configuration is not null
  }
}

Compliance Automation ROI

Manual compliance audits: 200-400 hours effort per audit. Automated compliance monitoring reduces audit preparation time by 70%, continuous compliance validation instead of point-in-time checks. Tools: AWS Security Hub, Azure Policy, GCP Security Command Center, Vanta, Drata.

Security Audit Checklist 2025

Need to conduct a security audit of your application but don't know where to start? This checklist is your guide. Comprehensive security audit requires a systematic approach - you can't just "look" at the code and say it's secure.

This checklist is based on NIST Cybersecurity Framework, CIS Benchmarks, and OWASP ASVS - proven standards used by Fortune 500. Go through each point and make sure your application meets the requirements.

1. Authentication & Access Control

MFA enforced for all accounts (admin mandatory, users recommended)
Password policy: minimum 12 chars, complexity requirements, rotation 90 days
RBAC implementation with least privilege principle
Session management: secure tokens, timeout 30min inactivity, logout functionality
Account lockout after 5 failed login attempts
OAuth/OIDC implementation for third-party integrations

2. Data Protection

Encryption at rest: AES-256 for databases, file storage, backups
Encryption in transit: TLS 1.3, HSTS headers, certificate expiration monitoring
Key management: centralized key vault, rotation policy, access auditing
Backup encryption and off-site storage, test restore quarterly
PII/PHI data masking in non-production environments
Data retention policies with automated purging

3. Application Security

OWASP Top 10 verification in latest release
SAST/DAST/SCA automated in CI/CD pipeline
Dependency vulnerability scanning, update critical within 7 days
Input validation all endpoints, output encoding XSS prevention
API security: rate limiting, authentication, input validation
Security headers: CSP, X-Frame-Options, X-Content-Type-Options

4. Infrastructure Security

Network segmentation: DMZ, internal zones, database tier isolation
Firewall rules: deny by default, minimal open ports, regular review
Container security: image scanning, runtime protection, minimal base images
Kubernetes security: RBAC, network policies, pod security standards
Patch management: OS/runtime updates within 30 days, critical within 7 days
IDS/IPS deployment, DDoS protection, WAF for web applications

5. Monitoring & Logging

Centralized logging: SIEM integration, log retention 12 months
Security event monitoring: failed logins, privilege escalation, data access
Real-time alerting for security incidents, 24/7 monitoring
Audit logging: who/what/when for all privileged operations
Log integrity: tamper-proof storage, encryption, access controls
Threat intelligence feeds integration, anomaly detection

6. Incident Response

Incident response plan documented, reviewed quarterly
IR team roles defined, contact list current, escalation procedures
Tabletop exercises semi-annual, lessons learned documented
Forensic capabilities: log preservation, chain of custody procedures
Communication plan: internal notification, customer communication, legal/PR
Recovery procedures: backup restore, service restoration, validation

Penetration Testing Schedule

Regular external validation by security professionals:

Annual full penetration test: External vendor, comprehensive scope, remediation verification
Quarterly vulnerability assessment: Automated + manual verification, trending analysis
Ad-hoc testing: Major releases, new features, architecture changes
Bug bounty program: Continuous testing by security researchers, responsible disclosure

Frequently Asked Questions

What are the most important changes in OWASP Top 10 2025?

OWASP Top 10 2025 adds three new threat categories. Insecure Design (A04) refers to fundamental architecture flaws - those you can't fix with a patch. Software and Data Integrity Failures (A08) is the response to supply chain attacks like SolarWinds. Server-Side Request Forgery (A10) is a growing problem in cloud architectures. Injection drops from #1 to #3 thanks to the popularization of ORMs and prepared statements, but Broken Access Control still reigns as the #1 threat - 94% of applications have this vulnerability.

What is the difference between SAST and DAST?

SAST (Static Application Security Testing) is code analysis without running the application - like reading a recipe without cooking. You find errors in source code during the development phase. DAST (Dynamic Application Security Testing) tests a running application - like a hacker trying to break into your system. You need both: SAST will find hardcoded secrets and SQL injection in code, DAST will detect configuration errors and authorization problems at runtime. Best results: SAST in CI/CD with every pull request + DAST weekly in staging.

How to implement DevSecOps in an existing CI/CD pipeline?

Start with small steps - don't try to change everything at once. Step 1: Add SAST (e.g., Semgrep) to pull request checks - this will take you 30 minutes. Step 2: Enable SCA (dependency scanning) - npm audit or Snyk, another 15 minutes. Step 3: Container scanning for Docker images - Trivy in your pipeline. Step 4: DAST in staging environment - OWASP ZAP once a week. Key: automate everything, zero manual checks. Every pipeline stage should have a security gate - if it finds a critical vulnerability, deployment fails.

What are GDPR requirements for application security?

GDPR requires specific technical safeguards, not generalities. You must have: encryption of personal data in transit (TLS 1.3 minimum) and at rest (AES-256), access controls with least privilege principle (RBAC), audit logging of every access to personal data with 12-month retention, breach detection within 72 hours, privacy by design from the design phase, ability to export user data (right to portability) and delete on request (right to erasure). All of this should be automated - manual processes are a recipe for disaster during an audit.

What should a security audit checklist contain?

Your security audit checklist should cover 6 main areas: 1) Authentication & Access Control - MFA, RBAC, session management, 2) Data Protection - encryption at rest/transit, key management, backups, 3) Application Security - OWASP Top 10 compliance, SAST/DAST/SCA results, dependency vulnerabilities, 4) Infrastructure Security - network segmentation, firewall rules, patch management, container/Kubernetes security, 5) Monitoring & Logging - SIEM, security events, audit trails, incident detection, 6) Compliance - GDPR/SOC2/ISO27001 requirements, documentation, policies. Plus annual penetration test by external vendor and quarterly vulnerability assessments. Use standards: NIST Cybersecurity Framework, CIS Benchmarks, OWASP ASVS.

Summary: Security-First in 2025

You've reached the end of this guide - now it's time for action. Application security in 2025 isn't optional, it's a business necessity for your company. We've covered five key areas: OWASP Top 10 shows the most critical threats to your application, DevSecOps integrates cybersecurity into your development workflow, automated testing (SAST/DAST/SCA) ensures continuous validation, API security protects modern architectures, and compliance frameworks (GDPR/SOC2/ISO27001) require specific technical safeguards.

Numbers don't lie: organizations with mature security practices have 60% fewer incidents, 50% faster remediation time, and 70% reduction in compliance effort. Investment in a comprehensive security strategy is an investment in your brand reputation, customer trust, and business continuity. Remember: web application security doesn't cost - lack of security costs millions in data breaches and customer loss.

Need help securing your application?

I specialize in comprehensive security assessments, DevSecOps implementation, fixing OWASP Top 10 vulnerabilities, automated security testing, and preparing for compliance audits (GDPR/SOC2/ISO27001). I've conducted dozens of security audits and helped companies secure their applications against attacks. Let's schedule a free 30-minute consultation where we'll discuss your application security.

Related Articles

Application Security Best Practices 2025 - Comprehensive Guide | Wojciechowski.app