[scan] Security attack vector mapping #26

Open
opened 2026-03-23 12:54:22 +00:00 by Virgil · 1 comment
Member

Map every external input entry point: function, file:line, input source, flows into, validation, attack vector.


Implementation Plan (Spark)

Security Attack Vector Map

Date: 2026-03-23

Scope:

  • Package-local review only. This maps the surfaces visible in this repository and does not assume protections from a parent application unless they are visible here.
  • CODEX.md was not present anywhere under /workspace, so this review used AGENTS.md, CLAUDE.md, and the code itself.
  • No fixes applied.

1. Route and Auth Boundary Map

Primary registration surface:

  • src/Website/Hub/Boot.php:93-98 registers the Hub routes with a domain, /hub prefix, and hub. route name prefix, but no package-local middleware.
  • src/Website/Hub/Routes/admin.php:15-74 defines the GET entry points for the admin panel.

Routeable components that rely on outer middleware only:

Route Entry point Local guard in component Notes
/hub/prompts src/Website/Hub/Routes/admin.php:49 -> src/Website/Hub/View/Modal/Admin/PromptManager.php:69-75 None Global prompt CRUD is exposed through Prompt::query() / findOrFail() / create() / delete() at PromptManager.php:80-87, PromptManager.php:195-259, PromptManager.php:266-286.
/hub/console src/Website/Hub/Routes/admin.php:27 -> src/Website/Hub/View/Modal/Admin/Console.php:13-46 None No auth or tier check before infrastructure/server inventory is loaded into the component state.
/hub/content-manager/{workspace}/{view?} src/Website/Hub/Routes/admin.php:19-20 -> src/Website/Hub/View/Modal/Admin/ContentManager.php:84-105 None Trusts route/event workspace input, then updates the current workspace session state.
/hub/content-editor/{workspace}/new/{contentType?} and /hub/content-editor/{workspace}/{id} src/Website/Hub/Routes/admin.php:21-23 -> src/Website/Hub/View/Modal/Admin/ContentEditor.php:135-188 None Route parameters feed directly into workspace and content loading, followed by global model lookups.
/hub/services/{service?}/{tab?} src/Website/Hub/Routes/admin.php:68-71 -> src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:74-95 None The service dashboard is reachable without a component-level auth check and later trusts tamperable website IDs and paths.
/hub/account/usage src/Website/Hub/Routes/admin.php:32 -> src/Website/Hub/View/Modal/Admin/AccountUsage.php:78-80 None Non-admin account route exposes shared AI service configuration writers at AccountUsage.php:209-270.
/hub/workspaces src/Website/Hub/Routes/admin.php:25 -> src/Website/Hub/View/Modal/Admin/Sites.php:42-46 None Workspace selection is delegated to WorkspaceService; addService() also creates global Feature and Package rows at Sites.php:212-269.

Routeable components that do self-gate:

  • src/Website/Hub/View/Modal/Admin/Platform.php:37-42
  • src/Website/Hub/View/Modal/Admin/PlatformUser.php:65-72
  • src/Website/Hub/View/Modal/Admin/ServiceManager.php:57-61
  • src/Website/Hub/View/Modal/Admin/WaitlistManager.php:45-49
  • src/Website/Hub/View/Modal/Admin/Honeypot.php:28-32
  • src/Website/Hub/View/Modal/Admin/Databases.php:38-42
  • src/Website/Hub/View/Modal/Admin/Deployments.php:21-24, src/Website/Hub/View/Modal/Admin/Deployments.php:262-266
  • src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:83-87
  • src/Website/Hub/View/Modal/Admin/Entitlement/FeatureManager.php:25-29
  • src/Website/Hub/View/Modal/Admin/Entitlement/PackageManager.php:26-30

Discovery amplifiers:

  • The admin layout mounts global search on every admin page at src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98.
  • The search provider advertises sensitive destinations such as prompts, console, deployments, and databases at src/Search/Providers/AdminPageSearchProvider.php:75-129.

2. CSRF-Relevant Admin Mutation Surface

