php-uptelligence/docs/security.md
Snider ef8a40829f security: fix shell injection in AssetTrackerService
- 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>
2026-01-29 12:21:07 +00:00

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:

  1. DiffAnalyzerService::generateDiff() - Uses array syntax (safe)

    Process::run(['diff', '-u', $prevPath, $currPath]);
    
  2. VendorStorageService::createArchive() - Uses array syntax (safe)

    new Process(['tar', '-czf', $archivePath, '-C', $sourcePath, '.']);
    
  3. 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 cast
  • UptelligenceWebhook.previous_secret - Laravel encrypted cast

Hidden from serialisation:

  • Both secret fields are in $hidden array

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/gzip content 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 issues
  • read:org - If targeting organisation repos

Token handling:

  • Sent via Authorization: Bearer header
  • Token not logged in error scenarios

Gitea API

Token handling:

  • Sent via Authorization: token header
  • 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

  1. Missing database migrations - Core models reference non-existent tables

    • Impact: Application will fail on first use
    • Status: Documented in TODO.md P1
  2. 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

  1. No authorisation in Livewire components

    • Impact: Relies entirely on route middleware
    • Mitigation: Admin routes should be protected at application level
  2. Missing File facade import in VendorStorageService

    • Impact: Runtime errors in extractMetadata/getDirectorySize
    • Status: Documented in TODO.md P2

Medium

  1. Inconsistent workspace scoping

    • Impact: Vendor data may leak between workspaces
    • Status: Design decision needed
  2. 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

  1. Rotate secret immediately via webhook->rotateSecret()
  2. Grace period allows valid senders to update
  3. Monitor for invalid signature attempts
  4. After grace period, old secret is invalidated

Compromised API Token

  1. Revoke token at provider (GitHub/Gitea)
  2. Generate new token
  3. Update environment variable
  4. Restart application
  5. Review logs for unauthorised actions

Suspected Data Breach

  1. Check webhook delivery logs for unusual patterns
  2. Review AI API call logs for data exfiltration
  3. Audit S3 access logs
  4. 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