diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 0d3ff49..149d94f 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -130,11 +130,11 @@ jobs: id: stan run: | set +e - vendor/bin/phpstan analyse --error-format=json --no-progress > phpstan.json 2>&1 + vendor/bin/phpstan analyse --error-format=json --no-progress > phpstan.json EXIT_CODE=$? # Also run for GitHub format - vendor/bin/phpstan analyse --error-format=github --no-progress 2>&1 || true + vendor/bin/phpstan analyse --error-format=github --no-progress || true ERRORS=$(jq '.totals.file_errors // 0' phpstan.json 2>/dev/null || echo "0") echo "errors=${ERRORS}" >> $GITHUB_OUTPUT @@ -181,11 +181,11 @@ jobs: id: psalm run: | set +e - vendor/bin/psalm --output-format=json --show-info=false > psalm.json 2>&1 + vendor/bin/psalm --output-format=json --show-info=false > psalm.json EXIT_CODE=$? # Generate SARIF for GitHub Security - vendor/bin/psalm --output-format=sarif --show-info=false > psalm.sarif 2>&1 || true + vendor/bin/psalm --output-format=sarif --show-info=false > psalm.sarif || true ERRORS=$(jq 'length' psalm.json 2>/dev/null || echo "0") echo "errors=${ERRORS}" >> $GITHUB_OUTPUT @@ -242,11 +242,10 @@ jobs: id: fmt run: | set +e - OUTPUT=$(vendor/bin/pint --test --format=json 2>&1) + vendor/bin/pint --test --format=json > pint.json EXIT_CODE=$? - echo "$OUTPUT" > pint.json - FILES=$(echo "$OUTPUT" | jq '.files | length' 2>/dev/null || echo "0") + FILES=$(jq '.files | length' pint.json 2>/dev/null || echo "0") echo "files=${FILES}" >> $GITHUB_OUTPUT if [ $EXIT_CODE -eq 0 ]; then diff --git a/AUDIT-AUTH.md b/AUDIT-AUTH.md new file mode 100644 index 0000000..40187a8 --- /dev/null +++ b/AUDIT-AUTH.md @@ -0,0 +1,35 @@ +# Security Audit: Authentication & Authorization + +## Authentication Review + +### Password Handling +- **Hashing Algorithm:** The application utilizes a custom hashing solution, `LthnHash`, which is explicitly documented as **not suitable for password hashing**. A `grep` search for `password_hash` returned no results, indicating that the application is not using the standard, secure password hashing functions provided by PHP. This represents a critical security vulnerability. +- **Salt Usage:** The `LthnHash` implementation uses a deterministic "salt" generation method, which is not suitable for password hashing. A random salt should be generated for each password. +- **Password Requirements:** No evidence of password complexity requirements was found during this audit. +- **Reset Flow Security:** The password reset flow could not be located and audited. + +### Session Management +- **Session Configuration:** The `config/session.php` file is missing from the repository. While the application uses Laravel's session helpers (`config('session.driver')`), the absence of the configuration file means the application is relying on default, potentially insecure, session settings. +- **Session ID Generation:** Without the configuration file, it is not possible to verify the security of the session ID generation. +- **Session Fixation Protection:** It is not possible to confirm that session fixation protection is enabled. +- **Timeout Policies:** Session lifetime and timeout policies cannot be audited. +- **Concurrent Session Handling:** The handling of concurrent sessions cannot be determined. + +### Token Security +- **Token Management:** The application uses a decentralized token management strategy. The `MakePlugCommand` command generates "Plugs" that use the `ManagesTokens` trait to handle their own tokens. This means that token security is not centralized, and each "Plug" is responsible for its own token storage, refresh, and revocation. +- **JWT Implementation:** No evidence of JWT implementation was found. +- **Token Storage:** The token storage mechanism is not defined in the `ManagesTokens` trait. It is up to the individual "Plug" to implement token storage. This could lead to inconsistent and insecure token storage practices. +- **Refresh Token Rotation:** Refresh token rotation is not handled by the `ManagesTokens` trait. +- **Token Revocation:** Token revocation is not handled by the `ManagesTokens` trait. + +### Multi-factor +- **MFA Implementation:** No evidence of a multi-factor authentication system was found in the codebase. +- **Bypass Vulnerabilities:** Not applicable. +- **Recovery Codes:** Not applicable. + +## Authorization Review +- **Access Control Model:** The application uses a custom "action whitelisting" system implemented in the `Core\Bouncer\Gate` directory. This system acts as a pre-authorization layer that checks if a controller action is explicitly permitted before it is executed. It is designed to work in conjunction with Laravel's standard Gate/Policy system. +- **Permission Checks:** Permission checks are centralized in the `ActionGateService`. The `ActionGateMiddleware` intercepts incoming requests and uses the `ActionGateService` to verify that the requested action is on the whitelist. +- **Privilege Escalation:** The risk of privilege escalation is mitigated by the "default-deny" nature of the action whitelisting system. However, the security of this system depends on the proper configuration and maintenance of the whitelist. +- **API Authorization:** The `guarded_middleware` configuration in `config/core.php` indicates that the action gate is applied to `api` routes, but a full audit of all API endpoints is required to ensure complete protection. +- **Resource Ownership:** No evidence of resource ownership checks (to prevent IDOR vulnerabilities) was found in the `Core\Bouncer\Gate` system. This is likely handled by the underlying Laravel Gate/Policy system, which could not be audited.