Livewire entry points are mounted from the admin layout and header:

  • src/Website/Hub/View/Blade/admin/layouts/app.blade.php:10 exposes the CSRF token in the page.
  • src/Website/Hub/View/Blade/admin/components/header.blade.php:24 mounts the workspace switcher.
  • src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98 mounts global search.

These are the state-changing methods worth testing for CSRF and replay because they are exposed as public Livewire actions. This map does not assert that Livewire's default token checks are absent; it identifies the methods with the highest impact if those checks are bypassed or weakened.

High-value public mutation methods exposed as Livewire actions:

Component Public action entry points Impact
Platform src/Website/Hub/View/Modal/Admin/Platform.php:60-98 Email verification plus cache, OPcache, and queue control.
PlatformUser src/Website/Hub/View/Modal/Admin/PlatformUser.php:84-149, src/Website/Hub/View/Modal/Admin/PlatformUser.php:250-399, src/Website/Hub/View/Modal/Admin/PlatformUser.php:462-530, src/Website/Hub/View/Modal/Admin/PlatformUser.php:604-707 Tier changes, verification, GDPR export/delete/anonymise, package provisioning, entitlement provisioning, boost removal.
PromptManager src/Website/Hub/View/Modal/Admin/PromptManager.php:211-292 Global prompt create/update/delete/duplicate/activate/restore.
ServiceManager src/Website/Hub/View/Modal/Admin/ServiceManager.php:110-150 Service metadata edits, enable/disable, module sync.
WaitlistManager src/Website/Hub/View/Modal/Admin/WaitlistManager.php:71-208 Invite sending, bulk invite, deletion, note writes, CSV export.
Entitlement\Dashboard src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:171-271, src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:358-419 Package/feature create, update, delete, and feature assignment.
Entitlement\FeatureManager src/Website/Hub/View/Modal/Admin/Entitlement/FeatureManager.php:100-148 Feature create/update/delete.
Entitlement\PackageManager src/Website/Hub/View/Modal/Admin/Entitlement/PackageManager.php:110-202 Package create/update/delete and feature sync.
Databases src/Website/Hub/View/Modal/Admin/Databases.php:133-207 Workspace WordPress connector enable/disable, secret regeneration, outbound test call.
ContentEditor src/Website/Hub/View/Modal/Admin/ContentEditor.php:297-328, src/Website/Hub/View/Modal/Admin/ContentEditor.php:379-409, src/Website/Hub/View/Modal/Admin/ContentEditor.php:437-562, src/Website/Hub/View/Modal/Admin/ContentEditor.php:666-779 Taxonomy creation, media upload, revision restore, save/publish/schedule, AI prompt execution, content replacement.
AccountUsage src/Website/Hub/View/Modal/Admin/AccountUsage.php:209-270 Shared AI service credential writes on a non-admin route.
Honeypot src/Website/Hub/View/Modal/Admin/Honeypot.php:50-60 Retention purge and IP flagging.

3. Livewire Injection and Tampering Map

