Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
2593292
AMP-31141 : Re-enable and redesign CSRF protection for state-changing…
brianbrix Jun 15, 2026
b604a60
AMP-31141 : Failing maven build
brianbrix Jun 15, 2026
afcafc4
AMP-31141 : Re-enable and redesign CSRF protection for state-changing…
brianbrix Jun 15, 2026
c3f64d8
AMP-31141 : Re-enable and redesign CSRF protection for state-changing…
brianbrix Jun 15, 2026
00da6aa
AMP-31141 : Re-enable and redesign CSRF protection for state-changing…
brianbrix Jun 16, 2026
5ecea45
AMP-31141 : Re-enable and redesign CSRF protection for state-changing…
brianbrix Jun 16, 2026
97bb146
AMP-31141 : Activity form not saving due to CSRF
brianbrix Jun 16, 2026
0a70668
AMP-31141 : Activity form not saving due to CSRF
brianbrix Jun 16, 2026
0103f69
AMP-31140 : CSRF protection on REST endpoints
brianbrix Jun 16, 2026
e465941
AMP-31140 : CSRF protection on REST endpoints
brianbrix Jun 16, 2026
e84e47d
AMP-31142 : Modernize authentication handling
brianbrix Jun 16, 2026
e5fa1c7
AMP-31143 : Restore browser hardening headers and document cookie and…
brianbrix Jun 16, 2026
14d4a62
AMP-31141 : Failing to get resources
brianbrix Jun 16, 2026
a21da26
AMP-31141 : Failing to get resources
brianbrix Jun 16, 2026
5b21037
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
ffe9285
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
d57eff9
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
478e2db
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
b1f8e11
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
2689305
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 16, 2026
af575e2
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 17, 2026
edab738
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 17, 2026
ab2da48
AMP-31144 : Add dependency and CVE scanning for OWASP audit
brianbrix Jun 17, 2026
e316304
Merge branch 'develop' into task/AMP-31140/Priority-changes-before-Tr…
brianbrix Jun 23, 2026
b907ad7
AMP-31140: Add audit evidence docs and operational scripts
brianbrix Jun 23, 2026
0d6c08a
AMP-31140 : Add NVD API Key
brianbrix Jun 24, 2026
2bf2c44
AMP-31140 : Add NVD API Key to actions
brianbrix Jun 24, 2026
3672d1d
AMP-31140 : Failing to upload scan report
brianbrix Jun 24, 2026
e9badfe
AMP-31140 : Failing to upload scan report
brianbrix Jun 24, 2026
ea8d912
AMP-31140 : NVD API Key is forbidden
brianbrix Jun 24, 2026
d922991
AMP-31140 : NVD API Key is forbidden
brianbrix Jun 24, 2026
e613022
AMP-31140 : NVD API Key is forbidden
brianbrix Jun 24, 2026
5fe7b11
AMP-31140 : Change CVE scan dependency for CI
brianbrix Jun 24, 2026
e01943c
AMP-31140 : Change CVE scan dependency for CI
brianbrix Jun 24, 2026
a15860b
AMP-31140 : Failing scan due to invalid code paths
brianbrix Jun 24, 2026
4887189
AMP-31140 : Failing scan due to invalid code paths
brianbrix Jun 24, 2026
cd067e5
AMP-31140 : Failing scan due to invalid code paths
brianbrix Jun 24, 2026
bdccaa3
AMP-31140 : Missing output directory
brianbrix Jun 24, 2026
a1b53e1
AMP-31140 : Missing output directory
brianbrix Jun 24, 2026
cdc50cd
AMP-31140 : Missing output directory
brianbrix Jun 24, 2026
222fe8f
AMP-31140 : Try resolving P1 CVEs
brianbrix Jun 25, 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
283 changes: 283 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
name: Security Scan

