- Add package name validation with strict regex patterns - Convert all Process::run() calls to array syntax - Support Composer and NPM package name formats - Add comprehensive shell injection tests (20 attack patterns) - Update security docs and changelog Fixes P2 shell injection vulnerability from security audit. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
8.7 KiB
| title | description | updated |
|---|---|---|
| Security | Security considerations and audit notes for core-uptelligence | 2026-01-29 |
Security Considerations
This document outlines security considerations, implemented protections, and areas requiring attention for the core-uptelligence package.
Authentication and Authorisation
Webhook Authentication
Webhooks are authenticated via HMAC signature verification, not API tokens or session auth.
Implementation: Models/UptelligenceWebhook.php
| Provider | Method | Algorithm |
|---|---|---|
| GitHub | X-Hub-Signature-256 header |
HMAC-SHA256 |
| GitLab | X-Gitlab-Token header |
Direct comparison |
| npm | X-Npm-Signature header |
HMAC-SHA256 |
| Packagist | X-Hub-Signature header |
HMAC-SHA1 |
| Custom | X-Signature header |
HMAC-SHA256 |
Strengths:
- Uses
hash_equals()for timing-safe comparison - Supports secret rotation with grace period
- Previous secret accepted during 24-hour grace period
Weaknesses:
- GitLab uses simple token comparison (not HMAC)
- No IP allowlist for webhook sources
- No request signing for outbound API calls
Admin Access
Admin routes are protected by middleware defined at the application level. The package itself does not enforce authorisation.
Risk: If admin middleware is misconfigured, admin endpoints could be exposed.
Recommendation: Add explicit authorisation checks in Livewire components.
API Token Storage
External API tokens (GitHub, Gitea, AI providers) are stored in environment variables, not in the database.
Configuration: config.php
'github' => [
'token' => env('GITHUB_TOKEN'),
],
'gitea' => [
'token' => env('GITEA_TOKEN'),
],
Strength: Tokens not exposed in database backups.
Input Validation
Webhook Payloads
Current state:
- JSON parsing with error handling
- Signature verification before processing
- Event type extraction from headers/payload
Missing:
- Maximum payload size validation
- Schema validation for expected structure
- Protection against deeply nested JSON
- Rate limiting per source IP (partially implemented)
File Path Validation
Implementation: Services/DiffAnalyzerService.php:232-274
Path traversal protection is implemented:
protected function validatePath(string $path, string $basePath): string
{
// Check for path traversal attempts
if (str_contains($path, '..') || str_contains($path, "\0")) {
throw new InvalidArgumentException('Invalid path: path traversal not allowed');
}
// ... realpath validation
}
Strengths:
- Blocks
..sequences - Blocks null bytes
- Validates against real filesystem path
Shell Command Execution
Risk areas:
-
DiffAnalyzerService::generateDiff()- Uses array syntax (safe)Process::run(['diff', '-u', $prevPath, $currPath]); -
VendorStorageService::createArchive()- Uses array syntax (safe)new Process(['tar', '-czf', $archivePath, '-C', $sourcePath, '.']); -
AssetTrackerService- Uses array syntax with validation (FIXED)// Package names are validated against allowlist patterns before use $packageName = $this->validatePackageName($asset->package_name, Asset::TYPE_COMPOSER); Process::run(['composer', 'show', $packageName, '--format=json']);
Mitigations applied:
- Array-based Process invocation prevents shell metacharacter interpretation
- Package name validation rejects names containing shell injection characters
- Invalid package names are logged and result in safe error responses
Data Protection
Sensitive Data Handling
Encrypted fields:
UptelligenceWebhook.secret- Laravel encrypted castUptelligenceWebhook.previous_secret- Laravel encrypted cast
Hidden from serialisation:
- Both secret fields are in
$hiddenarray
Logging Considerations
Risk: API responses and payloads may be logged on error.
Current logging:
Log::error('Uptelligence: GitHub issue creation failed', [
'todo_id' => $todo->id,
'status' => $response->status(),
'body' => substr($response->body(), 0, 500), // Truncated but may contain sensitive data
]);
Recommendation:
- Redact or exclude response bodies
- Never log full webhook payloads
- Use structured logging with PII filtering
File Storage Security
S3 Configuration:
- Uses private bucket by default
- Dual endpoint support for Hetzner Object Store
- Files stored with
application/gzipcontent type
Local Storage:
- Files stored under
storage/app/vendors/ - Not publicly accessible by default
- Temp files cleaned up after 24 hours
Rate Limiting
Implemented Limiters
| Limiter | Rate | Scope |
|---|---|---|
upstream-ai-api |
10/minute | Global |
upstream-registry |
30/minute | Global |
upstream-issues |
10/minute | Global |
uptelligence-webhooks |
60/minute | Per webhook UUID or IP |
Webhook Rate Limiting
RateLimiter::for('uptelligence-webhooks', function (Request $request) {
$webhook = $request->route('webhook');
return $webhook
? Limit::perMinute(60)->by('uptelligence-webhook:'.$webhook)
: Limit::perMinute(30)->by('uptelligence-webhook-ip:'.$request->ip());
});
Note: IP-based fallback uses $request->ip() which may be spoofed without proper proxy configuration.
External Service Integration
GitHub API
Scopes required:
repo- For reading releases and creating issuesread:org- If targeting organisation repos
Token handling:
- Sent via
Authorization: Bearerheader - Token not logged in error scenarios
Gitea API
Token handling:
- Sent via
Authorization: tokenheader - Similar security profile to GitHub
AI Providers (Anthropic/OpenAI)
Data sent to AI:
- Code diffs (potentially containing sensitive patterns)
- File paths
- Vendor names
Recommendation:
- Consider PII scanning before AI submission
- Document data processing in privacy policy
- Offer opt-out for AI analysis
Known Vulnerabilities
Critical
-
Missing database migrations - Core models reference non-existent tables
- Impact: Application will fail on first use
- Status: Documented in TODO.md P1
-
Shell injection in AssetTrackerService- FIXED- Impact: Was arbitrary command execution if package names were malicious
- Status: RESOLVED - Now uses array-based Process invocation with package name validation
High
-
No authorisation in Livewire components
- Impact: Relies entirely on route middleware
- Mitigation: Admin routes should be protected at application level
-
Missing File facade import in VendorStorageService
- Impact: Runtime errors in extractMetadata/getDirectorySize
- Status: Documented in TODO.md P2
Medium
-
Inconsistent workspace scoping
- Impact: Vendor data may leak between workspaces
- Status: Design decision needed
-
Webhook payloads stored unencrypted
- Impact: Payload data visible in database
- Mitigation: Payloads are not typically sensitive
Security Checklist for Production
Before deploying to production:
- All API tokens set via environment variables
- S3 bucket configured as private
- Webhook secrets generated with sufficient entropy (64+ characters)
- Rate limiters tested and tuned
- Admin routes protected by authentication middleware
- Logging configured to exclude sensitive data
- Database migrations created and run
- AssetTrackerService shell injection fixed
- Trusted proxy configuration set (for accurate IP detection)
Incident Response
Compromised Webhook Secret
- Rotate secret immediately via
webhook->rotateSecret() - Grace period allows valid senders to update
- Monitor for invalid signature attempts
- After grace period, old secret is invalidated
Compromised API Token
- Revoke token at provider (GitHub/Gitea)
- Generate new token
- Update environment variable
- Restart application
- Review logs for unauthorised actions
Suspected Data Breach
- Check webhook delivery logs for unusual patterns
- Review AI API call logs for data exfiltration
- Audit S3 access logs
- Check for path traversal attempts in logs
Compliance Notes
GDPR Considerations
- Webhook payloads may contain contributor names/emails
- AI analysis may process code comments with PII
- Digest notifications sent to user email addresses
Recommendations:
- Document data flows in privacy policy
- Implement data retention policies
- Provide data export/deletion capabilities
EUPL-1.2 License
The package is licensed under EUPL-1.2 (copyleft).
- Modifications to
Core\namespace must be shared - Does not apply to vendor code being analysed
- External API usage subject to provider terms