Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
2358582
Restrict NodeGoat web port to localhost
ThakshilaUddeepana Sep 23, 2026
9b61c81
Document NodeGoat local Docker setup
ThakshilaUddeepana Sep 23, 2026
010d2aa
Document NodeGoat architecture and trust boundaries
ThakshilaUddeepana Sep 23, 2026
6052e35
Merge pull request #1 from Thakshila05/member1/docker-setup
Thakshila05 Sep 23, 2026
4deb20f
Prevent server-side JavaScript injection in contributions
ThakshilaUddeepana Sep 23, 2026
d7cca0e
Same exploit after fix
Uinduwara Sep 24, 2026
b3c5929
Add DevSecOps build and test workflow
Sep 24, 2026
895c247
Add dependency security audit
bhanukadilshan Sep 27, 2026
b9b9e97
Add Semgrep SAST to DevSecOps pipeline
bhanukadilshan Sep 27, 2026
61897f8
Fix SSJS injection and add custom SAST rule
bhanukadilshan Sep 27, 2026
c868d58
Merge pull request #2 from Thakshila05/member1/fix-eval-injection
bhanukadilshan Sep 29, 2026
1c16cd5
Finalize Semgrep DevSecOps workflow
bhanukadilshan Sep 29, 2026
0b9c373
Merge Member 3 DevSecOps pipeline
bhanukadilshan Sep 29, 2026
70aee02
Merge remote-tracking branch 'origin/master' into member2/idor-fix
Uinduwara Sep 29, 2026
a35d8a8
Separate dependency security gate
bhanukadilshan Sep 29, 2026
d190942
Add Member 2 IDOR before and after scan evidence
Uinduwara Sep 29, 2026
5897e29
Add Member 2 IDOR browser evidence
Uinduwara Sep 29, 2026
bf15d8e
Fix deprecated E2E GitHub Actions
Thakshila05 Sep 30, 2026
f00e0b9
Install dependency required by legacy Cypress
Thakshila05 Sep 30, 2026
20ab04b
Wait for MongoDB readiness before E2E tests
Thakshila05 Sep 30, 2026
5f7db2a
Make misplaced Semgrep file a valid manual workflow
Thakshila05 Sep 30, 2026
f8eb3f5
Add security scanning and container security gate
IT24102493 Sep 30, 2026
129b2e9
Fix security scan and CI compatibility
IT24102493 Sep 30, 2026
2ce33d8
Remove vulnerable package managers from runtime image
IT24102493 Sep 30, 2026
dd5775b
Fix E2E template rendering failures
IT24102493 Sep 30, 2026
0888c02
Fix remaining E2E rendering and assertions
IT24102493 Sep 30, 2026
8a146b0
Fix ReDoS in bank routing validation
bhanukadilshan Sep 30, 2026
2b931c7
Fix deprecated E2E actions and remove misplaced Semgrep workflow
Uinduwara Sep 30, 2026
b04396d
Merge pull request #3 from Thakshila05/member2/idor-fix
Thakshila05 Sep 30, 2026
ecaa3b0
Merge pull request #4 from Thakshila05/member3/devsecops-pipeline
Thakshila05 Sep 30, 2026
6aeb711
Fix legacy Cypress E2E workflow compatibility
Uinduwara Sep 30, 2026
5815eeb
Merge pull request #6 from Thakshila05/member3/redos-fix
Thakshila05 Sep 30, 2026
fd86d3e
Allow dependency audit findings without failing pipeline
Uinduwara Sep 30, 2026
5d3f324
Merge pull request #5 from Thakshila05/fix/github-workflow-errors
Thakshila05 Sep 30, 2026
3c5e32b
Make dependency audit report-only
Thakshila05 Sep 30, 2026
a1966b2
Update allocations E2E test for IDOR fix
Thakshila05 Sep 30, 2026
46643f5
Update allocation E2E test for IDOR fix
Uinduwara Sep 30, 2026
5715c6e
Merge pull request #7 from Thakshila05/fix/dependency-audit-report-only
Thakshila05 Sep 30, 2026
c08b587
Add IDOR evidence screenshot
Uinduwara Sep 30, 2026
44c7c03
Merge branch 'master' into member4/security-scanning
IT24102493 Sep 30, 2026
fd279ad
Repair DevSecOps workflow after conflict resolution
Thakshila05 Sep 30, 2026
53fa0c3
Merge latest master into member2 workflow repair
Uinduwara Sep 30, 2026
d37978b
Restore E2E workflow after conflict resolution
Thakshila05 Sep 30, 2026
469a4ea
Merge pull request #8 from Thakshila05/member4/security-scanning
Thakshila05 Sep 30, 2026
be9d16f
Fix lint workflow matrix indentation
Thakshila05 Sep 30, 2026
195fcdb
Install dependencies before running JSHint
Thakshila05 Sep 30, 2026
3e7059f
Merge pull request #9 from Thakshila05/fix/lint-workflow-matrix
Thakshila05 Sep 30, 2026
4909568
Merge latest master into workflow repair
Uinduwara Sep 30, 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
7 changes: 7 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,10 @@ docker-compose.yml
.git
.github
.gitignore
.semgrep-env/
trivy-*.txt
.env
.env.*
artifacts/cert/server.key
node_modules
artifacts/cert/server.key.backup
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MONGODB_URI=mongodb://USERNAME:PASSWORD@HOST:27017/nodegoat
SESSION_SECRET=replace-with-real-secret
113 changes: 113 additions & 0 deletions .github/workflows/devsecops.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: DevSecOps Pipeline

