Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
523222a
feat(lab1): juice shop deploy + PR template + triage report
Jun 12, 2026
b13efb5
feat(lab1): triage report fix
Jun 12, 2026
2f82cb6
Merge pull request #1 from Wilikson173/feature/lab1
Wilikson173 Jun 12, 2026
ae27928
feat(lab2): Threagile threat model + secure variant risk diff
Jun 12, 2026
49c874c
feat(lab2): Threagile threat model + secure variant + auth flow bonus
Jun 12, 2026
7420a0e
Merge pull request #2 from Wilikson173/feature/lab2
Wilikson173 Jun 19, 2026
c12a034
test: first signed commit
Wilikson173 Jun 19, 2026
a807e63
feat(lab3): add pre-commit gitleaks configuration
Wilikson173 Jun 19, 2026
5ed04f0
docs(lab3): complete lab3 submission
Wilikson173 Jun 19, 2026
f2eec75
Merge pull request #3 from Wilikson173/feature/lab3
Wilikson173 Jun 19, 2026
afb8a12
feat(lab4): complete SBOM, SCA, Trivy comparison, attestation
Wilikson173 Jun 19, 2026
653cee3
ZAP baseline,auth, Semgrep and SAST/DAST correlation
Jun 26, 2026
6f0d27b
Merge pull request #4 from Wilikson173/feature/lab4
Wilikson173 Jun 26, 2026
eb8cd48
Merge pull request #5 from Wilikson173/feature/lab5
Wilikson173 Jun 26, 2026
87bebc9
Checkov, KICS scans and custom policy
Jun 26, 2026
fcbfcd6
Merge pull request #6 from Wilikson173/feature/lab6
Wilikson173 Jun 26, 2026
5abbc27
feat(lab7): trivy + PSS restricted + conftest gate
Jul 3, 2026
7283bef
Merge pull request #7 from Wilikson173/feature/lab7
Wilikson173 Jul 3, 2026
ec32081
feat(lab8): cosign sign + SBOM/provenance attestations + blob signing
Jul 3, 2026
95eef33
Merge pull request #8 from Wilikson173/feature/lab8
Wilikson173 Jul 3, 2026
d5ee923
feat(lab9): falco custom rules + conftest hardening policies + bonus …
Jul 10, 2026
02887a6
Merge pull request #9 from Wilikson173/feature/lab9
Wilikson173 Jul 10, 2026
e4c6401
feat(lab10): defectdojo governance report + capstone walkthrough
Jul 10, 2026
5cc4681
Merge pull request #10 from Wilikson173/feature/lab10
Wilikson173 Jul 10, 2026
4c4b9ed
feat(lab11): hardened nginx + WAF sidecar with OWASP CRS
Jul 17, 2026
c070671
Merge pull request #11 from Wilikson173/feature/lab11
Wilikson173 Jul 17, 2026
5d266fb
feat(lab12): complete kata vs runc comparison with escape PoC
Jul 17, 2026
790e8d4
feat(lab12): complete kata vs runc comparison with escape PoC
Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Goal
<!-- One sentence: what does this PR deliver? -->

## Changes
<!-- Bullet list of all files added or modified -->
-

## Testing
<!-- Commands you ran and the output you observed -->
```
# Example:
docker ps --filter name=juice-shop
curl -s -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:3000
```

## Artifacts & Screenshots
<!-- Links to files in this PR; embed screenshots where useful -->
- `submissions/labN.md`

---

## Checklist
- [ ] Title follows `feat(labN): <topic>` style
- [ ] No secrets or large temp files committed
- [ ] Submission file exists at `submissions/labN.md`
70 changes: 70 additions & 0 deletions .github/workflows/lab1-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: lab1-smoke

on:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
smoke-test:
name: Juice Shop smoke test
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Pull and start Juice Shop
run: |
docker run -d --name juice-shop \
-p 127.0.0.1:3000:3000 \
bkimminich/juice-shop:v20.0.0

- name: Wait for Juice Shop to be ready (max 60s)
run: |
echo "Waiting for Juice Shop to start..."
for i in $(seq 1 30); do
if curl --silent --fail http://localhost:3000/rest/admin/application-version > /dev/null; then
echo "Juice Shop is up after $((i * 2))s"
exit 0
fi
echo "Attempt $i/30 — not ready yet, sleeping 2s..."
sleep 2
done
echo "ERROR: Juice Shop did not start within 60 seconds"
docker logs juice-shop
exit 1

