Add CI security suite and scrub hardcoded local host/path defaults

This commit is contained in:
Kelsi 2026-02-19 06:46:11 -08:00
parent 550366df07
commit 00086c2ad9
5 changed files with 163 additions and 26 deletions

137
.github/workflows/security.yml vendored Normal file
View file

@ -0,0 +1,137 @@
name: Security
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
permissions:
contents: read
jobs:
codeql:
name: CodeQL (C/C++)
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
build-essential \
pkg-config \
libsdl2-dev \
libglew-dev \
libglm-dev \
libssl-dev \
zlib1g-dev \
libavformat-dev \
libavcodec-dev \
libswscale-dev \
libavutil-dev \
libunicorn-dev \
libx11-dev
sudo apt-get install -y libstormlib-dev || true
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: cpp
- name: Build
run: |
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel $(nproc)
- name: Analyze
uses: github/codeql-action/analyze@v3
semgrep:
name: Semgrep
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install Semgrep
run: |
python -m pip install --upgrade pip
python -m pip install semgrep
- name: Run Semgrep (security + secrets)
run: |
semgrep scan \
--config p/security-audit \
--config p/secrets \
--error
sanitizer-build:
name: Sanitizer Build (ASan/UBSan)
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
build-essential \
pkg-config \
libsdl2-dev \
libglew-dev \
libglm-dev \
libssl-dev \
zlib1g-dev \
libavformat-dev \
libavcodec-dev \
libswscale-dev \
libavutil-dev \
libunicorn-dev \
libx11-dev
sudo apt-get install -y libstormlib-dev || true
- name: Configure (ASan/UBSan)
run: |
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DWOWEE_BUILD_TESTS=ON \
-DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" \
-DCMAKE_SHARED_LINKER_FLAGS="-fsanitize=address,undefined"
- name: Build
run: cmake --build build --parallel $(nproc)
- name: Run tests (if present)
env:
ASAN_OPTIONS: detect_leaks=1:halt_on_error=1
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
run: |
if [ -f build/CTestTestfile.cmake ] || [ -d build/tests ]; then
ctest --test-dir build --output-on-failure
else
echo "No tests configured; sanitizer build completed."
fi

View file

