Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4b0b7ee
feat(lab1): add github actions smoke test workflow
SamiKO228 Jun 12, 2026
c8ebb99
fix(workflow): fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
727146f
fix(workflow): 2nd fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
43b7c55
fix(workflow): 3rd fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
7dff1d2
fix(workflow): 4th fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
5b210cd
fix(workflow): 5th fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
67ea879
fix(workflow): 6th fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
62141f5
fix(workflow): 7th fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
7b1eb41
fix(workflow): 8th fix indentation and syntax in smoke-test
SamiKO228 Jun 12, 2026
f267fb8
feat(lab1): juice shop deploy + PR template + triage report
SamiKO228 Jun 12, 2026
00e2dcf
feat(lab3): SSH signing + gitleaks pre-commit + history rewrite practice
SamiKO228 Jun 18, 2026
e4c2981
Merge remote-tracking branch 'origin/feature/lab1' into feature/lab4
SamiKO228 Jun 19, 2026
a013a44
Merge remote-tracking branch 'origin/feature/lab3' into feature/lab4
SamiKO228 Jun 19, 2026
5476dc7
chore(pre-commit): increase large-file threshold for SBOM artifacts
SamiKO228 Jun 19, 2026
4a04045
feat(lab4): juice-shop SBOM + Grype/Trivy comparison + sign-ready att…
SamiKO228 Jun 19, 2026
47a04c2
feat(lab5): ZAP baseline + auth + Semgrep + correlation
SamiKO228 Jun 26, 2026
1a0d3f9
feat(lab6): Checkov + KICS scans + custom policy
SamiKO228 Jun 26, 2026
6e0162f
feat(lab7): trivy + PSS restricted + conftest gate
SamiKO228 Jul 3, 2026
b278dc2
feat(lab8): cosign sign + SBOM/provenance attestations + blob signing
SamiKO228 Jul 3, 2026
269370b
feat(lab9): falco custom rules + conftest hardening policies
SamiKO228 Jul 10, 2026
5be0aa0
feat(lab10): defectdojo governance report + capstone walkthrough
SamiKO228 Jul 10, 2026
52d0509
feat(lab11): hardened nginx + WAF sidecar
SamiKO228 Jul 17, 2026
4bfe252
chore: resolve merge conflict in nginx.conf
SamiKO228 Jul 17, 2026
a6c0e9c
feat(lab12): kata vs runc isolation + perf + escape PoC
SamiKO228 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
18 changes: 18 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Goal
[Опиши в одном предложении, что делает этот PR]

## Changes
* Добавлен отчет submissions/labX.md
* Добавлены скриншоты/артефакты (если есть)

## Testing
* Запущены команды: `docker ps`, `curl`
* Все проверки пройдены локально

## Artifacts & Screenshots
* [Ссылки или изображения]

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

on:
pull_request:
branches:
- main

permissions:
contents: read

jobs:
smoke-test:
runs-on: ubuntu-latest

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: 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 become ready
run: |
for i in $(seq 1 30); do
if curl --silent --fail http://127.0.0.1:3000/rest/admin/application-version >/dev/null; then
echo "Juice Shop is ready"
exit 0
fi
echo "Waiting for Juice Shop..."
sleep 2
done
echo "Juice Shop does not seem to be ready"
docker logs juice-shop || true
exit 1

- name: Verify homepage
run: |
curl --silent --fail http://127.0.0.1:3000 >/dev/null
echo "Homepage returned HTTP 200"
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,8 @@ node_modules/
.venv/
.DS_Store
*.swp
labs/lab4/grype-results.json
labs/lab4/trivy-results.json
labs/lab4/grype-from-sbom.*
labs/lab4/trivy.*
labs/lab11/results/
12 changes: 12 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.28.0
hooks:
- id: gitleaks

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: detect-private-key
exclude: ^labs/lab6/
- id: check-added-large-files
94 changes: 82 additions & 12 deletions labs/lab11/reverse-proxy/nginx.conf
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
user nginx;
worker_processes auto;
worker_processes 1;

events { worker_connections 1024; }
events {
worker_connections 1024;
}