- name: Verify homepage returns HTTP 200
run: |
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000)
echo "Homepage HTTP status: $HTTP_CODE"
if [ "$HTTP_CODE" != "200" ]; then
echo "ERROR: Expected 200, got $HTTP_CODE"
exit 1
fi
echo "HTTP 200 confirmed — smoke test passed."

- name: Verify version endpoint
run: |
RESPONSE=$(curl -s http://localhost:3000/rest/admin/application-version)
echo "Version endpoint response: $RESPONSE"
echo "$RESPONSE" | grep -q '"version":"20.0.0"' || (echo "ERROR: unexpected version response" && exit 1)
echo "Version check passed."

- name: Verify product count
run: |
COUNT=$(curl -s http://localhost:3000/api/Products | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d['data']))")
echo "Product count: $COUNT"
if [ "$COUNT" -lt 1 ]; then
echo "ERROR: No products returned"
exit 1
fi
echo "Product count check passed: $COUNT products found."

- name: Cleanup
if: always()
run: docker rm -f juice-shop || true
11 changes: 11 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.26.0
hooks:
- id: gitleaks

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: detect-private-key
- id: check-added-large-files
93 changes: 20 additions & 73 deletions labs/lab11/reverse-proxy/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,70 +1,14 @@
user nginx;
worker_processes auto;

events { worker_connections 1024; }

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 10;
server_tokens off;
gzip off;

# Security-focused logs
log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct=$upstream_connect_time '
'urt=$upstream_response_time';
access_log /var/log/nginx/access.log security;
error_log /var/log/nginx/error.log warn;

# Upstream app
upstream juice {
server juice:3000;
keepalive 32;
}

# Rate limit zone for login
# ~10 req/min per IP, burst of 5
# Rate limiting zones (должны быть внутри http)
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
limit_req_status 429;

map $http_upgrade $connection_upgrade { default upgrade; '' close; }

# Common proxy settings
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;
# Prevent upstream TLS BREACH vector by disabling compression from upstream
proxy_set_header Accept-Encoding "";
proxy_read_timeout 30s;
proxy_send_timeout 30s;
proxy_connect_timeout 5s;
proxy_hide_header X-Powered-By;
# Hide upstream headers to avoid duplicates and enforce policy at the proxy
proxy_hide_header X-Frame-Options;
proxy_hide_header X-Content-Type-Options;
proxy_hide_header Referrer-Policy;
proxy_hide_header Permissions-Policy;
proxy_hide_header Cross-Origin-Opener-Policy;
proxy_hide_header Cross-Origin-Resource-Policy;
proxy_hide_header Content-Security-Policy;
proxy_hide_header Content-Security-Policy-Report-Only;
proxy_hide_header Access-Control-Allow-Origin;

# HTTP server (redirect to HTTPS)
# HTTP server — redirect to HTTPS
server {
listen 8080;
listen [::]:8080;
server_name _;

# Core headers (also on redirects)
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Expand All @@ -85,26 +29,25 @@ http {

ssl_certificate /etc/nginx/certs/localhost.crt;
ssl_certificate_key /etc/nginx/certs/localhost.key;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:EECDH+AESGCM:EDH+AESGCM";
ssl_prefer_server_ciphers on;

ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;

ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# ssl_ciphers "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256";
ssl_ecdh_curve X25519:secp384r1;

ssl_stapling off;
# If using a publicly-trusted certificate, you may enable OCSP stapling:
# ssl_stapling on;
# ssl_stapling_verify on;
# resolver 1.1.1.1 8.8.8.8 valid=300s;
# resolver_timeout 5s;
# ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
ssl_stapling_verify off;

client_max_body_size 2m;
client_body_timeout 10s;
client_header_timeout 10s;
keepalive_timeout 10s;
send_timeout 10s;

# Security headers (include HSTS here only)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
Expand All @@ -117,11 +60,15 @@ http {
location = /rest/user/login {
limit_req zone=login burst=5 nodelay;
limit_req_log_level warn;
proxy_pass http://juice;
proxy_pass http://juice:3000;
}

location / {
proxy_pass http://juice;
proxy_pass http://juice:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
23 changes: 23 additions & 0 deletions labs/lab11/waf/docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
waf:
image: owasp/modsecurity-crs:nginx
container_name: lab11-waf
restart: unless-stopped
depends_on:
- nginx
environment:
BACKEND: "https://nginx:8443"
PROXY_SSL_VERIFY: "no"
PORT: "8080"

MODSEC_RULE_ENGINE: "on"
MODSEC_AUDIT_ENGINE: "RelevantOnly"
MODSEC_AUDIT_LOG_RELEVANT_STATUS: "^(?:5|4(?!04))"
MODSEC_AUDIT_LOG: "/dev/stdout"
MODSEC_AUDIT_LOG_FORMAT: "JSON"

PARANOIA: "1"
BLOCKING_PARANOIA: "1"
TX_ANOMALY_SCORE_THRESHOLD: "5"
ports:
- "8090:8080"
2 changes: 2 additions & 0 deletions labs/lab12/results/dev-diff.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1d0
< core
4 changes: 4 additions & 0 deletions labs/lab12/results/io-bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
=== runc I/O ===
104857600 bytes (100.0MB) copied, 0.007597 seconds, 12.9GB/s
=== kata I/O ===
104857600 bytes (100.0MB) copied, 0.008624 seconds, 11.3GB/s
5 changes: 5 additions & 0 deletions labs/lab12/results/kata-caps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
14 changes: 14 additions & 0 deletions labs/lab12/results/kata-devs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fd
full
mqueue
null
ptmx
pts
random
shm
stderr
stdin
stdout
tty
urandom
zero
2 changes: 2 additions & 0 deletions labs/lab12/results/kata-escape-attempt.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
time="2026-07-17T22:22:45+03:00" level=warning msg="cannot set cgroup manager to \"systemd\" for runtime \"io.containerd.kata.v2\""
time="2026-07-17T22:22:47+03:00" level=fatal msg="failed to create shim task: Creating container device LinuxDevice { path: \"/dev/full\", typ: C, major: 1, minor: 7, file_mode: Some(438), uid: Some(0), gid: Some(0) }\n\nCaused by:\n EEXIST: File exists\n\nStack backtrace:\n 0: <unknown>\n 1: <unknown>\n 2: <unknown>\n 3: <unknown>\n 4: <unknown>\n 5: <unknown>\n 6: <unknown>\n 7: <unknown>\n 8: <unknown>\n 9: <unknown>\n 10: <unknown>\n\nStack backtrace:\n 0: <unknown>\n 1: <unknown>\n 2: <unknown>\n 3: <unknown>\n 4: <unknown>\n 5: <unknown>\n 6: <unknown>\n 7: <unknown>\n 8: <unknown>\n 9: <unknown>\n 10: <unknown>\n 11: <unknown>\n 12: <unknown>\n 13: <unknown>\n 14: <unknown>\n 15: <unknown>\n 16: <unknown>\n 17: <unknown>\n 18: <unknown>\n 19: <unknown>\n 20: <unknown>\n 21: <unknown>\n 22: <unknown>: unknown"
5 changes: 5 additions & 0 deletions labs/lab12/results/kata-kernel.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
time="2026-07-17T22:21:21+03:00" level=warning msg="cannot set cgroup manager to \"systemd\" for runtime \"io.containerd.kata.v2\""
Linux 21ef90bc1e2f 6.18.35 #1 SMP Mon Jun 15 12:55:58 UTC 2026 x86_64 Linux
processor : 0
vendor_id : GenuineIntel
cpu family : 6
5 changes: 5 additions & 0 deletions labs/lab12/results/runc-caps.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
CapInh: 0000000000000000
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
15 changes: 15 additions & 0 deletions labs/lab12/results/runc-devs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
core
fd
full
mqueue
null
ptmx
pts
random
shm
stderr
stdin
stdout
tty
urandom
zero
4 changes: 4 additions & 0 deletions labs/lab12/results/runc-kernel.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Linux be6c2de605fc 6.12.33+kali-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.12.33-1kali1 (2025-06-25) x86_64 Linux
processor : 0
vendor_id : GenuineIntel
cpu family : 6
12 changes: 12 additions & 0 deletions labs/lab12/results/startup-bench.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
=== runc ===
1: .534444087 s
2: .506874467 s
3: .511743839 s
4: .508918350 s
5: .537591629 s
=== kata ===
1: 2.182025002 s
2: 1.969614788 s
3: 2.150948127 s
4: 2.038093392 s
5: 2.245332786 s
Loading