on:
push:
# Scan the default branch directly on merge; feature branches are covered
# by the pull_request trigger below, avoiding duplicate runs.
branches:
- develop
- main
pull_request:
branches: [ "**" ]
schedule:
# Re-scan every Monday at 06:00 UTC to catch newly published CVEs.
# Runs on the default branch; push/PR triggers cover all other branches.
- cron: '0 6 * * 1'
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to scan (optional — leave blank to scan the branch selected above)'
required: false
type: string
default: ''

permissions:
contents: read

jobs:
# -----------------------------------------------------------------------
# Resolve the exact commit to scan.
# - Automatic triggers (push / PR / schedule): use the triggering SHA.
# - Manual (workflow_dispatch, no pr_number): use the branch selected in
# the "Run workflow" UI — GitHub checks out that branch automatically.
# - Manual (workflow_dispatch + pr_number): fetch the PR head SHA via API.
# -----------------------------------------------------------------------
setup:
name: Resolve target ref
runs-on: ubuntu-latest
outputs:
ref: ${{ steps.resolve.outputs.ref }}
steps:
- name: Resolve checkout ref
id: resolve
run: |
PR="${{ inputs.pr_number }}"
if [ -n "$PR" ]; then
if ! [[ "$PR" =~ ^[0-9]+$ ]]; then
echo "::error::pr_number must be numeric, got: ${PR}"
exit 1
fi
DATA=$(curl -sf \
-H "Authorization: Bearer ${{ github.token }}" \
"https://api.github.com/repos/${{ github.repository }}/pulls/${PR}")
STATE=$(echo "$DATA" | jq -r '.state')
if [ "$STATE" != "open" ]; then
echo "::error::PR #${PR} is not open (state: ${STATE})"
exit 1
fi
HEAD_REF=$(echo "$DATA" | jq -r '.head.ref')
HEAD_SHA=$(echo "$DATA" | jq -r '.head.sha')
echo "Scanning PR #${PR}: branch=${HEAD_REF} sha=${HEAD_SHA}"
echo "ref=${HEAD_SHA}" >> $GITHUB_OUTPUT
else
echo "ref=${{ github.sha }}" >> $GITHUB_OUTPUT
fi

# -----------------------------------------------------------------------
# Job 1: OWASP Dependency-Check (Java / Maven artifacts)
# Uses the official GHA action which downloads a pre-built NVD snapshot,
# avoiding the raw NVD API stream that causes 524 timeouts in CI.
# -----------------------------------------------------------------------
owasp-maven:
name: OWASP Dependency-Check (Maven)
runs-on: ubuntu-latest
timeout-minutes: 60
needs: setup

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.ref }}

- name: Create report output directory
run: mkdir -p amp/target/dependency-check-report

- name: Run OWASP Dependency-Check
uses: dependency-check/Dependency-Check_Action@main
id: owasp
continue-on-error: true
with:
project: 'amp'
# Scan the Maven module directory; the action resolves dependencies from pom.xml
path: 'amp'
format: 'ALL'
out: 'amp/target/dependency-check-report'
args: >
--nvdApiKey ${{ secrets.NVD_API_KEY }}
--nvdApiDelay 10000
--failOnCVSS 7
--suppression /github/workspace/security/owasp-suppressions.xml
--scan /github/workspace/amp/ckeditor_4.4.6
--disableNodeAudit
--enableExperimental

- name: Upload HTML report
if: always()
uses: actions/upload-artifact@v4
with:
name: owasp-dependency-check-report
path: amp/target/dependency-check-report/
retention-days: 30
if-no-files-found: warn

- name: Show report directory (debug)
if: always()
run: |
echo "=== Dependency-Check output ==="
find . -path "*/dependency-check*" -print 2>/dev/null || true

- name: Fail if OWASP found CVEs
if: steps.owasp.outcome == 'failure'
run: exit 1

# -----------------------------------------------------------------------
# Job 2: npm audit — all frontend packages
# -----------------------------------------------------------------------
npm-audit:
name: npm audit (Frontend)
runs-on: ubuntu-latest
timeout-minutes: 30
needs: setup