http {
<<<<<<< feature/lab11
include /etc/nginx/mime.types;
default_type application/octet-stream;

# Rate Limiting & Connection Limiting Zones
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
limit_conn_zone $binary_remote_addr zone=conn:10m;
limit_req_status 429;

server {
listen 8080;
listen [::]:8080;
server_name localhost;
return 308 https://$host:8443$request_uri;
=======
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
Expand Down Expand Up @@ -60,8 +76,8 @@ http {

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

# Core headers (also on redirects)
Expand All @@ -73,13 +89,13 @@ http {
add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'" always;

return 308 https://$host:8443$request_uri;
return 308 https://$host$request_uri;
}

# HTTPS server
server {
listen 8443 ssl;
listen [::]:8443 ssl;
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name _;

Expand Down Expand Up @@ -118,10 +134,64 @@ http {
limit_req zone=login burst=5 nodelay;
limit_req_log_level warn;
proxy_pass http://juice;
>>>>>>> main
}

location / {
proxy_pass http://juice;
server {
listen 8443 ssl;
listen [::]:8443 ssl;
http2 on;
server_name localhost;

# Connection Limits & Fail-Closed Timeouts
limit_conn conn 50;
client_body_timeout 10s;
client_header_timeout 10s;

# TLS 1.3 & Cipher Hardening (добавлен ECDHE для совместимости с OpenSSL 3.0)
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
ssl_ecdh_curve X25519:secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 1.1.1.1 valid=300s;

ssl_certificate /etc/nginx/certs/localhost.crt;
ssl_certificate_key /etc/nginx/certs/localhost.key;

add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'" always;

location /rest/user/login {
limit_req zone=login burst=5 nodelay;

proxy_read_timeout 30s;
proxy_connect_timeout 5s;
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;
}

location / {
proxy_read_timeout 30s;
proxy_connect_timeout 5s;
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;
}
}
}
}
}
13 changes: 13 additions & 0 deletions labs/lab11/waf/docker-compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
services:
waf:
image: owasp/modsecurity-crs:nginx-alpine
container_name: lab11-waf-1
ports:
- "8081:80"
environment:
- PARANOIA=1
- SEC_RULE_ENGINE=On
- BACKEND=http://juice:3000
- MODSEC_AUDIT_LOG_TYPE=Serial
- MODSEC_AUDIT_LOG_FORMAT=JSON
- MODSEC_AUDIT_LOG=/var/log/modsecurity/audit/audit.log
13 changes: 13 additions & 0 deletions labs/lab4/juice-shop-attestation.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions labs/lab4/juice-shop.cdx.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions labs/lab4/juice-shop.spdx.json

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions labs/lab6/policies/my-custom-policy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
metadata:
id: CKV2_CUSTOM_1
name: "Ensure S3 buckets define a DataClassification tag"
category: "CONVENTION"
severity: "MEDIUM"

definition:
cond_type: "attribute"
resource_types:
- "aws_s3_bucket"
attribute: "tags.DataClassification"
operator: "exists"
104 changes: 104 additions & 0 deletions labs/lab7/k8s/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: juice-shop
namespace: juice-shop
labels:
app: juice-shop
spec:
replicas: 1
selector:
matchLabels:
app: juice-shop
template:
metadata:
labels:
app: juice-shop
spec:
serviceAccountName: juice-shop-sa
automountServiceAccountToken: false

securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: RuntimeDefault

initContainers:
- name: seed-writable-dirs
image: bkimminich/juice-shop@sha256:fd58bdc9745416afce8184ee0666278a436574633ea7880365153a63bfd418b0
command:
- /nodejs/bin/node
- -e
- |
const fs = require('fs');
fs.cpSync('/juice-shop/data', '/data-vol', { recursive: true });
fs.cpSync('/juice-shop/ftp', '/ftp-vol', { recursive: true });
fs.cpSync('/juice-shop/frontend/dist', '/frontend-dist-vol', { recursive: true });
fs.cpSync('/juice-shop/.well-known', '/well-known-vol', { recursive: true });
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: app-data
mountPath: /data-vol
- name: app-ftp
mountPath: /ftp-vol
- name: frontend-dist
mountPath: /frontend-dist-vol
- name: well-known
mountPath: /well-known-vol

containers:
- name: juice-shop
image: bkimminich/juice-shop@sha256:fd58bdc9745416afce8184ee0666278a436574633ea7880365153a63bfd418b0
ports:
- containerPort: 3000
protocol: TCP

securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL

resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"

volumeMounts:
- name: tmp
mountPath: /tmp
- name: app-logs
mountPath: /juice-shop/logs
- name: app-data
mountPath: /juice-shop/data
- name: app-ftp
mountPath: /juice-shop/ftp
- name: frontend-dist
mountPath: /juice-shop/frontend/dist
- name: well-known
mountPath: /juice-shop/.well-known

volumes:
- name: tmp
emptyDir: {}
- name: app-logs
emptyDir: {}
- name: app-data
emptyDir: {}
- name: app-ftp
emptyDir: {}
- name: frontend-dist
emptyDir: {}
- name: well-known
emptyDir: {}
Empty file added labs/lab7/k8s/namespace.yaml
Empty file.
35 changes: 35 additions & 0 deletions labs/lab7/k8s/networkpolicy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: juice-shop-netpol
namespace: juice-shop
spec:
podSelector:
matchLabels:
app: juice-shop
policyTypes:
- Ingress
- Egress

ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: juice-shop
ports:
- protocol: TCP
port: 3000

egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
- ports:
- protocol: TCP
port: 443
Empty file.
Loading