Instructions for AI coding agents working on this repository.
OWASP Security Shepherd is a web and mobile application security training platform. The web app is a Java servlet application built with Maven, deployed as a WAR on Tomcat. The mobile challenges are independent Android apps under mobile/MobileShepherd/.
The following paths contain deliberately insecure code used for security training. Do not fix, refactor, or flag security vulnerabilities in these files:
src/main/java/servlets/module/lesson/— lesson servlets with intentional vulnerabilitiessrc/main/java/servlets/module/challenge/— challenge servlets with intentional vulnerabilitiesmobile/MobileShepherd/— mobile challenge apps with intentional vulnerabilities
Security improvements should only be made to the platform infrastructure (authentication, session management, admin functions, DB layer, etc.), never to the training content.
All Java code MUST be formatted with Google Java Format. CI enforces this via axel-op/googlejavaformat-action and will reject unformatted code.
Before committing Java changes, run:
google-java-format --replace <changed-files>The project targets Java 8. All code must compile against Java 8, even though CI uses Java 24 for linting. Do not use Java 9+ APIs or language features.
mvn -Pdocker clean install -DskipTests -B # build WAR with Docker profile (required before docker compose)
docker compose build # build Docker images
mvn test -B # unit tests
mvn verify -DskipUTs=true -DmongoDocker -B # integration tests (requires MySQL + MongoDB)The -Pdocker profile must run before docker compose build — it generates SQL scripts, MongoDB init scripts, and TLS keystores.
Always run tests locally before pushing to remote.
Integration tests require a running database. For quick local test runs, start a plain MariaDB container:
docker run -d --name secshep_test_db \
-e MYSQL_ROOT_PASSWORD=CowSaysMoo \
-e MYSQL_DATABASE=core \
-p 3306:3306 \
mariadb:10.6.11The docker-compose db service is not suitable for quick test runs — it requires mvn -Pdocker validate first to generate SQL init scripts, and those scripts run on first container startup to create all challenge schemas.
Tests read DB connection details from .env via dotenv. The key values:
TEST_MYSQL_HOST— default127.0.0.1TEST_MYSQL_PORT— default3306TEST_MYSQL_PASSWORD— must match the password on the running database
The .env file ships with TEST_MYSQL_PASSWORD=password (used in CI where a separate MySQL service is configured with that password). When running locally against the container above (password CowSaysMoo), either:
# Option 1: override at test time
TEST_MYSQL_PASSWORD=CowSaysMoo mvn test -B
# Option 2: update .env temporarilyDo not commit .env changes that break CI.
- Never commit directly to
masterordev - Branch naming:
dev#{issueNumber}(e.g.dev#536) - PRs always target
dev, notmaster
src/main/java/— web app sourcedbProcs/— database layer:Database.java(connection pooling),Getter.java(read queries),Setter.java(write queries),MongoDatabase.java,Constants.java,FileInputProperties.javaservlets/— platform servlets (Login, Register, Setup, etc.)servlets/admin/— admin servlets (config/,moduleManagement/,userManagement/)servlets/module/— module framework (SolutionSubmit.java,GetModule.java, etc.) pluschallenge/andlesson/(intentionally vulnerable — do not fix)utils/— shared utilities (validation, hashing, scoring, XSS/SQL filters)
src/main/resources/— config and challenge properties filessrc/test/java/— unit testssrc/it/java/— integration tests (require running DB containers)mobile/MobileShepherd/— independent Android apps (Gradle-based, not part of Maven build)
- MySQL/MariaDB for the core app and SQL-based challenges
- MongoDB for NoSQL challenges
- Each challenge uses isolated DB credentials scoped to its own schema — do not consolidate challenge DB users
- Encoding must be
utf8mb4(notutf8) for full Unicode support - Password hashing uses Argon2 (requires
libargon2native library)
src/main/resources/database/coreSchema.sql— source of truth for the core database: users table, settings table, stored procedures (user management, authentication, class management, scoring), and seed data (default admin user, default settings)src/main/resources/database/moduleSchemas.sql— challenge and lesson schemas with intentionally vulnerable data (treat as training content, not infrastructure)docker/mariadb/target/— build-generated copies produced bymvn -Pdocker; not source of truth, do not edit directly
The settings table stores admin-configurable options as key-value pairs (setting VARCHAR, value VARCHAR). Known keys: adminCheatsEnabled, playerCheatsEnabled, moduleLayout, enableFeedback, openRegistration, scoreboardStatus, scoreboardClass, hasStartTime, startTime, hasLockTime, lockTime, hasEndTime, endTime, enableTranslations, defaultClass.
Stored procedures use DELIMITER statements that are commented out in the source SQL (for tool compatibility). The build script docker/scripts/convert-sql-scripts.sh uncomments them when copying to docker/mariadb/target/. See the "Docker DB init fails" section above if procedures fail to parse.
Run mvn test -B locally before pushing any code changes. If integration tests are relevant to your changes, run those too. Do not rely solely on CI to catch failures.
When fixing a bug, always write a test that reproduces the bug first, then apply the fix. The test should fail without the fix and pass with it.
When making significant changes (new features, architectural changes, build/config changes, new dependencies), check whether these files need updating:
AGENTS.md(this file)CONTRIBUTING.mdREADME.md- Files in
docs/
Do not scan these files on every change — only review and update them when your changes would make their content inaccurate.