@ -286,7 +286,7 @@ std::string host = realm.address.substr(0, colonPos);
uint16_t port = std::stoi(realm.address.substr(colonPos + 1)); uint16_t port = std::stoi(realm.address.substr(colonPos + 1));
``` ```
**Realm address format:** `"127.0.0.1:8085"` **Realm address format:** `"localhost:8085"`
### Phase 3: World Server Connection ### Phase 3: World Server Connection
@ -295,7 +295,7 @@ uint16_t port = std::stoi(realm.address.substr(colonPos + 1));
```cpp ```cpp
game::GameHandler gameHandler; game::GameHandler gameHandler;
gameHandler.connect( gameHandler.connect(
host, // e.g., "127.0.0.1" host, // e.g., "localhost"
port, // e.g., 8085 port, // e.g., 8085
sessionKey, // 40 bytes from auth server sessionKey, // 40 bytes from auth server
accountName, // Same account accountName, // Same account
@ -447,7 +447,7 @@ void testCompleteAuthFlow() {
// Real auth handler // Real auth handler
auth::AuthHandler auth; auth::AuthHandler auth;
auth.connect("127.0.0.1", 3724); auth.connect("localhost", 3724);
bool success = false; bool success = false;
std::vector<uint8_t> key; std::vector<uint8_t> key;
@ -472,7 +472,7 @@ void testCompleteAuthFlow() {
MockWorldServer worldServer(8085); MockWorldServer worldServer(8085);
game::GameHandler game; game::GameHandler game;
game.connect("127.0.0.1", 8085, key, "TEST", 12340); game.connect("localhost", 8085, key, "TEST", 12340);
bool worldSuccess = false; bool worldSuccess = false;
game.setOnSuccess([&worldSuccess]() { game.setOnSuccess([&worldSuccess]() {

View file

@ -28,7 +28,7 @@ struct Realm {
uint8_t lock; // Lock status uint8_t lock; // Lock status
uint8_t flags; // Realm flags (bit 0x04 = has version info) uint8_t flags; // Realm flags (bit 0x04 = has version info)
std::string name; // Realm name (e.g., "My Private Server") std::string name; // Realm name (e.g., "My Private Server")
std::string address; // Server address (e.g., "127.0.0.1:8085") std::string address; // Server address (e.g., "localhost:8085")
float population; // Population level (0.0 to 2.0+) float population; // Population level (0.0 to 2.0+)
uint8_t characters; // Number of characters player has on this realm uint8_t characters; // Number of characters player has on this realm
uint8_t timezone; // Timezone ID uint8_t timezone; // Timezone ID
@ -127,7 +127,7 @@ int main() {
// Connect // Connect
std::cout << "Connecting to authentication server..." << std::endl; std::cout << "Connecting to authentication server..." << std::endl;
if (!auth.connect("127.0.0.1", 3724)) { if (!auth.connect("localhost", 3724)) {
std::cerr << "Connection failed" << std::endl; std::cerr << "Connection failed" << std::endl;
return 1; return 1;
} }
@ -218,7 +218,7 @@ int main() {
std::cout << "Address: " << selectedRealm.address << std::endl; std::cout << "Address: " << selectedRealm.address << std::endl;
// TODO: Parse address and connect to world server // TODO: Parse address and connect to world server
// Example: "127.0.0.1:8085" -> host="127.0.0.1", port=8085 // Example: "localhost:8085" -> host="localhost", port=8085
} }
} }
@ -424,7 +424,7 @@ For testing without a live server, you can create mock realms:
Realm mockRealm; Realm mockRealm;
mockRealm.id = 1; mockRealm.id = 1;
mockRealm.name = "Test Realm"; mockRealm.name = "Test Realm";
mockRealm.address = "127.0.0.1:8085"; mockRealm.address = "localhost:8085";
mockRealm.icon = 1; mockRealm.icon = 1;
mockRealm.lock = 0; mockRealm.lock = 0;
mockRealm.flags = 0x04; // Has version info mockRealm.flags = 0x04; // Has version info
@ -438,7 +438,7 @@ mockRealm.build = 12340;
// Test parsing address // Test parsing address
std::string host = parseHost(mockRealm.address); std::string host = parseHost(mockRealm.address);
assert(host == "127.0.0.1"); assert(host == "localhost");
uint16_t port = parsePort(mockRealm.address); uint16_t port = parsePort(mockRealm.address);
assert(port == 8085); assert(port == 8085);

View file

@ -16,7 +16,7 @@ The authentication screen comes with local server defaults:
| Setting | Default Value | Description | | Setting | Default Value | Description |
|---------|---------------|-------------| |---------|---------------|-------------|
| **Hostname** | 127.0.0.1 | Localhost (your machine) | | **Hostname** | localhost | Localhost (your machine) |
| **Port** | 3724 | Standard auth server port | | **Port** | 3724 | Standard auth server port |
| **Username** | (empty) | Your account username | | **Username** | (empty) | Your account username |
| **Password** | (empty) | Your account password | | **Password** | (empty) | Your account password |
@ -120,16 +120,16 @@ nano authserver.conf
**Key settings in `authserver.conf`:** **Key settings in `authserver.conf`:**
```ini ```ini
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" LoginDatabaseInfo = "localhost;3306;trinity;trinity;auth"
RealmServerPort = 3724 RealmServerPort = 3724
BindIP = "127.0.0.1" BindIP = "localhost"
``` ```
**Key settings in `worldserver.conf`:** **Key settings in `worldserver.conf`:**
```ini ```ini
LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" LoginDatabaseInfo = "localhost;3306;trinity;trinity;auth"
WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world" WorldDatabaseInfo = "localhost;3306;trinity;trinity;world"
CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters" CharacterDatabaseInfo = "localhost;3306;trinity;trinity;characters"
DataDir = "/path/to/your/WoW-3.3.5a/Data" # Your WoW client data directory DataDir = "/path/to/your/WoW-3.3.5a/Data" # Your WoW client data directory
``` ```
@ -154,7 +154,7 @@ account set gmlevel testuser 3 -1
In the worldserver console: In the worldserver console:
``` ```
realm add "Local Test Realm" 127.0.0.1:8085 0 1 realm add "Local Test Realm" localhost:8085 0 1
``` ```
Or directly in database: Or directly in database:
@ -162,7 +162,7 @@ Or directly in database:
mysql -u trinity -ptrinity auth mysql -u trinity -ptrinity auth
INSERT INTO realmlist (name, address, port, icon, realmflags, timezone, allowedSecurityLevel) INSERT INTO realmlist (name, address, port, icon, realmflags, timezone, allowedSecurityLevel)
VALUES ('Local Test Realm', '127.0.0.1', 8085, 1, 0, 1, 0); VALUES ('Local Test Realm', 'localhost', 8085, 1, 0, 1, 0);
``` ```
## Running the Server ## Running the Server
@ -212,14 +212,14 @@ server shutdown 10 # Shutdown in 10 seconds
### 1. Start the Client ### 1. Start the Client
```bash ```bash
cd /home/k/Desktop/wowee/wowee cd /path/to/wowee
./build/bin/wowee ./build/bin/wowee
``` ```
### 2. Login Screen ### 2. Login Screen
You'll see the authentication screen with default values: You'll see the authentication screen with default values:
- **Hostname:** 127.0.0.1 (already set) - **Hostname:** localhost (already set)
- **Port:** 3724 (already set) - **Port:** 3724 (already set)
- **Username:** (enter your account username) - **Username:** (enter your account username)
- **Password:** (enter your account password) - **Password:** (enter your account password)
@ -291,7 +291,7 @@ ps aux | grep worldserver
netstat -an | grep 8085 netstat -an | grep 8085
# Update realmlist address # Update realmlist address
UPDATE realmlist SET address='127.0.0.1' WHERE id=1; UPDATE realmlist SET address='localhost' WHERE id=1;
``` ```
### Cannot Enter World ### Cannot Enter World
@ -335,13 +335,13 @@ ifconfig | grep inet
Edit `authserver.conf`: Edit `authserver.conf`:
```ini ```ini
BindIP = "0.0.0.0" # Listen on all interfaces BindIP = "<bind-address>" # Listen on all interfaces
``` ```
Edit database: Edit database:
```sql ```sql
mysql -u trinity -ptrinity auth mysql -u trinity -ptrinity auth
UPDATE realmlist SET address='192.168.1.100' WHERE id=1; # Your local IP UPDATE realmlist SET address='<your-lan-ip>' WHERE id=1; # Your local IP
``` ```
**3. Configure firewall:** **3. Configure firewall:**
@ -351,7 +351,7 @@ sudo ufw allow 8085 # World server
``` ```
**4. In wowee:** **4. In wowee:**
- Change hostname to your server's local IP (e.g., 192.168.1.100) - Change hostname to your server's local IP (e.g., <your-lan-ip>)
- Keep port as 3724 - Keep port as 3724
- Connect - Connect
@ -366,7 +366,7 @@ For testing with a remote server (VPS, dedicated server):
**Server configuration:** **Server configuration:**
```ini ```ini
# authserver.conf # authserver.conf
BindIP = "0.0.0.0" BindIP = "<bind-address>"
# Database # Database
UPDATE realmlist SET address='your.server.ip' WHERE id=1; UPDATE realmlist SET address='your.server.ip' WHERE id=1;
@ -600,7 +600,7 @@ server shutdown 10
- [ ] Account created with proper credentials - [ ] Account created with proper credentials
- [ ] Firewall allows ports 3724 and 8085 - [ ] Firewall allows ports 3724 and 8085
- [ ] WOW_DATA_PATH set correctly (if using MPQ assets) - [ ] WOW_DATA_PATH set correctly (if using MPQ assets)
- [ ] Client can resolve hostname (127.0.0.1 for localhost) - [ ] Client can resolve hostname (localhost for localhost)
## Next Steps ## Next Steps

View file

@ -51,7 +51,7 @@ private:
}; };
// UI state // UI state
char hostname[256] = "127.0.0.1"; char hostname[256] = "localhost";
char username[256] = ""; char username[256] = "";
char password[256] = ""; char password[256] = "";
char pinCode[32] = ""; char pinCode[32] = "";