Skip to content

Add PHP trackingreportservice (Path Traversal + XPath Injection) - #41

Open
bsowers-contrast wants to merge 25 commits into
mainfrom
add-php-service
Open

Add PHP trackingreportservice (Path Traversal + XPath Injection)#41
bsowers-contrast wants to merge 25 commits into
mainfrom
add-php-service

Conversation

@bsowers-contrast

@bsowers-contrast bsowers-contrast commented May 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a new PHP/Symfony microservice, trackingreportservice, that demonstrates two Contrast detection stories:

  • Path Traversal in GET /api/tracking-report/download?file=... — caught by Assess (data-flow trace to file_get_contents) and blocked by Protect (Path Traversal RASP rule).
  • XPath Injection in 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 into ApiController.

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:

  • Phase 11 of normal traffic exercises the new tracking-report endpoints (lookup, event POST, download with a random seeded filename, benign search).
  • New individual exploits: Path Traversal (PHP) and XPath Injection (PHP).
  • The existing .NET imageservice button is relabeled to Path Traversal (.NET) for disambiguation.

Docs:

  • docs/vulnerabilities.md gets two new sections (Path Traversal PHP, XPath Injection PHP).
  • README diagram + service list updated.

Test plan

  • make deploy builds all 12 images and reaches Running 1/1 on every pod
  • PHP agent visible in pod logs (flex-agents/php/1.52.0)
  • Seeded files exist at /var/www/var/reports/exports/TRACK-*.txt
  • Legit download returns the seeded report
  • ?file=../../../../../etc/passwd returns /etc/passwd contents (Protect off)
  • URL-encoded variant works the same way
  • XPath tautology in ?q= dumps all 5 shipments
  • Console UI normal-traffic run completes all 11 phases with 200s
  • Console UI "Run All Exploits" includes both PHP exploits and they report SUCCESS
  • Dashboard tracking modal renders the new search form and table results
  • Verify Assess findings appear in Contrast UI (Path Traversal + XPath Injection)
  • Enable Protect for the application, confirm Path Traversal is blocked, confirm XPath Injection is not blocked (the whole point of the side-by-side)

🤖 Generated with Claude Code

trosonke and others added 19 commits May 20, 2026 08:52
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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-injector added.
  • Frontgate Java proxy + four /api/tracking-report/* routes, plus tracking history search UI in index.html/dashboard.html and 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.

Comment thread contrast-agent-operator-config.yaml Outdated
Comment thread services/frontgateservice/src/main/resources/templates/index.html Outdated
bsowers-contrast and others added 4 commits May 28, 2026 15:09
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants