Add comprehensive security audit (86 findings across 10 areas)

Secure dev auth with signed tokens, add email support for --user
Simplify breakpoint variables, suppress Sass deprecation warnings

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-19 01:14:31 +00:00
parent ee87bc6297
commit f67c88a4f1
10 changed files with 270 additions and 35 deletions

View File

@@ -10,6 +10,7 @@ namespace App\RSpade\Commands\Rsx;
use Illuminate\Console\Command;
use Symfony\Component\Process\Process;
use App\RSpade\Core\Debug\Debugger;
use App\RSpade\Core\Models\Login_User_Model;
/**
* RSX Route Debug Command
@@ -29,7 +30,7 @@ use App\RSpade\Core\Debug\Debugger;
* 6. Rotates logs again after test for clean slate on next run
*
* KEY FEATURES:
* - Backdoor authentication: Use --user-id to bypass login and test as any user
* - Backdoor authentication: Use --user with ID or email to bypass login
* - Plain text error output: Errors returned as plain text with stack traces
* - Console capture: JavaScript errors and logs captured (--console for all)
* - XHR/fetch tracking: Monitor API calls with --xhr-dump or --xhr-list
@@ -55,7 +56,8 @@ use App\RSpade\Core\Debug\Debugger;
*
* USAGE EXAMPLES:
* php artisan rsx:debug /dashboard # Basic route test
* php artisan rsx:debug /dashboard --user-id=1 # Test as user ID 1
* php artisan rsx:debug /dashboard --user=1 # Test as user ID 1
* php artisan rsx:debug /dashboard --user=admin@test.com # Test as user by email
* php artisan rsx:debug /api/users --no-body # Headers only
* php artisan rsx:debug /login --full # Maximum information
* php artisan rsx:debug /api/data --xhr-list # Simple XHR list
@@ -127,8 +129,7 @@ class Route_Debug_Command extends Command
protected $signature = 'rsx:debug
{url? : The URL to debug (e.g., /dashboard, /api/users). Use --examples to see usage examples}
{--examples : Show comprehensive usage examples}
{--user= : Test as specific user ID (bypasses authentication)}
{--user-id= : Alias for --user option}
{--user= : Test as specific user ID or email (bypasses authentication)}
{--log : Display Laravel error log if not empty}
{--no-body : Suppress HTTP response body (show headers/status only)}
{--follow-redirects : Follow HTTP redirects and show full redirect chain}
@@ -212,9 +213,15 @@ class Route_Debug_Command extends Command
$url = '/' . $url;
}
// Get user ID from options
$user_id = $this->option('user-id') ?: $this->option('user');
// Get user ID from options (accepts ID or email)
$user_id = $this->option('user');
if ($user_id !== null) {
$user_id = $this->resolve_user($user_id);
if ($user_id === null) {
return 1; // Error already displayed
}
}
// Get log flag
$show_log = $this->option('log');
@@ -373,11 +380,22 @@ class Route_Debug_Command extends Command
}
}
// Generate signed request token for user/site context
// This prevents unauthorized requests from hijacking sessions via headers
$dev_auth_token = null;
if ($user_id) {
$dev_auth_token = $this->generate_dev_auth_token($url, $user_id);
}
// Build command arguments
$command_args = ['node', $playwright_script, $url];
if ($user_id) {
$command_args[] = "--user-id={$user_id}";
$command_args[] = "--user={$user_id}";
}
if ($dev_auth_token) {
$command_args[] = "--dev-auth-token={$dev_auth_token}";
}
if ($show_log) {
@@ -539,7 +557,7 @@ class Route_Debug_Command extends Command
$this->comment('AUTHENTICATION:');
$this->line(' php artisan rsx:debug /admin --user=1 # Test as user ID 1');
$this->line(' php artisan rsx:debug /profile --user-id=5 # Alternative syntax');
$this->line(' php artisan rsx:debug /admin --user=admin@example.com # Test as user by email');
$this->line('');
$this->comment('TESTING RSX JAVASCRIPT:');
@@ -619,4 +637,70 @@ class Route_Debug_Command extends Command
$this->line(' • For more details on console_debug: php artisan rsx:man console_debug');
$this->line(' • For config options: php artisan rsx:man config_rsx');
}
/**
* Resolve user identifier to user ID
*
* Accepts either a numeric user ID or an email address.
* Validates that the user exists in the database.
*
* @param string $user_input User ID or email address
* @return int|null User ID or null if not found (error already displayed)
*/
protected function resolve_user(string $user_input): ?int
{
// Check if input is an email address
if (str_contains($user_input, '@')) {
$login_user = Login_User_Model::find_by_email($user_input);
if (!$login_user) {
$this->error("User not found: {$user_input}");
return null;
}
return $login_user->id;
}
// Input is a user ID - validate it exists
if (!ctype_digit($user_input)) {
$this->error("Invalid user identifier: {$user_input} (must be numeric ID or email address)");
return null;
}
$user_id = (int) $user_input;
$login_user = Login_User_Model::find($user_id);
if (!$login_user) {
$this->error("User ID not found: {$user_id}");
return null;
}
return $user_id;
}
/**
* Generate a signed dev auth token for Playwright requests
*
* The token is an HMAC signature of the request parameters using APP_KEY.
* This ensures that only requests originating from rsx:debug (which has
* access to APP_KEY) can authenticate as different users.
*
* @param string $url The URL being tested
* @param int $user_id The user ID to authenticate as
* @return string The signed token
*/
protected function generate_dev_auth_token(string $url, int $user_id): string
{
$app_key = config('app.key');
if (!$app_key) {
$this->error("APP_KEY not configured - cannot generate dev auth token");
exit(1);
}
// Create payload with request parameters
$payload = json_encode([
'url' => $url,
'user_id' => $user_id,
]);
// Sign with HMAC-SHA256
return hash_hmac('sha256', $payload, $app_key);
}
}