Entry point Attacker-controlled input Sink Notes
src/Website/Hub/View/Blade/admin/global-search.blade.php:78 -> src/Website/Hub/View/Modal/Admin/GlobalSearch.php:140-148 -> src/Website/Hub/View/Blade/admin/global-search.blade.php:28 Arbitrary array $result from the Livewire call payload dispatch('navigate-to-url', url: $result['url']) followed by Livewire.navigate(...) Client-controlled result payload can drive arbitrary in-panel navigation if the action is invoked with a crafted URL.
src/Website/Hub/View/Blade/admin/workspace-switcher.blade.php:35 -> src/Website/Hub/View/Modal/Admin/WorkspaceSwitcher.php:52-69 string $slug WorkspaceService::setCurrent($slug), event dispatch, redirect to captured returnUrl Authorisation depends entirely on WorkspaceService::setCurrent().
src/Website/Hub/View/Modal/Admin/ContentEditor.php:135-146 Route workspace, id, and contentType parameters Workspace::where('slug', $workspace)->first(), loadContent((int) $id) Route parameter tampering reaches unscoped workspace/content loading immediately.
src/Website/Hub/View/Modal/Admin/ContentEditor.php:651-699 selectedPromptId, promptName, promptVariables Prompt::find(), Prompt::where('name', ...)->first(), AI execution Prompt selection and execution trust client-chosen prompt IDs/names inside a content editor.
src/Website/Hub/View/Modal/Admin/ContentManager.php:84-105 Route/event workspace slug Workspace::where('slug', $workspace)->first(), setCurrent($workspace) Workspace slug is accepted from both route and workspace-changed event.
src/Website/Hub/View/Modal/Admin/ContentManager.php:434-487 selectedItemId, logId ContentItem::find($selectedItemId), ContentWebhookLog::find($logId) Item preview and webhook retry trust raw IDs from the browser.
src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:263-285 websiteId, path Sets pageDetailsWebsiteId, pageDetailsPath, selectedWebsiteId Later analytics queries use these values directly rather than re-deriving them from the current workspace list.
src/Website/Hub/View/Modal/Admin/PlatformUser.php:442-493, src/Website/Hub/View/Modal/Admin/PlatformUser.php:580-670 selectedWorkspaceId, selectedPackageCode, entitlementWorkspaceId, entitlementFeatureCode, entitlementLimit, entitlementExpiresAt Workspace/package/feature lookups and entitlement mutation provisionPackage() accepts an arbitrary workspace ID without the ownership check used elsewhere in the component.
src/Website/Hub/View/Modal/Admin/WpConnectorSettings.php:28-124 Bound Workspace $workspace, then mutable public properties Direct workspace mutation methods No ownership or auth check inside the component if it is ever routed or embedded.

4. Unscoped Query Map

Concrete unscoped reads and writes in admin views/components:

Location Unscoped operation Why it matters
src/Website/Hub/View/Modal/Admin/ContentEditor.php:141-156 Workspace::where('slug', $workspace)->first() and ContentItem::with(...)->findOrFail($id) Route slug is not scoped to the current user, and editing by ID replaces the workspace context with the found row's workspace_id.
src/Website/Hub/View/Modal/Admin/ContentEditor.php:252 ContentMedia::find($this->featuredMediaId) Featured media lookup is not limited to the active workspace.
src/Website/Hub/View/Modal/Admin/ContentEditor.php:439-445 ContentRevision::findOrFail($revisionId) Revision is loaded globally first, then checked against content_item_id only after retrieval.
src/Website/Hub/View/Modal/Admin/ContentEditor.php:500-502 ContentItem::findOrFail($this->contentId) Save path updates by raw content ID without re-scoping to the current workspace or user.
src/Website/Hub/View/Modal/Admin/ContentEditor.php:570-580, src/Website/Hub/View/Modal/Admin/ContentEditor.php:655-690 Global Prompt queries inside a workspace editor Workspace editor can read and run globally scoped prompts.
src/Website/Hub/View/Modal/Admin/ContentManager.php:89-97, src/Website/Hub/View/Modal/Admin/ContentManager.php:100-105 Workspace::where('slug', $workspace)->first() Workspace selection from route/event input is not tied to the current user's memberships in this component.
src/Website/Hub/View/Modal/Admin/ContentManager.php:395-396 ContentItem::find($this->selectedItemId) Preview lookup bypasses the forWorkspace(...) scoping used elsewhere in the component.
src/Website/Hub/View/Modal/Admin/ContentManager.php:483-486 ContentWebhookLog::find($logId) Webhook retry can target any log row if the ID is tampered.
src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:337-449, src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:473-535 Analytics queries keyed directly by selectedWebsiteId The selected website ID is client-controlled and these queries do not re-check membership against $this->analyticsWebsites.
src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:535-717 AnalyticsWebsite::find($pageDetailsWebsiteId) and related event/session/visitor queries Page details trust a tamperable website ID and path pair.
src/Website/Hub/View/Modal/Admin/PlatformUser.php:472-478 Workspace::findOrFail($this->selectedWorkspaceId) followed by provisioning No verification that the selected workspace belongs to the user being administered before provisioning a package.
src/Website/Hub/View/Modal/Admin/PromptManager.php:80-87, src/Website/Hub/View/Modal/Admin/PromptManager.php:167-183, src/Website/Hub/View/Modal/Admin/PromptManager.php:195-289 Entire prompt dataset is global Combined with the missing local guard, this is a direct global-data surface.
src/Website/Hub/View/Modal/Admin/AccountUsage.php:177-200, src/Website/Hub/View/Modal/Admin/AccountUsage.php:209-270 Shared AI provider load/save on a non-admin account page Reads and writes appear global rather than per-user or per-workspace.
src/Website/Hub/View/Modal/Admin/ActivityLog.php:43-48, src/Website/Hub/View/Modal/Admin/ActivityLog.php:57-62 Distinct log_name and event values are read from all Activity rows Filter metadata leaks global activity categories even though activities() later narrows by workspace members.
src/Website/Hub/View/Modal/Admin/Databases.php:43-49 Workspace::where('slug', $slug)->first() Hades-only, but still a raw workspace lookup from session state rather than a scoped relationship.