strategy:
fail-fast: false
matrix:
package:
- path: amp/TEMPLATE/reamp
name: reamp
- path: amp/TEMPLATE/ampTemplate/amp-state
name: amp-state
- path: amp/TEMPLATE/ampTemplate/amp-boilerplate
name: amp-boilerplate
- path: amp/TEMPLATE/ampTemplate/amp-filter
name: amp-filter
- path: amp/TEMPLATE/ampTemplate/amp-translate
name: amp-translate
- path: amp/TEMPLATE/ampTemplate/amp-url
name: amp-url
- path: amp/TEMPLATE/ampTemplate/amp-settings
name: amp-settings
- path: amp/TEMPLATE/ampTemplate/gis-layers-manager
name: gis-layers-manager
- path: amp/TEMPLATE/ampTemplate/dashboard/dev
name: dashboard
- path: amp/TEMPLATE/ampTemplate/gisModule/dev
name: gisModule

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.ref }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '16'

- name: npm install (no scripts)
working-directory: ${{ matrix.package.path }}
run: npm install --ignore-scripts --prefer-offline 2>&1 || true

- name: Install npm-audit-html
run: npm install -g npm-audit-html --prefer-offline 2>&1 || true

- name: npm audit
id: audit
working-directory: ${{ matrix.package.path }}
# Continue so all packages are scanned; the summary step decides outcome
continue-on-error: true
run: |
npm audit \
--audit-level high \
--json \
> /tmp/${{ matrix.package.name }}-audit.json 2>&1

