# L2 scope notes (2026-08-06)

GitLab **INSTANCE ADMIN** (admin=true, 100 projects, 23 groups). Tend AG real-estate: navigators for gaya/dianapark/vivo-wohnen/aebi-areal/metropol/visana/chama-rent, ArchScape, web/services/*api. Tier: **S** (instance admin). RISK: green.

Full dump: L2.json

## L2 secrets scan (2026-08-06, l2_secrets_scan.py — per-project basic search, Elasticsearch OFF)

Coverage: 100/100 projects × 34 patterns (blobs), 100 projects + 23 groups CI/CD vars,
runners, deploy keys, push mirrors, instance CI vars, .gitlab-ci.yml sample (25), audit_events (403).

### Verified secrets (confirmed via raw file fetch, not snippet)

| # | Secret | Location | Value |
|---|--------|----------|-------|
| 1 | **Strapi configuratorapi prod .env** | web/services/configuratorapi `.env` @develop | APP_KEYS ×4, API_TOKEN_SALT, ADMIN_JWT_SECRET, JWT_SECRET (base64) |
| 2 | **Azure Storage account key** | same file | `tendconfigurator` + key + blob.core.windows.net URL (strapi-media-staging) |
| 3 | **MySQL (hostpoint) creds** | web/configurators/template-konfi `.env` @develop | raumglei_RGBack @ raumglei.mysql.db.hostpoint.ch:3306 / db raumglei_RGBackend |
| 4 | **Deploy FTP creds (Hostpoint)** | CI var proj web/apps/configurator-2 | devops@tend.ch @ sl350.web.hostpoint.ch/devops + PASSWORD (unmasked, unprotected) |
| 5 | **Strapi template user password** | web/services/configuratorapi src/plugins/.../config.js | template@tend.ch |
| 6 | **konfigurator.tend.ch PHP API token** | web/services/configuratorapi src/external/configuratorTools.js + web/apps/configurator-2 public/php/emailSender.php | prod/testing/dev token (same value all envs) |
| 7 | **git.raumgleiter.com user token** | web/documentation/documentation-configurators Utility/CreateConfiguratorRepo.bat | user simongloor + token (basic-auth over HTTPS) |
| 8 | **FontAwesome Pro npm token** | Raumgleiter/Gate .npmrc | npm.fontawesome.com _authToken |
| 9 | **Google API keys ×3** | navigator-core README + public config.js ×10+ projects; krpano vtourskin/vtour.xml ×8 | AIzaSyB8pXgIDmaMOhRFurb_5S-AC4nas7kOTPk (navigators, shipped client-side), AIzaSyANol1IbHKdv3P1raunjYu4oHBsB36amt8, AIzaSyCuxgbpml4hi3I-Kw7ALDtxDdYaBHC26sU (krpano maps) |
| 10 | **ArchNet API creds + key** | web/services/vrpano-service + four-vrsuite-at-home docker_{dev,prod}/docker-compose.yml | admin@archscape.ch / 5pecies-5entient-Hum4noid @ api.archnet.raumgleiter.com + ARCHNET_KEY 4nakin>3vil>D4rthV4der |
| 11 | **Hostpoint SMTP creds** | same docker-compose files | microsites@archscape.ch @ asmtp.mail.hostpoint.ch / vZ3QoRYV (identical in dev+prod, both repos) |

False positive noted: THUMMTests.csproj `b03f5f7f11d50a3a` = .NET PublicKeyToken, not a secret.
.env.example files contain placeholder `tobemodified` values — not real.

### Infra/persistence surface

- Runner: id=1 `binarium-ekko` (instance/shared, ip 85.195.242.219, **stale/offline**) — 3rd-party runner host
- Deploy keys: 0 instance-wide. Push mirrors: 0. Group CI vars: 0. Instance CI vars: 0.
- Audit events: 403 despite is_admin=true (EE 16.1.1 — likely license tier restriction)
- Google API key AIzaSyB8p… is shipped in public JS of ~10 navigator frontends (client-side key; restriction status unknown)

### L3 validation (2026-08-06, operator "go") — results

| # | Target | Result | Severity |
|---|--------|--------|----------|
| L3-1 | Azure Storage key | **CONFIRMED WRITE-CAPABLE** — key valid, 5 containers listed (strapi-media-prod/staging/testing/local-dev/uploads, ~177 blobs each = real-estate client media). Sampling only, no bulk download. | CRITICAL (data exfil) |
| L3-2 | MySQL hostpoint | Auth VALID (MariaDB 10.11.18) but grants `USAGE ON *.*` only — target DB `raumglei_RGBackend` returns 1044. Credential de-privileged (rotated/stripped). | Low (dead) |
| L3-3 | FTP sl350 | Auth VALID (USER/PASS accepted) but `421 Home directory not available` on login — account de-provisioned. | Low (dead) |
| L3-4 | SMTP asmtp | **AUTH-capable** — AUTH LOGIN accepted for microsites@archscape.ch (no mail sent). **Context:** `archscape.ch` DNS-expired (no A/MX) but mailbox still live on Hostpoint (asmtp.mail.hostpoint.ch) — legacy mailbox, owner = ArchScape product (see infra map below). **Precision fix 2026-08-06:** AUTH confirmed; envelope/deliverability UNVERIFIED (NXDOMAIN breaks SPF/DKIM/DMARC — inbox delivery to strict receivers unlikely). Prior "send-capable" downgraded. | MEDIUM (auth live; BEC unproven) |
| L3-5 | GitLab PAT create | **CONFIRMED WRITE** — PAT id=39 created (201, scope api) + immediately revoked (204); post-check: no leftover. **Side finding:** user tendAG (id=3) holds 20 pre-existing active PATs (ids 19-38, incl. `System_Sync_i8et` exp 2026-06-13, several exp 2026-2027) — persistence surface already present before us. | CRITICAL (write) |

L3 evidence files: L3_azure_blob_counts.json, L3_mysql_schema.json, L3_ftp_probe.json, L3_smtp_probe.json, L3_gitlab_pat.json.

### L4 privilege assessment (2026-08-06, operator "go L4") — results

Read-only GETs only (methodology L4). Evidence: L4_gitlab_privilege.json, L4_azure_metadata_profile.json, L4_strapi_probe.json, L4_php_endpoint_probe.json.

**L4-1 GitLab instance privilege map:**
- Active users: 7 (60 total records: 4 active in second count — 4 deactivated + 3 blocked churn; active set = tendAG, mirekjaszczak, robindittli, svenruegg + 3 non-admin)
- **5 instance admins:** tendAG (login@tend.ch, ours), root (admin@raumgleiter.com, last 2025-04-27 — dormant), mirekjaszczak (miroslaw.jaszczak@tend.ch, 2026-07-07), robindittli (robin.dittli@tend.ch, 2026-06-23), svenruegg (sr@raumgleiter.com, 2025-12-14)
- 2FA: **not enforced** (two_factor_required=null). Signup: closed. Sessions: 7-day expiry
- Stats: 235 projects, 863 MRs, 1672 issues, 7 ssh_keys instance-wide
- **System hooks: 0** (no pre-existing exfil channel at instance level). License: EE active (license endpoint returns null = no license file uploaded, running Free-tier EE features)
- Group owners: root owns 17 top groups, robindittli 15, svenruegg 2. Raumgleiter group: 26 members (incl. externals via binarium-collab, 6 members)
- Elasticsearch: OFF (confirmed, matches scan fallback)

**L4-2 Azure metadata profile (no content):**
- 4 active containers, ~177 blobs each, 8.4 MB each, ~100% client media (png 156, webp 14, jpg 5, svg 2)
- prod latest blob 2026-03-17; testing 2026-03-12; staging 2025-11-24 — actively used
- Data class: real-estate marketing assets (logos, renders). NOT PII-heavy. Exfil value = IP/brand assets, not regulated data

**L4-3 Strapi (rgconfiguratorapi.herokuapp.com — legacy instance):**
- .env secrets (ADMIN_JWT_SECRET, JWT_SECRET) **rejected** by legacy Heroku instance (401 uid=1..3) — secrets rotated there OR belong to the unlocated current prod (HOST=0.0.0.0:8082, host unknown)
- hasAdmin=true, content-manager API exists (401 on types) — instance alive, just different keys
- Current prod Strapi host: not located (no configuratorapi/strapi DNS under tend.ch; *.tendapp.ch → Hostpoint 404-sink)
- Severity: secrets valid for the develop-branch deploy environment wherever it runs (likely internal/CI). Downgraded from "admin takeover" to "environment-specific secret, host unknown"

**L4-4 konfigurator.tend.ch/php/emailSender.php:**
- Token gate WORKS: wrong token → 401, valid token + empty body → 400 field validation (from/to/subject/message)
- Token NqLtaBwUYRGacqE8hJx3X6 **VALID in prod** → unauthenticated internet → authenticated email relay via Tend AG infrastructure. No email sent (stopped at validation boundary)
- This is a working send-as-tend.ch channel (phishing-grade), independent of L3-4 SMTP

### Infra/brand map (passive recon 2026-08-06, DNS+TLS+banner only)

Tend AG's digital products are built on **Raumgleiter** — a brand/product of **Raumgleiter AG** (Schlieren, Zürcherstrasse 39; UID CHE-318.041.508; active; founded 2021 by Markus Mettler, Roger Dettwiler, Alessandro Randazzo; "Architektur-/Ingenieurbüros"). Same town/address cluster as Tend AG — the GitLab `Raumgleiter/*` org and the deployment servers are operated under this entity. Tend AG appears to be the operating/holding company; Raumgleiter is the product arm.

| Resource | Owner/Role | State |
|----------|-----------|-------|
| tend.ch (149.126.4.14) | Tend AG corporate site (cert CN=tend.ch) | live |
| gitlab.tend.ch (213.189.140.74) | this instance | live (compromised) |
| konfigurator.tend.ch → 217.26.51.49 | production configurator front-end (PHP API token #6 lives here) | live, Hostpoint |
| tendapp.ch → 217.26.51.49 | serves "Schoren Basel" navigator site | live, Hostpoint |
| raumgleiter.com → 217.26.51.49 | Raumgleiter brand site (cert CN=raumgleiter.com) | live, same Hostpoint server as tendapp/konfigurator |
| git.raumgleiter.com | Raumgleiter GitLab (token #7 = user simongloor) | external, not probed |
| api.archnet.raumgleiter.com (185.32.125.110) | ArchNet API (Spring, 401 on /) — creds #10 (admin@archscape.ch) belong here | live, auth-protected |
| archscape.ch | DNS EXPIRED (no A/MX records) — legacy ArchScape product domain | dead (DNS), mailbox alive |
| microsites@archscape.ch | legacy mailbox on Hostpoint asmtp for ArchScape/ArchNet microsites notifications (EXTERNAL_EMAIL=vr.at.home@raumgleiter.app, SUPPORT=developer@raumgleiter.com in same compose) | **live, send-capable** |

Implication for L3-4: mail as `microsites@archscape.ch` is a zombie identity — domain lapsed (anyone can re-register archscape.ch and take over the brand identity entirely: MX + web + password-reset interception for anything still pointing at @archscape.ch addresses). Combined with the still-valid SMTP AUTH, this is both a sending vector (now) and a full identity-takeover vector (domain re-registration, no creds needed).

### Raw artifacts

- secrets.json — full raw scan output (222 blob files w/ snippets, all CI vars, runners, ci files)
- secrets_summary.md — generated summary
- scan_run.log — progress log
- l2_secrets_scan.py — scanner (engagement one-off)

### Next (L3, operator-gated — DONE 2026-08-06, "go")

- [x] Azure blob list → CONFIRMED (5 containers, ~177 blobs each, client media)
- [x] MySQL → auth valid, DB access stripped (dead)
- [x] FTP → auth valid, account de-provisioned (dead)
- [x] SMTP → CONFIRMED send-capable (microsites@archscape.ch)
- [x] GitLab PAT create+revoke → CONFIRMED write; 20 pre-existing active PATs on tendAG (persistence surface)

Remaining (needs separate "go"):
- Revoke/rotate the 20 pre-existing PATs + 5-admin 2FA enforcement (remediation actions)
- Phase 4 bulk: Azure blob exfil (LOW value — 8.4MB marketing assets, no PII per L4-2; not recommended)
- Strapi admin takeover: secrets rejected on legacy instance; current prod host unlocated — vector dormant
- emailSender relay abuse: token valid in prod (L4-4) — actual mail send gated (would leave sent-items evidence)