5. Embedded Livewire Components Present on Most Admin Pages

These are not standalone routes in Routes/admin.php, but they are mounted broadly and therefore expand the reachable Livewire surface:

  • src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98 -> src/Website/Hub/View/Modal/Admin/GlobalSearch.php:27-256
  • src/Website/Hub/View/Blade/admin/components/header.blade.php:24 -> src/Website/Hub/View/Modal/Admin/WorkspaceSwitcher.php:11-75

That means most authenticated Hub pages also expose:

  • Search-driven navigation dispatch at GlobalSearch.php:140-148
  • Workspace switching at WorkspaceSwitcher.php:52-69
Map every external input entry point: function, file:line, input source, flows into, validation, attack vector. --- ## Implementation Plan (Spark) # Security Attack Vector Map Date: 2026-03-23 Scope: - Package-local review only. This maps the surfaces visible in this repository and does not assume protections from a parent application unless they are visible here. - `CODEX.md` was not present anywhere under `/workspace`, so this review used `AGENTS.md`, `CLAUDE.md`, and the code itself. - No fixes applied. ## 1. Route and Auth Boundary Map Primary registration surface: - `src/Website/Hub/Boot.php:93-98` registers the Hub routes with a domain, `/hub` prefix, and `hub.` route name prefix, but no package-local middleware. - `src/Website/Hub/Routes/admin.php:15-74` defines the GET entry points for the admin panel. Routeable components that rely on outer middleware only: | Route | Entry point | Local guard in component | Notes | | --- | --- | --- | --- | | `/hub/prompts` | `src/Website/Hub/Routes/admin.php:49` -> `src/Website/Hub/View/Modal/Admin/PromptManager.php:69-75` | None | Global prompt CRUD is exposed through `Prompt::query()` / `findOrFail()` / `create()` / `delete()` at `PromptManager.php:80-87`, `PromptManager.php:195-259`, `PromptManager.php:266-286`. | | `/hub/console` | `src/Website/Hub/Routes/admin.php:27` -> `src/Website/Hub/View/Modal/Admin/Console.php:13-46` | None | No auth or tier check before infrastructure/server inventory is loaded into the component state. | | `/hub/content-manager/{workspace}/{view?}` | `src/Website/Hub/Routes/admin.php:19-20` -> `src/Website/Hub/View/Modal/Admin/ContentManager.php:84-105` | None | Trusts route/event workspace input, then updates the current workspace session state. | | `/hub/content-editor/{workspace}/new/{contentType?}` and `/hub/content-editor/{workspace}/{id}` | `src/Website/Hub/Routes/admin.php:21-23` -> `src/Website/Hub/View/Modal/Admin/ContentEditor.php:135-188` | None | Route parameters feed directly into workspace and content loading, followed by global model lookups. | | `/hub/services/{service?}/{tab?}` | `src/Website/Hub/Routes/admin.php:68-71` -> `src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:74-95` | None | The service dashboard is reachable without a component-level auth check and later trusts tamperable website IDs and paths. | | `/hub/account/usage` | `src/Website/Hub/Routes/admin.php:32` -> `src/Website/Hub/View/Modal/Admin/AccountUsage.php:78-80` | None | Non-admin account route exposes shared AI service configuration writers at `AccountUsage.php:209-270`. | | `/hub/workspaces` | `src/Website/Hub/Routes/admin.php:25` -> `src/Website/Hub/View/Modal/Admin/Sites.php:42-46` | None | Workspace selection is delegated to `WorkspaceService`; `addService()` also creates global `Feature` and `Package` rows at `Sites.php:212-269`. | Routeable components that do self-gate: - `src/Website/Hub/View/Modal/Admin/Platform.php:37-42` - `src/Website/Hub/View/Modal/Admin/PlatformUser.php:65-72` - `src/Website/Hub/View/Modal/Admin/ServiceManager.php:57-61` - `src/Website/Hub/View/Modal/Admin/WaitlistManager.php:45-49` - `src/Website/Hub/View/Modal/Admin/Honeypot.php:28-32` - `src/Website/Hub/View/Modal/Admin/Databases.php:38-42` - `src/Website/Hub/View/Modal/Admin/Deployments.php:21-24`, `src/Website/Hub/View/Modal/Admin/Deployments.php:262-266` - `src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:83-87` - `src/Website/Hub/View/Modal/Admin/Entitlement/FeatureManager.php:25-29` - `src/Website/Hub/View/Modal/Admin/Entitlement/PackageManager.php:26-30` Discovery amplifiers: - The admin layout mounts global search on every admin page at `src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98`. - The search provider advertises sensitive destinations such as prompts, console, deployments, and databases at `src/Search/Providers/AdminPageSearchProvider.php:75-129`. ## 2. CSRF-Relevant Admin Mutation Surface Livewire entry points are mounted from the admin layout and header: - `src/Website/Hub/View/Blade/admin/layouts/app.blade.php:10` exposes the CSRF token in the page. - `src/Website/Hub/View/Blade/admin/components/header.blade.php:24` mounts the workspace switcher. - `src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98` mounts global search. These are the state-changing methods worth testing for CSRF and replay because they are exposed as public Livewire actions. This map does not assert that Livewire's default token checks are absent; it identifies the methods with the highest impact if those checks are bypassed or weakened. High-value public mutation methods exposed as Livewire actions: | Component | Public action entry points | Impact | | --- | --- | --- | | `Platform` | `src/Website/Hub/View/Modal/Admin/Platform.php:60-98` | Email verification plus cache, OPcache, and queue control. | | `PlatformUser` | `src/Website/Hub/View/Modal/Admin/PlatformUser.php:84-149`, `src/Website/Hub/View/Modal/Admin/PlatformUser.php:250-399`, `src/Website/Hub/View/Modal/Admin/PlatformUser.php:462-530`, `src/Website/Hub/View/Modal/Admin/PlatformUser.php:604-707` | Tier changes, verification, GDPR export/delete/anonymise, package provisioning, entitlement provisioning, boost removal. | | `PromptManager` | `src/Website/Hub/View/Modal/Admin/PromptManager.php:211-292` | Global prompt create/update/delete/duplicate/activate/restore. | | `ServiceManager` | `src/Website/Hub/View/Modal/Admin/ServiceManager.php:110-150` | Service metadata edits, enable/disable, module sync. | | `WaitlistManager` | `src/Website/Hub/View/Modal/Admin/WaitlistManager.php:71-208` | Invite sending, bulk invite, deletion, note writes, CSV export. | | `Entitlement\Dashboard` | `src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:171-271`, `src/Website/Hub/View/Modal/Admin/Entitlement/Dashboard.php:358-419` | Package/feature create, update, delete, and feature assignment. | | `Entitlement\FeatureManager` | `src/Website/Hub/View/Modal/Admin/Entitlement/FeatureManager.php:100-148` | Feature create/update/delete. | | `Entitlement\PackageManager` | `src/Website/Hub/View/Modal/Admin/Entitlement/PackageManager.php:110-202` | Package create/update/delete and feature sync. | | `Databases` | `src/Website/Hub/View/Modal/Admin/Databases.php:133-207` | Workspace WordPress connector enable/disable, secret regeneration, outbound test call. | | `ContentEditor` | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:297-328`, `src/Website/Hub/View/Modal/Admin/ContentEditor.php:379-409`, `src/Website/Hub/View/Modal/Admin/ContentEditor.php:437-562`, `src/Website/Hub/View/Modal/Admin/ContentEditor.php:666-779` | Taxonomy creation, media upload, revision restore, save/publish/schedule, AI prompt execution, content replacement. | | `AccountUsage` | `src/Website/Hub/View/Modal/Admin/AccountUsage.php:209-270` | Shared AI service credential writes on a non-admin route. | | `Honeypot` | `src/Website/Hub/View/Modal/Admin/Honeypot.php:50-60` | Retention purge and IP flagging. | ## 3. Livewire Injection and Tampering Map | Entry point | Attacker-controlled input | Sink | Notes | | --- | --- | --- | --- | | `src/Website/Hub/View/Blade/admin/global-search.blade.php:78` -> `src/Website/Hub/View/Modal/Admin/GlobalSearch.php:140-148` -> `src/Website/Hub/View/Blade/admin/global-search.blade.php:28` | Arbitrary `array $result` from the Livewire call payload | `dispatch('navigate-to-url', url: $result['url'])` followed by `Livewire.navigate(...)` | Client-controlled result payload can drive arbitrary in-panel navigation if the action is invoked with a crafted URL. | | `src/Website/Hub/View/Blade/admin/workspace-switcher.blade.php:35` -> `src/Website/Hub/View/Modal/Admin/WorkspaceSwitcher.php:52-69` | `string $slug` | `WorkspaceService::setCurrent($slug)`, event dispatch, redirect to captured `returnUrl` | Authorisation depends entirely on `WorkspaceService::setCurrent()`. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:135-146` | Route `workspace`, `id`, and `contentType` parameters | `Workspace::where('slug', $workspace)->first()`, `loadContent((int) $id)` | Route parameter tampering reaches unscoped workspace/content loading immediately. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:651-699` | `selectedPromptId`, `promptName`, `promptVariables` | `Prompt::find()`, `Prompt::where('name', ...)->first()`, AI execution | Prompt selection and execution trust client-chosen prompt IDs/names inside a content editor. | | `src/Website/Hub/View/Modal/Admin/ContentManager.php:84-105` | Route/event `workspace` slug | `Workspace::where('slug', $workspace)->first()`, `setCurrent($workspace)` | Workspace slug is accepted from both route and `workspace-changed` event. | | `src/Website/Hub/View/Modal/Admin/ContentManager.php:434-487` | `selectedItemId`, `logId` | `ContentItem::find($selectedItemId)`, `ContentWebhookLog::find($logId)` | Item preview and webhook retry trust raw IDs from the browser. | | `src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:263-285` | `websiteId`, `path` | Sets `pageDetailsWebsiteId`, `pageDetailsPath`, `selectedWebsiteId` | Later analytics queries use these values directly rather than re-deriving them from the current workspace list. | | `src/Website/Hub/View/Modal/Admin/PlatformUser.php:442-493`, `src/Website/Hub/View/Modal/Admin/PlatformUser.php:580-670` | `selectedWorkspaceId`, `selectedPackageCode`, `entitlementWorkspaceId`, `entitlementFeatureCode`, `entitlementLimit`, `entitlementExpiresAt` | Workspace/package/feature lookups and entitlement mutation | `provisionPackage()` accepts an arbitrary workspace ID without the ownership check used elsewhere in the component. | | `src/Website/Hub/View/Modal/Admin/WpConnectorSettings.php:28-124` | Bound `Workspace $workspace`, then mutable public properties | Direct workspace mutation methods | No ownership or auth check inside the component if it is ever routed or embedded. | ## 4. Unscoped Query Map Concrete unscoped reads and writes in admin views/components: | Location | Unscoped operation | Why it matters | | --- | --- | --- | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:141-156` | `Workspace::where('slug', $workspace)->first()` and `ContentItem::with(...)->findOrFail($id)` | Route slug is not scoped to the current user, and editing by ID replaces the workspace context with the found row's `workspace_id`. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:252` | `ContentMedia::find($this->featuredMediaId)` | Featured media lookup is not limited to the active workspace. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:439-445` | `ContentRevision::findOrFail($revisionId)` | Revision is loaded globally first, then checked against `content_item_id` only after retrieval. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:500-502` | `ContentItem::findOrFail($this->contentId)` | Save path updates by raw content ID without re-scoping to the current workspace or user. | | `src/Website/Hub/View/Modal/Admin/ContentEditor.php:570-580`, `src/Website/Hub/View/Modal/Admin/ContentEditor.php:655-690` | Global `Prompt` queries inside a workspace editor | Workspace editor can read and run globally scoped prompts. | | `src/Website/Hub/View/Modal/Admin/ContentManager.php:89-97`, `src/Website/Hub/View/Modal/Admin/ContentManager.php:100-105` | `Workspace::where('slug', $workspace)->first()` | Workspace selection from route/event input is not tied to the current user's memberships in this component. | | `src/Website/Hub/View/Modal/Admin/ContentManager.php:395-396` | `ContentItem::find($this->selectedItemId)` | Preview lookup bypasses the `forWorkspace(...)` scoping used elsewhere in the component. | | `src/Website/Hub/View/Modal/Admin/ContentManager.php:483-486` | `ContentWebhookLog::find($logId)` | Webhook retry can target any log row if the ID is tampered. | | `src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:337-449`, `src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:473-535` | Analytics queries keyed directly by `selectedWebsiteId` | The selected website ID is client-controlled and these queries do not re-check membership against `$this->analyticsWebsites`. | | `src/Website/Hub/View/Modal/Admin/ServicesAdmin.php:535-717` | `AnalyticsWebsite::find($pageDetailsWebsiteId)` and related event/session/visitor queries | Page details trust a tamperable website ID and path pair. | | `src/Website/Hub/View/Modal/Admin/PlatformUser.php:472-478` | `Workspace::findOrFail($this->selectedWorkspaceId)` followed by provisioning | No verification that the selected workspace belongs to the user being administered before provisioning a package. | | `src/Website/Hub/View/Modal/Admin/PromptManager.php:80-87`, `src/Website/Hub/View/Modal/Admin/PromptManager.php:167-183`, `src/Website/Hub/View/Modal/Admin/PromptManager.php:195-289` | Entire prompt dataset is global | Combined with the missing local guard, this is a direct global-data surface. | | `src/Website/Hub/View/Modal/Admin/AccountUsage.php:177-200`, `src/Website/Hub/View/Modal/Admin/AccountUsage.php:209-270` | Shared AI provider load/save on a non-admin account page | Reads and writes appear global rather than per-user or per-workspace. | | `src/Website/Hub/View/Modal/Admin/ActivityLog.php:43-48`, `src/Website/Hub/View/Modal/Admin/ActivityLog.php:57-62` | Distinct `log_name` and `event` values are read from all `Activity` rows | Filter metadata leaks global activity categories even though `activities()` later narrows by workspace members. | | `src/Website/Hub/View/Modal/Admin/Databases.php:43-49` | `Workspace::where('slug', $slug)->first()` | Hades-only, but still a raw workspace lookup from session state rather than a scoped relationship. | ## 5. Embedded Livewire Components Present on Most Admin Pages These are not standalone routes in `Routes/admin.php`, but they are mounted broadly and therefore expand the reachable Livewire surface: - `src/Website/Hub/View/Blade/admin/layouts/app.blade.php:95-98` -> `src/Website/Hub/View/Modal/Admin/GlobalSearch.php:27-256` - `src/Website/Hub/View/Blade/admin/components/header.blade.php:24` -> `src/Website/Hub/View/Modal/Admin/WorkspaceSwitcher.php:11-75` That means most authenticated Hub pages also expose: - Search-driven navigation dispatch at `GlobalSearch.php:140-148` - Workspace switching at `WorkspaceSwitcher.php:52-69`
Author
Member

Security Scan: Attack Vector Map completed. Details in agent log.

## Security Scan: Attack Vector Map completed. Details in agent log.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

-

Dependencies

No dependencies set.

Reference: core/php-admin#26
No description provided.