- name: Print audit summary
if: always()
working-directory: ${{ matrix.package.path }}
run: |
FILE="/tmp/${{ matrix.package.name }}-audit.json"
if command -v jq &>/dev/null && [ -f "$FILE" ]; then
echo "### ${{ matrix.package.name }} vulnerability counts"
jq '{
critical: (.metadata.vulnerabilities.critical // 0),
high: (.metadata.vulnerabilities.high // 0),
moderate: (.metadata.vulnerabilities.moderate // 0),
low: (.metadata.vulnerabilities.low // 0)
}' "$FILE"
fi

- name: Generate HTML report
if: always()
run: |
FILE="/tmp/${{ matrix.package.name }}-audit.json"
if [ -f "$FILE" ]; then
npm-audit-html --input "$FILE" --output "/tmp/${{ matrix.package.name }}-audit.html" 2>/dev/null || true
fi

- name: Upload audit report
if: always()
uses: actions/upload-artifact@v4
with:
name: npm-audit-${{ matrix.package.name }}
path: |
/tmp/${{ matrix.package.name }}-audit.html
/tmp/${{ matrix.package.name }}-audit.json
retention-days: 30

- name: Fail on HIGH or CRITICAL findings
working-directory: ${{ matrix.package.path }}
run: |
FILE="/tmp/${{ matrix.package.name }}-audit.json"
if [ ! -f "$FILE" ]; then exit 0; fi
HIGH=$(jq '.metadata.vulnerabilities.high // 0' "$FILE")
CRIT=$(jq '.metadata.vulnerabilities.critical // 0' "$FILE")
TOTAL=$(( HIGH + CRIT ))
if [ "$TOTAL" -gt 0 ]; then
echo "::error::${{ matrix.package.name }}: ${CRIT} critical + ${HIGH} high vulnerabilities found. Run 'npm audit' in ${{ matrix.package.path }} for details."
exit 1
fi

# -----------------------------------------------------------------------
# Job 3: Trivy — container image CVE scan (runs on push to main / PRs)
# Catches OS-level CVEs that OWASP cannot see (e.g. base image packages)
# -----------------------------------------------------------------------
trivy-image:
name: Trivy (Container Image)
runs-on: ubuntu-latest
timeout-minutes: 30
needs: setup
# Only scan the image on pushes to main/master or on PRs targeting them,
# to avoid redundant scans on every feature branch push.
if: |
github.event_name == 'pull_request' ||
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/master' ||
github.event_name == 'schedule' ||
github.event_name == 'workflow_dispatch'

steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ needs.setup.outputs.ref }}

- name: Build Docker image (no push)
working-directory: amp
run: |
docker build \
--build-arg BUILD_SOURCE=security-scan \
--build-arg AMP_URL=http://localhost/ \
-t amp-security-scan:${{ github.sha }} \
. || echo "::warning::Docker build failed; skipping Trivy image scan"

- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@v0.36.0
with:
image-ref: 'amp-security-scan:${{ github.sha }}'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
exit-code: '1'
ignore-unfixed: true
continue-on-error: true

- name: Upload Trivy SARIF artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: trivy-sarif
path: trivy-results.sarif
retention-days: 30
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,6 @@ amp/src/main/java/org/digijava/module/xmlpatcher/jaxb/ConditionType.java
amp/src/main/java/org/digijava/module/xmlpatcher/jaxb/package-info.java
amp/src/main/java/org/digijava/module/xmlpatcher/jaxb/ConditionParam.java
amp/src/main/java/org/digijava/module/help/jaxbi/AmpHelpType.java

# ISO 27001 evidence CSVs and raw DB exports — contain personal data, never commit
audit-evidence/evidence/
7 changes: 7 additions & 0 deletions amp/TEMPLATE/ampTemplate/amp-boilerplate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,12 @@
},
"dependencies": {
"amp-translate": "^0.0.1"
},
"overrides": {
"minimist": ">=1.2.6",
"shell-quote": ">=1.7.4",
"braces": ">=3.0.3",
"browserify-sign": ">=4.2.2",
"semver": ">=7.5.2"
}
}
7 changes: 7 additions & 0 deletions amp/TEMPLATE/ampTemplate/amp-filter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,12 @@
],
"dependencies": {
"amp-translate": "^0.0.1"
},
"overrides": {
"minimist": ">=1.2.6",
"shell-quote": ">=1.7.4",
"braces": ">=3.0.3",
"browserify-sign": ">=4.2.2",
"semver": ">=7.5.2"
}
}
7 changes: 7 additions & 0 deletions amp/TEMPLATE/ampTemplate/amp-settings/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,12 @@
},
"dependencies": {
"amp-translate": "https://github.com/devgateway/amp-translate.git"
},
"overrides": {
"minimist": ">=1.2.6",
"shell-quote": ">=1.7.4",
"braces": ">=3.0.3",
"browserify-sign": ">=4.2.2",
"semver": ">=7.5.2"
}
}
7 changes: 7 additions & 0 deletions amp/TEMPLATE/ampTemplate/amp-translate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,12 @@
},
"devDependencies": {
"brfs": "1.2.0"
},
"overrides": {
"minimist": ">=1.2.6",
"shell-quote": ">=1.7.4",
"braces": ">=3.0.3",
"browserify-sign": ">=4.2.2",
"semver": ">=7.5.2"
}
}
8 changes: 8 additions & 0 deletions amp/TEMPLATE/reampv2/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,13 @@
"fs": "^0.0.1-security",
"jquery-ui": "^1.10.5",
"use-sync-external-store": "^1.2.0"
},
"overrides": {
"minimist": ">=1.2.6",
"lodash": ">=4.17.21",
"shell-quote": ">=1.7.4",
"braces": ">=3.0.3",
"semver": ">=7.5.2",
"browserify-sign": ">=4.2.2"
}
}
6 changes: 5 additions & 1 deletion amp/context.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
allowLinking="true" antiJARLocking="" antiResourceLocking="" clearReferencesStopTimerThreads="true"
clearReferencesThreadLocals="true" jndiExceptionOnFailedWrite="false" processTlds="false">
<Environment name="hostname" value="" type="java.lang.String"/>


<!-- SameSite=Lax: browser will not send the session cookie on cross-site
POST/PUT/DELETE requests, providing CSRF protection for all endpoints
including /rest/** without requiring any token in requests. -->
<CookieProcessor sameSiteCookies="lax" />
<!-- PostgreSQL connection -->
<Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
defaultTransactionIsolation="READ_COMMITTED"
Expand Down
Loading
Loading