Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ One-sentence description of what this PR delivers.

- [ ] Title uses `feat(labN): <topic>` style
- [ ] No secrets/large temp files committed
- [ ] `submissions/labN.md` present
- [ ] `submissions/labN.md` present
39 changes: 39 additions & 0 deletions .github/workflows/lab1-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Lab1 Smoke Test

on:
pull_request:
branches: [ main ]

permissions:
contents: read

jobs:
smoke:
name: Smoke-test Juice Shop
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Run Juice Shop container
run: |
docker run -d --name juice-shop -p 3000:3000 bkimminich/juice-shop:v20.0.0

- name: Wait for Juice Shop to respond
run: |
for i in $(seq 1 30); do
if curl --silent --fail http://localhost:3000/rest/admin/application-version >/dev/null 2>&1; then
echo "juice-shop healthy"; exit 0
fi
sleep 2
done
echo "juice-shop did not become healthy"; docker logs juice-shop || true; exit 1

- name: Curl homepage
run: |
curl --silent --fail -I http://localhost:3000 | head -n 20

- name: Stop container
if: always()
run: |
docker stop juice-shop || true
147 changes: 147 additions & 0 deletions submissions/lab1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Lab 1 — Submission

## Task 1 — Deploy Juice Shop & Triage Report (6 pts)

## Triage Report: OWASP Juice Shop

### Scope & Asset
- Asset: OWASP Juice Shop (local lab instance)
- Image: `bkimminich/juice-shop:v20.0.0`
- Image digest: `sha256:99779f57113bd47312e8fe7b264ff402ee41da76ddda7f2fc842a92ad51827ce` (from `docker inspect juice-shop --format '{{.Image}}'`)
- Host OS: Ubuntu 24.04
- Docker version: `Docker version 29.4.0, build 9d7ad9f`

### Deployment Details
- Run command used:

```bash
docker run -d --name juice-shop \
-p 127.0.0.1:3000:3000 \
bkimminich/juice-shop:v20.0.0
```
- Access URL: http://127.0.0.1:3000
- Network exposure: 127.0.0.1 only? [x] Yes [ ] No — container bound to localhost
- Container restart policy: default (`no`)

### Health Check
- HTTP code on `/`: `200`
API check (first 200 chars of `/api/Products`):

```json
{"status":"success","data":[{"id":1,"name":"Apple Juice (1000ml)","description":"The all-time classic.","price":1.99,"deluxePrice":0.99,"image":"apple_juice.jpg","createdAt":"2026-06-10T01:28:01.171Z"...
```

- Product count from `/api/Products`: `46`
- Container uptime: Up 12 hours

```text
juice-shop Up 12 hours 127.0.0.1:3000->3000/tcp
```

### Initial Surface Snapshot (from browser exploration)
- Login/Registration visible: [x] Yes [ ] No — notes: account menu has Login/Register.
- Product listing/search present: [x] Yes [ ] No — notes: products displayed on landing page.
- Admin or account area discoverable: [x] Yes [ ] No — notes: Admin endpoints under `/rest/admin/` discovered via API probe, hidden admin endpoint discoverable via `/#/administration`, unauthorized access to critical configuration via `/rest/admin/application-configuration`.
- Client-side errors in DevTools console: [ ] Yes [x] No — notes: None observed during initial load.
- Pre-populated local storage / cookies: Local storage empty, cookies include: `continueCode`, `cookieconsent_status`, `language`, `welcomebanner_status`.

### Security Headers (Quick Look)
Run: `curl -I http://127.0.0.1:3000 | head -20`. Paste output:

```
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 9903 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Feature-Policy: payment 'self'
X-Recruiting: /#/jobs
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Wed, 10 Jun 2026 01:28:02 GMT
ETag: W/"26af-19eaf24c181"
Content-Type: text/html; charset=UTF-8
Content-Length: 9903
Vary: Accept-Encoding
Date: Wed, 10 Jun 2026 03:05:31 GMT
Connection: keep-alive
Keep-Alive: timeout=5
```

Which of these are MISSING? (cross-reference Lecture 1 OWASP Top 10:2025 — A06):
- [x] `Content-Security-Policy` — missing
- [x] `Strict-Transport-Security` — missing (site served over HTTP)
- [ ] `X-Content-Type-Options: nosniff` — present
- [ ] `X-Frame-Options` — present

### Top 3 Risks Observed (2-3 sentences each)

1. **Missing Content-Security-Policy (and HSTS).**
No CSP header is returned, so the browser has no policy to restrict script
sources which widens the blast radius of any XSS injection. The absence of
`Strict-Transport-Security` also allows downgrade to cleartext HTTP. These are insecure default header settings. Mapping: **OWASP Top 10:2025 — A02 Security Misconfiguration.**

2. **Permissive CORS: `Access-Control-Allow-Origin: *`.**
The API allows any origin to read its responses. Combined with unauthenticated data endpoints like `/api/Products`, this lets a third-party site query and exfiltrate content from a victim's browser leading to an access-control failure. Mapping: **OWASP Top 10:2025 — A01 Broken Access Control.**

3. **Information disclosure / fingerprinting.**
The custom `X-Recruiting: /#/jobs` header and `/rest/admin/application-version` (version 20.0.0) leak unnecessary detail. These leaks make it trivial to fingerprint the stack and target known CVEs matching the exact version a configuration that exposes more than it should. Mapping: **OWASP Top 10:2025 — A02 Security Misconfiguration.**

---

## PR Template Setup

- File added: `.github/PULL_REQUEST_TEMPLATE.md`
- Sections included: Goal / Changes / Testing / Artifacts & Screenshots
- Checklist included: Title style, No secrets/large files, `submissions/labN.md` present
- Auto-fill verification: To verify, push `feature/lab1` and open a draft PR — the PR description should pre-fill with this template.
---

## Task 3 — GitHub Community Engagement (1 pt)

- Starred: DevSecOps-Intro (course repo), simple-container-com/api
- Followed: @Cre-eD, @Naghme98, @pierrepicaud, and three classmates

Why: Starring in the open source community helps discovery and signals interest; following instructors and peers enables collaboration and timely updates. It can also serve as a token of appreciation for maintainers/contributors and helps for bookmarking purposes.

---

## Bonus Task — Smoke-Test Workflow in GitHub Actions (2 pts)

## Bonus: CI Smoke Test

- Workflow file: `.github/workflows/lab1-smoke.yml`
- Trigger: `pull_request` on main
- Run URL (must be green): [<link to your Actions run>](https://github.com/IamdLite/DevSecOps-Intro/actions/runs/27287731734/job/80599483714?pr=1)
- Workflow run duration: 22s
- Curl response excerpt:
```
Run curl --silent --fail -I http://localhost:3000 | head -n 20
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Feature-Policy: payment 'self'
X-Recruiting: /#/jobs
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Wed, 10 Jun 2026 15:41:12 GMT
ETag: W/"26af-19eb231dc77"
Content-Type: text/html; charset=UTF-8
Content-Length: 9903
Vary: Accept-Encoding
Date: Wed, 10 Jun 2026 15:41:13 GMT
Connection: keep-alive
Keep-Alive: timeout=5
```

---

## Cleanup

```bash
docker stop juice-shop || true
# docker rm juice-shop # optional
```
Loading