on:
push:
pull_request:

jobs:
build-and-test:
name: Build and Unit Test
runs-on: ubuntu-latest

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

- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Run unit tests
run: npm test

dependency-security:
name: Dependency Security Audit (report only)
runs-on: ubuntu-latest

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

- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 22
cache: npm

- name: Install dependencies
run: npm ci

- name: Dependency Security Audit
continue-on-error: true
run: npm audit --omit=dev --audit-level=high

sast-semgrep:
name: SAST - Semgrep
runs-on: ubuntu-latest

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

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install Semgrep
run: python -m pip install semgrep

- name: Run Semgrep SAST
run: |
semgrep scan \
--config auto \
--config .semgrep.yml \
--json \
--output semgrep-results.json .

python - <<'PY'
import json
with open("semgrep-results.json") as f:
data = json.load(f)
print(f"Semgrep findings: {len(data.get('results', []))}")
PY

gitleaks:
name: Secret Scanning - Gitleaks
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

trivy:
name: Container Security - Trivy
runs-on: ubuntu-latest

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

- name: Build Docker image
run: docker build -t nodegoat-member4-web:${{ github.sha }} .

- name: Run Trivy vulnerability scan
uses: aquasecurity/trivy-action@v0.36.0
with:
image-ref: nodegoat-member4-web:${{ github.sha }}
format: table
vuln-type: os,library
severity: HIGH,CRITICAL
exit-code: '1'
41 changes: 32 additions & 9 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: E2E Test

on: [push, pull_request]

jobs:
Expand All @@ -9,21 +10,21 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: ["10.x", "12.x", "14.x"]
node-version: ["22.x"]

steps:
- name: Checkout https://github.com/${{ github.repository }}@${{ github.ref }}
uses: actions/checkout@v2
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}

- name: Use cache
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: |
~/.npm
Expand All @@ -37,15 +38,37 @@ jobs:

- name: Start MongoDB
run: |
docker run -d -p 27017:27017 mongo:4.0
timeout 60s bash -c 'until nc -z -w 2 localhost 27017 && echo MongoDB ready; do sleep 2; done'
docker run -d --name nodegoat-mongo -p 27017:27017 mongo:4.4
for attempt in {1..30}; do
if docker exec nodegoat-mongo mongo --quiet --eval 'db.adminCommand({ ping: 1 }).ok' | grep -qx 1; then
echo "MongoDB ready"
exit 0
fi
sleep 2
done
docker logs nodegoat-mongo
exit 1

- name: Seed test database
run: npm run db:seed

- name: Run E2E test suite
id: test-suite
run: |
NODE_ENV=test npm start -- --silent &
NODE_ENV=test npm start -- --silent > /tmp/nodegoat.log 2>&1 &
for attempt in $(seq 1 30); do
if curl --silent --fail http://localhost:4000/login >/dev/null; then
break
fi
sleep 2
done
curl --silent --fail http://localhost:4000/login >/dev/null || { cat /tmp/nodegoat.log; exit 1; }
npm run test:ci -- --config video=true

- name: Show application logs on failure
if: failure() && (steps.test-suite.outcome == 'failure')
run: cat /tmp/nodegoat.log

- name: Prepare cypress artifacts
if: failure() && (steps.test-suite.outcome == 'failure')
working-directory: ./test/e2e
Expand All @@ -55,7 +78,7 @@ jobs:

- name: Upload cypress artifacts
if: failure() && (steps.test-suite.outcome == 'failure')
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: cypress-artifacts-node${{ matrix.node-version }}
path: test/e2e/screenshots
path: test/e2e/screenshots
11 changes: 7 additions & 4 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ jobs:
strategy:
fail-fast: false
matrix:
node-version: ["14.x"]
node-version: ["22.x"]

steps:
- name: Checkout https://github.com/${{ github.repository }}@${{ github.ref }}
uses: actions/checkout@v2
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v7
with:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm ci

- name: Run linter
run: npx --no-install jshint@2.12.0 .
run: npx --no-install jshint .
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ test/e2e/screenshots/
test/e2e/videos/

# ignore sensitive files
.env.local
.env
.env.*
!.env.example
artifacts/cert/server.key.backup

# ignore Snyk Code scanner files
.dccache

/scan-comparison/
7 changes: 7 additions & 0 deletions .semgrep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
rules:
- id: nodegoat-eval-user-input
languages:
- javascript
message: "User-controlled input is passed to eval(). Use numeric parsing instead."
severity: ERROR
pattern: eval(req.body.$FIELD)
Loading