Why this matters now
Even if you’re outside the EU, your EU customers are pushing NIS 2 obligations downstream via MSAs, DPAs, and security schedules. To keep deals moving (and renewals clean), you need a fast, evidence-driven plan that proves reasonable security, incident readiness, and continuous improvement—without boiling the ocean.
This playbook gives Non-EU vendors a 60-day, engineering-first plan to reach a credible baseline, complete with code, KPIs, ISO 27001 alignment, and a customer-ready attestation packet. For quick gap scans to seed your backlog, you can use our Free Website Vulnerability Scanner and attach before/after evidence to tickets.
Need help compressing timelines? Our team runs focused **[Risk Assessment Services]…
Why this matters now
Even if you’re outside the EU, your EU customers are pushing NIS 2 obligations downstream via MSAs, DPAs, and security schedules. To keep deals moving (and renewals clean), you need a fast, evidence-driven plan that proves reasonable security, incident readiness, and continuous improvement—without boiling the ocean.
This playbook gives Non-EU vendors a 60-day, engineering-first plan to reach a credible baseline, complete with code, KPIs, ISO 27001 alignment, and a customer-ready attestation packet. For quick gap scans to seed your backlog, you can use our Free Website Vulnerability Scanner and attach before/after evidence to tickets.
Need help compressing timelines? Our team runs focused Risk Assessment Services and hands-on Remediation Services to accelerate this 60-day track with auditor-ready artifacts.
Who’s in scope via supply chains and contracts
If you process, host, monitor, or support systems for EU customers in NIS 2 sectors—or you’re a material supplier to those who do—you’ll likely see NIS 2 clauses appear in:
- Master Service Agreements and Security Addenda
- Data Processing Agreements and Sub-processor terms
- RFPs/RFIs and vendor risk questionnaires
Practical test: if an EU customer asks for “NIS 2 evidence,” “incident reporting readiness,” “patch SLAs,” or “risk register excerpts,” you’re functionally in scope—treat it like a contractual requirement.
The 60-Day Plan (four 2-week sprints)
Sprint 1 (Days 1–14): Asset inventory & baseline controls
Objectives
- Centralize asset & service inventory (cloud + endpoints + SaaS)
- Fix internet-facing quick wins (TLS, headers, auth exposures)
- Stand up logging & evidence storage
Code & configs
Cloud asset snapshot (multi-cloud, Python)
# /ops/asset_snapshot.py
import json, subprocess, datetime, pathlib
ts = datetime.datetime.utcnow().strftime("%Y-%m-%dT%H%M%SZ")
def sh(cmd): return subprocess.check_output(cmd, shell=True, text=True).strip()
inventory = {"ts": ts, "aws":{}, "gcp":{}, "azure":{}}
# AWS EC2 + ELB + S3 (requires AWS CLI + creds)
inventory["aws"]["ec2"] = json.loads(sh("aws ec2 describe-instances --output json"))
inventory["aws"]["elb"] = json.loads(sh("aws elbv2 describe-load-balancers --output json"))
inventory["aws"]["s3"] = json.loads(sh("aws s3api list-buckets --output json"))
# GCP instances
# gcloud auth configure first
inventory["gcp"]["compute"] = json.loads(sh("gcloud compute instances list --format=json"))
# Azure VMs
inventory["azure"]["vms"] = json.loads(sh("az vm list --show-details -o json"))
pathlib.Path("evidence/assets").mkdir(parents=True, exist_ok=True)
open(f"evidence/assets/inventory_{ts}.json","w").write(json.dumps(inventory, indent=2))
print("Saved asset inventory", ts)
Linux web surface quick-hardening (NGINX)
# /etc/nginx/conf.d/ssl.conf
ssl_protocols TLSv1.2 TLSv1.3;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "DENY";
Evidence binder structure
mkdir -p evidence/{assets,scans,configs,logs}/$(date +%F)
Seed your backlog with pre-fix evidence (Free Scanner)
- Run a quick scan against public URLs; export results as PDF/CSV.
- Attach the pre-fix file to the ticket; retest and attach post-fix. Use: Website Vulnerability Scanner Online free. For context, see our SOC 2 evidence article showing how to capture scanner screenshots/reports as artifacts.
Screenshot of the free tools webpage where you can access security assessment tools.
Related reading: 21 Essential SOC 2 Type II Evidence Artifacts—includes examples of storing scanner screenshots/reports as proof.
Sprint 2 (Days 15–28): Incident readiness & reporting drill
Objectives
- Define SEV ladder, on-call, and T+24h customer notify flow
- Practice a tabletop: detection → triage → comms → forensics → lessons
- Capture runbooks and IR metrics as evidence
Runbook (YAML)
# /runbooks/incident_webapp.yaml
severity: SEV-2
triggers:
- multiple 5xx spikes > 3x baseline 10m
- WAF blocks > 10k/min or auth failures > 2% users
first_response:
- page: "oncall-web@pagerduty"
- gather: "nginx access/error logs, WAF events, APM traces"
- contain: "disable new signups, enable read-only if needed"
communications:
internal: "slack #inc-webapp, exec-brief 60m"
customer: "draft T+8h, send T+24h if incident confirmed"
evidence:
- attach: "cloudtrail exports, kibana searches, timeline.md"
closure:
- lessons: "PRs linked, playbook updated, KPI captured"
Detection queries
Splunk (admin logins outside expected geo)
index=auth action=login role=admin NOT src_country="expected"
| stats count by user, src_ip, src_country
Nginx error spike alert (bash + grep)
grep "$(date -u +%d/%b/%Y:%H)" /var/log/nginx/error.log | wc -l
# hook into cron + alerting if > threshold
Sprint 3 (Days 29–42): Patch SLAs & vulnerability closure
Objectives
- Define Patch SLAs (e.g., Critical 72h, High 7d, Medium 30d)
- Enforce auto-updates where safe; ticket exceptions
- Track closure KPIs (exposure age, % within SLA)
Windows patch export (PowerShell)
Get-HotFix | Select HotFixID,InstalledOn |
Sort-Object InstalledOn -Descending |
Export-Csv evidence/patches_win_$(Get-Date -Format yyyy-MM-dd).csv -NoType
Linux unattended security updates (Debian/Ubuntu)
apt-get update && apt-get install -y unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
AWS SSM Patch Baseline (CLI snippet)
aws ssm create-patch-baseline \
--name "ProdSecurity" --approval-rules '...
{"PatchRules":[{"PatchFilterGroup":{"PatchFilters":[
{"Key":"PATCHELIGIBILITY","Values":["SECURITY"]}]},
"ApproveAfterDays":2,"ComplianceLevel":"CRITICAL"}]}'
Vuln closure KPI (SQL on your ticket DB)
-- % findings closed within SLA by severity (last 30 days)
SELECT severity,
100.0*SUM(CASE WHEN closed_at <= due_at THEN 1 ELSE 0 END)/COUNT(*) AS pct_within_sla
FROM findings
WHERE created_at >= NOW() - INTERVAL '30 day'
GROUP BY severity;
When you’re ready to formalize this, our Remediation Services team can pair with your engineers to close high-risk items and produce clear before/after evidence for customers.
Sprint 4 (Days 43–60): DDoS posture, KPIs & “living” risk register
Objectives
- Add rate-limit/WAF controls; verify metrics and fallbacks
- Publish board-ready KPIs (rolling)
- Maintain a living risk register mapped to ISO 27001
NGINX basic rate limiting
# /etc/nginx/conf.d/ratelimit.conf
limit_req_zone $binary_remote_addr zone=reqzone:10m rate=10r/s;
server {
location / {
limit_req zone=reqzone burst=20 nodelay;
}
}
Cloudflare (Terraform sketch)
resource "cloudflare_rate_limit" "login" {
zone_id = var.zone_id
threshold = 100
period = 60
action { mode = "managed_challenge" }
match { request { url = "/login" methods = ["POST"] } }
enabled = true
}
Living risk register (YAML)
# /risk/risk_register.yaml
- id: R-001
desc: Internet-exposed login susceptible to credential stuffing
inherent: High
controls: [WAF-01, RL-01, MFA-01]
iso27001: [A.5.15, A.8.16, A.8.20]
owner: eng-appsec
due: 2025-12-15
treatment: Reduce
evidence: ["evidence/waf/waf_rules_2025-11-11.json","kpis/kpi_ddos_2025-11.csv"]
status: Open
Board-ready KPIs (CSV emitted weekly)
# /ops/kpis.sh
now=$(date -u +%F)
mkdir -p kpis
echo "name,value,date" > kpis/$now.csv
echo "patch_within_sla,$(psql -d sec -At -f queries/pct_within_sla.sql),$now" >> kpis/$now.csv
echo "mfa_coverage,$(python ops/mfa_coverage.py),$now" >> kpis/$now.csv
echo "waf_blocks_last_7d,$(jq '.events|length' logs/waf_last7d.json),$now" >> kpis/$now.csv
Aligning with ISO 27001 (reuse evidence, cut time)
Rather than inventing new artifacts, map what you already produce to Annex A controls:
- Access control & MFA → user/admin inventory, SSO enforcement (A.5.15, A.8.2, A.8.3)
- Vulnerability mgmt & patching → scanner exports, SLA KPIs, change tickets (A.8.8, A.8.9)
- Logging & monitoring → SIEM queries, CloudTrail retention, tamper-evident chains (A.8.15, A.8.16)
- Business continuity → backup restore tests, DR targets & actuals (A.5.29, A.5.30)
If you need ready-to-reuse templates and binders, our Risk Assessment Services package includes ISO 27001 mappings that align with the evidence types above.
What to show customers: the attestation packet
Bundle the following into a single PDF/ZIP and share through your customer’s secure channel:
- Executive attestation (1 page)
We, <Company>, attest that we maintain reasonable security controls aligned to NIS 2 expectations for suppliers. Evidence enclosed:
assets, patch SLAs & KPIs, IR runbooks, tabletop report, scanner pre/post-fix, WAF/rate-limits, and a current risk register excerpt.
Signed: CISO/CTO, Date
- Evidence index (machine-readable)
{
"version": "2025-11-11",
"artifacts": [
{"name":"asset_inventory","path":"evidence/assets/inventory_2025-11-11.json"},
{"name":"scanner_before","path":"evidence/scans/pre_fix_2025-11.pdf"},
{"name":"scanner_after","path":"evidence/scans/post_fix_2025-11.pdf"},
{"name":"ir_runbook","path":"runbooks/incident_webapp.yaml"},
{"name":"ddos_controls","path":"configs/waf/ratelimit.conf"},
{"name":"kpis","path":"kpis/2025-11-11.csv"},
{"name":"risk_register","path":"risk/risk_register.yaml"}
]
}
- Test & runbook excerpts Include sanitized tabletop notes and a short restoration drill log (timestamped).
See how we capture scans and artifacts in SOC 2 Evidence Artifacts; the same pattern satisfies NIS 2 request-lists from customers.
Sample Report to check Website Vulnerability
Sample vulnerability assessment report generated with our free tool, providing insights into possible vulnerabilities.
DEV-oriented quick wins you can ship in two sprints
- Guardrails: branch protection + required reviews (
gh api ... > branch_protection.json) - Evals: integration tests that fail on missing headers/TLS regressions
- Logging: CloudTrail + 365-day retention (IaC), hash-chained daily exports
- Kill-switches: feature flags for read-only mode, signup throttle, or webhooks pause
(We show copy-pasteable examples in the article above; save outputs in /evidence/... for auditors and customers.)
Related internal resources (keep learning)
- 21 Essential SOC 2 Type II Evidence Artifacts – concrete artifacts customers and auditors accept.
- 7 Proven Steps to a Unified Risk Register in 30 Days – build a single, reusable register mapped across frameworks.
- Android Security Bulletin November 2025: 72-Hour Playbook – an example of compressing vulnerability response into SLA windows.
- Browse more posts on our Blog and scan your perimeter with the Free Website Vulnerability Scanner to generate before/after evidence quickly.
Move faster with guided help
- Start with a structured readout and prioritized backlog via Risk Assessment Services.
- Close high-risk items and produce clean customer packets via Remediation Services.