Add PHP trackingreportservice (Path Traversal + XPath Injection) - #41
Open
bsowers-contrast wants to merge 25 commits into
Open
Add PHP trackingreportservice (Path Traversal + XPath Injection)#41bsowers-contrast wants to merge 25 commits into
bsowers-contrast wants to merge 25 commits into
Conversation
Replaces XPath Injection (Assess-only, no Protect coverage) with Path Traversal (both Assess and Protect coverage in the PHP agent) so the PHP service tells the same dual Assess+Protect story as the rest of cargo-cats. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ersal Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove searchTrackingHistory endpoint entirely (XPath sink) - Rewrite getTrackingReport to use safe DOM iteration instead of XPath - Add GET /api/tracking-report/download?file= with vulnerable file_get_contents - Seed per-shipment text reports under var/reports/exports/ at boot The new sink has both Assess and Protect coverage in the Contrast PHP agent, restoring the dual coverage story for this service. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove the /api/tracking-report/search proxy (XPath demo deleted) and add /api/tracking-report/download which proxies the Path Traversal sink in the PHP service. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Matches the symmetric naming used by getTrackingReport and addTrackingEvent (controller method == proxy method). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The new /exploit/php-path-traversal endpoint targets the new PHP trackingreportservice download endpoint and uses a disambiguated name to avoid colliding with the existing .NET imageservice path-traversal exploit. Phase 10 normal traffic now exercises the new download endpoint with seeded report filenames instead of the deleted /search route. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The actual ingress host is cargocats.localhost, not app.localhost. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
With the PHP path traversal exploit now sitting next to it in the UI, labeling the .NET imageservice exploit explicitly avoids demo audience confusion about which language each button targets. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dpoint Re-introduces the searchTrackingHistory endpoint on the PHP service with its original XPath injection sink, the matching frontgate proxy/route, and the console-ui exploit and normal-traffic wiring. Sits alongside the Path Traversal download endpoint. Path Traversal demonstrates dual Assess + Protect coverage; XPath Injection demonstrates Assess-only detection (no Protect rule exists for XPath in any Contrast language agent), telling the "Assess catches what Protect cannot" story. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Symfony's autoload_runtime calls bootEnv() which requires a .env file at the project root, even when APP_ENV is set in the process env. The cache:warmup step was failing because no .env was checked in. Generate one inside the image so the file lives only in the built container, not in the repo. The Helm chart overrides APP_* via Kubernetes env vars at runtime. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The exports directory is /var/www/var/reports/exports, which sits 5 levels below filesystem root. The previous 4-dotdot payload resolved to /var/etc/passwd (nonexistent), so file_exists() returned false and the endpoint replied 404 instead of disclosing /etc/passwd. Updates the controller docblock example, both console-ui exploit variants (raw and URL-encoded), and the vulnerabilities.md curl example. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # Makefile # README.md # cargocats/values.yaml # services/console-ui/app.py # services/frontgateservice/src/main/java/com/contrast/frontgateservice/controller/ApiController.java
The reports page load and report-service health check still used a 5s timeout. After a rolling restart the reports page first-hit can exceed that (the shadow-AI insight in reportservice now also calls ollama). The actual report generation and AI summary POSTs were already bumped to 60s/120s in a previous main commit; this brings the page load and health check in line. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The spec and implementation plan under docs/superpowers/ were development-time artifacts and do not belong alongside the user-facing docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add "Download as Text" link next to "Export Tracking Report" on the tracking results card. Hits /api/tracking-report/download with the TRACK-<id>.txt seeded filename. - Add "Search Tracking History" form on the landing page that hits /api/tracking-report/search and renders matches in a table. This also gives a UI surface for the XPath Injection demo (paste the payload directly into the search box). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous UI work added the search form to index.html (landing page), which authenticated users do not see. The dashboard's Track Shipment modal is the actual entry point post-login, so move the search form there alongside the existing tracking lookup. Also widens the tracking modal to modal-lg to fit the results table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bsowers-contrast
requested review from
jason-at-contrast,
sergeib-gmail and
svevia
May 28, 2026 20:04
There was a problem hiding this comment.
Pull request overview
Adds a new PHP/Symfony trackingreportservice to the cargo-cats demo, intentionally exposing Path Traversal (download endpoint) and XPath Injection (search endpoint) for Contrast detection storytelling. The service is wired into the existing Spring frontgate, dashboard UI, simulation console (normal-traffic phase 11 + two new individual exploits), Helm chart, agent-operator config, and docs.
Changes:
- New PHP/Symfony microservice with seeded XML/text reports, vulnerable download and search endpoints, plus benign GET/POST routes; Helm template, Dockerfile, Apache vhost, and
contrast-php-injectoradded. - Frontgate Java proxy + four
/api/tracking-report/*routes, plus tracking history search UI inindex.html/dashboard.htmland new buttons in the track-shipment result. - Console UI adds phase 11 normal traffic and two new individual exploits (PHP Path Traversal, XPath Injection), and relabels the existing .NET path traversal button.
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| services/trackingreportservice/src/Kernel.php | Standard Symfony micro-kernel entrypoint. |
| services/trackingreportservice/src/Controller/TrackingReportController.php | Core controller with seeding, MySQL sync, and the two intentional vulnerabilities. |
| services/trackingreportservice/public/index.php | Symfony front-controller bootstrap. |
| services/trackingreportservice/Dockerfile | Ubuntu + Apache + mod_php image, Composer install and cache warmup. |
| services/trackingreportservice/docker/apache-site.conf | Apache vhost routing to Symfony front controller. |
| services/trackingreportservice/config/services.yaml | Symfony framework + service container config. |
| services/trackingreportservice/config/routes.yaml | Attribute-based controller route loader. |
| services/trackingreportservice/composer.json | Symfony 7 / PHP 8.1+ dependency manifest. |
| services/trackingreportservice/bin/console | Symfony console entrypoint. |
| services/trackingreportservice/.gitignore | Standard Symfony ignores plus seeded XML store. |
| services/frontgateservice/src/main/resources/templates/index.html | Adds Search Tracking History form + JS handler on landing page. |
| services/frontgateservice/src/main/resources/templates/dashboard.html | Widens tracking modal and adds history search form + handler. |
| services/frontgateservice/src/main/resources/application.properties | Adds trackingreportservice.url config. |
| services/frontgateservice/src/main/java/.../TrackingReportServiceProxy.java | New REST proxy for the four tracking-report endpoints. |
| services/frontgateservice/src/main/java/.../ApiController.java | Wires four /api/tracking-report/* routes and adds report/download buttons in track HTML. |
| services/console-ui/templates/index.html | Adds two PHP exploit buttons and relabels Path Traversal as .NET. |
| services/console-ui/app.py | Adds PHP path traversal + XPath injection exploits, phase 11 traffic, exploit list updates. |
| README.md | Updates architecture diagram, service count, and vulnerability list. |
| Makefile | Adds build-trackingreportservice target. |
| docs/vulnerabilities.md | Documents the two new PHP vulnerabilities. |
| contrast-agent-operator-config.yaml | Adds a contrast-php-injector AgentInjector. |
| cargocats/values.yaml | Adds Helm values entry for the new service. |
| cargocats/templates/trackingreportservice.yaml | Adds Deployment + Service for the new microservice. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1. Remove dead contrast-php-injector. All services use the contrast-agent: flex label and match the flex injector, so the php-specific injector never bound and was misleading config. 2. URL-encode the q parameter in TrackingReportServiceProxy searchTrackingHistory, consistent with the other proxy methods. Search terms containing &, #, +, or spaces would otherwise produce a malformed upstream URL. 3. Add an escapeHtml() helper in both index.html and dashboard.html and apply it to all user-controlled fields rendered into the tracking history results table. Avoids DOM-XSS via tracking ID, cat name, origin, destination, status, or the search term itself. 4. URL-encode trackingIdValue in the two new anchor hrefs (Export Tracking Report, Download as Text) in ApiController. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Squashed follow-up doc tweaks (4 commits) into one. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bsowers-contrast
force-pushed
the
add-php-service
branch
from
May 28, 2026 20:30
de62d1b to
fa06cae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new PHP/Symfony microservice,
trackingreportservice, that demonstrates two Contrast detection stories:GET /api/tracking-report/download?file=...— caught by Assess (data-flow trace tofile_get_contents) and blocked by Protect (Path Traversal RASP rule).GET /api/tracking-report/search?q=...— caught by Assess only (no Protect rule exists for XPath in any Contrast language agent). This is the side-by-side counterpoint that sells the "Assess catches what Protect can't" story.Closes a meaningful language gap in cargo-cats (Java, Python, .NET, Node.js, and now PHP).
What's in the PR
New PHP service (
services/trackingreportservice): Symfony 7 / PHP 8.3 on Apache + mod_php, instrumented by the Contrast PHP agent via the existing agent-operator. Seeds five per-shipment text reports at boot.Frontgate integration: new proxy class and four
/api/tracking-report/*routes (get / search / download / events) wired intoApiController.Dashboard UI: the Track Shipment modal now contains both a lookup form and a Search Tracking History form (with a results table); the lookup results card has Export Tracking Report (JSON) and Download as Text (txt file) buttons.
Simulation console:
Docs:
docs/vulnerabilities.mdgets two new sections (Path Traversal PHP, XPath Injection PHP).Test plan
make deploybuilds all 12 images and reachesRunning 1/1on every podflex-agents/php/1.52.0)/var/www/var/reports/exports/TRACK-*.txt?file=../../../../../etc/passwdreturns/etc/passwdcontents (Protect off)?q=dumps all 5 shipments🤖 Generated with Claude Code