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.

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 - 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 vulnerabilitiesAzure 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.yamlInfrastructure 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 actionsShift-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-secretsDetects: 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 runAdvantage: 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
fiTool 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:
- BadBotGraphQL 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 - 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:
// 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:
# 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:
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
2. Data Protection
3. Application Security
4. Infrastructure Security
5. Monitoring & Logging
6. Incident Response
Penetration Testing Schedule
Regular external validation by security professionals:
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.