Last Updated: February 9, 2026
This document summarizes all security, code quality, and infrastructure improvements made to AMVRS ARMED to achieve production-ready status.
File: helpers.php
Added reusable validation functions for:
validate_email() - RFC valid email formatvalidate_username() - Alphanumeric with underscore/hyphen, 3-20 charsvalidate_password() - 8+ chars, must include upper, lower, digitvalidate_string() - Trim, max length, HTML escapevalidate_int() - Type validationvalidate_phone() - Basic format validationUsage Example:
$email = validate_email($_POST['email']); // Returns valid email or ''
if (empty($email)) { die('Invalid email'); }
File: helpers.php
Created wrapper functions to simplify and secure database queries:
query($sql, $params) - SELECT with result objectquery_row() - Get first row as associative arrayquery_all() - Get all rows as array of arraysquery_count() - Count rows matching queryexecute() - INSERT/UPDATE/DELETE with affected row countBenefits:
Usage Example:
// Before (VULNERABLE):
$query = "SELECT * FROM users WHERE id = '$id'"; // SQL injection risk!
// After (SECURE):
$user = query_row("SELECT * FROM users WHERE id = ?", array($id));
Files: csrf.php, helpers.php
csrf_token() - Generate/retrieve token for formvalidate_csrf() - Validate token on POSTForm Integration:
<form method="POST">
<input type="hidden" name="csrf_token"
value="<?php echo htmlspecialchars(csrf_token(), ENT_QUOTES, 'UTF-8'); ?>">
<!-- other fields -->
</form>
File: helpers.php
log_error($type, $message, $detail) - Log errors to logs/errors.loglog_action($action, $details) - Log user actions to logs/audit.logExample:
log_error('Database Error', 'Query failed', $db_error);
log_action('user_login', "User $username logged in");
File: security_config.php
font-src, style-src, script-src whitelistedsession_set_cookie_params([
'secure' => true, // HTTPS only
'httponly' => true, // Prevent JS access
'samesite' => 'Strict' // CSRF protection
]);
Updated critical handlers to use prepared statements:
| File | Before | After |
|---|---|---|
usersig.php |
String concat in INSERT | Prepared statement with validation |
userlog.php |
String concat in SELECT | Prepared statement + password_verify |
userreg.php |
String concat in INSERT | Prepared statement + file validation |
userrequest.php |
String concat in INSERT/SELECT | Prepared statement + access control |
password_hash() with default cost (12 rounds bcrypt)password_verify() - immune to timing attacks.env Support: Database and email config from environmentmail_config.php: Centralized SMTP configurationsecurity_config.php: Global security policieshelpers.php: Reusable utility functionsset_flash('success', 'Operation completed!');
set_flash('error', 'Something went wrong');
// In template:
<?php echo display_flash(); ?>
session_set($key, $value);
$value = session_get($key, $default);
is_logged_in(); // Check authentication
check_role('admin'); // Check authorization
require_login(); // Redirect if not logged in
require_role('admin'); // Redirect if unauthorized
// Prevents open redirect vulnerabilities
safe_redirect('users.php'); // OK - relative URL
safe_redirect('http://evil.com'); // Blocked - different domain
phpunit.xml: Test configurationtests/bootstrap.php: Test environment setup with mockstests/HelpersTest.php: Unit tests for validation functionsphp vendor/bin/phpunit
Dockerfile: Multi-stage build with PHP-Apachedocker-compose.yml: Web + MySQL stackdocker compose uplogs/errors.log - PHP errors and application errorslogs/audit.log - User action audit trailquery_all()/query_row()helpers.php (new)security_config.php (new)tests/bootstrap.php (new)tests/HelpersTest.php (new)phpunit.xml (new)usersig.php (updated)userlog.php (updated)userreg.php (updated)userrequest.php (updated)header.php (updated)database.php (updated)SECURITY.md (updated)DEPLOYMENT.md (updated).github/workflows/ci.yml (existing).github/workflows/deploy.yml (existing).github/workflows/publish-image.yml (existing)Before going live:
.env file on server with real DB/SMTP credentialsphp vendor/bin/phpunit - all tests passphp test_mail.phplogs/ for errors during first weekdocker compose up --build
# Visit http://localhost:8080
git push origin main # Triggers deploy.yml workflow
# Requires SSH secrets configured in GitHub
ssh user@server
cd /var/www/amvrs
rsync -avz --delete user@local:path/ .
# Create .env with credentials
docker compose pull && docker compose up -d
Status: 🟢 PRODUCTION READY with remaining optional hardening tasks
All critical security vulnerabilities have been fixed. The application is now suitable for production deployment with proper secret management and HTTPS configured.