Findings Register
Categories:
Every finding in the assessment, grouped by the repository it lands in, so a team owning one repository can see its whole queue on one screen.
Read this alongside Critical and High findings, which gives the fix for each of the 28 top-severity rows. This page is the index; that page is the work.
The count is provisional
The assessment’s own handling notes record that the total is under revision. Several findings are candidates for merge or reclassification, and the set may land nearer 173 than 184. Use these reference numbers for tracking and do not quote the total outside the team.How to read a row
- Confidence: Verified means the finding was re-derived against the source during review. Inferred means it was read from code and configuration without a runtime probe. Inferred is not weaker evidence about the code; it means nobody demonstrated the outcome on a running system. 172 of 184 are Inferred.
- Status is the assessment’s status at the time of writing. Every row is Open.
- Severity is the assessment’s rating. Where an open question bounds a rating, the finding page says so.
Totals
| Severity | Count |
|---|---|
| Critical | 2 |
| High | 26 |
| Medium | 69 |
| Low | 78 |
| Informational | 9 |
| Total | 184 |
Findings per component
| Component | Findings | C | H | M | L | I |
|---|---|---|---|---|---|---|
| phenom-backend | 44 | 0 | 6 | 20 | 16 | 2 |
| phenom-infra | 32 | 1 | 6 | 16 | 8 | 1 |
| ghostmode-thephenom-app | 22 | 0 | 2 | 5 | 12 | 3 |
| phenom-drop | 22 | 1 | 5 | 6 | 8 | 2 |
| sablier-weblogon | 14 | 0 | 2 | 6 | 6 | 0 |
| PhenomApp | 9 | 0 | 1 | 3 | 5 | 0 |
| www | 9 | 0 | 0 | 1 | 8 | 0 |
| codetalker-dev | 7 | 0 | 1 | 2 | 4 | 0 |
| analytics-thephenom-app | 4 | 0 | 0 | 1 | 2 | 1 |
| phenom-earth-docs | 4 | 0 | 0 | 2 | 2 | 0 |
| phenom-push-sender | 4 | 0 | 1 | 1 | 2 | 0 |
| adsb-archive | 3 | 0 | 0 | 2 | 1 | 0 |
| Buzzard-Android | 3 | 0 | 1 | 1 | 1 | 0 |
| dev-environment | 2 | 0 | 0 | 2 | 0 | 0 |
| dev-environment-installer | 2 | 0 | 1 | 0 | 1 | 0 |
| mlx-whisper-stt | 2 | 0 | 0 | 1 | 1 | 0 |
| analytics-thephenom-app+ ghostmode-thephenom-app | 1 | 0 | 0 | 0 | 1 | 0 |
| Total | 184 | 2 | 26 | 69 | 78 | 9 |
Full register
phenom-backend
44 findings: 6 High, 20 Medium, 16 Low, 2 Informational.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H06 | High | Inferred | A Firebase Admin SDK private key for the live project is in repository history reachable from HEAD’s own ancestry |
| MGR-H07 | High | Verified | Every authenticated account reads all rows and columns of the submission table, including email, name and coordinates |
| MGR-H08 | High | Inferred | The provisioning runbook instructs the operator to store a full-scope GitHub token in cleartext on a host it also makes root-equivalent |
| MGR-H09 | High | Inferred | The documentation proxy builds its upstream URL by concatenation, sending a Cloudflare Access service token to an attacker-chosen host |
| MGR-H10 | High | Inferred | A sighting’s author can set its moderation status to any value, republishing a scanner-held or moderator-rejected sighting |
| MGR-H11 | High | Verified | Twelve tables grant role user an unfiltered read, exposing every account’s email and the coordinates and media of unpublished sightings |
| MGR-M15 | Medium | Inferred | The chat canary Worker is an off-zone, unrate-limited path to the production chat origin |
| MGR-M16 | Medium | Inferred | The chat edge Worker accepts any ID token from the shared production pool: no audience, no token-use, no group check |
| MGR-M17 | Medium | Inferred | The chat message read permission for role user filters only on the deleted flag, not on room membership |
| MGR-M18 | Medium | Inferred | No depth, complexity, node or effective rate limit stands in front of the GraphQL endpoint, and every role can introspect the schema |
| MGR-M19 | Medium | Inferred | Database deploy workflows pipe an installer from a moving upstream ref into a shell |
| MGR-M20 | Medium | Inferred | The metadata declares 13 permission blocks the repository itself says the engine rejects, on a pipeline configured not to fail on either |
| MGR-M21 | Medium | Inferred | Any account can insert share rows naming any other account, with no team constraint, no rate limit and no delete permission |
| MGR-M22 | Medium | Inferred | A list-share recipient can raise their own share row from read to write, gaining insert and delete on another user’s list |
| MGR-M23 | Medium | Inferred | The API Worker is deployed to production without ever being typechecked or tested; its 23 test files have never run in CI |
| MGR-M24 | Medium | Inferred | The API resolves a session’s application identity by email attribute as superuser and never binds the matched row to the token subject |
| MGR-M25 | Medium | Inferred | The API’s own documented invariant that the superuser secret is unreachable from a user request path is violated at 39 of 42 call sites |
| MGR-M26 | Medium | Inferred | The API proxies internal documentation with its own Cloudflare Access token before the authentication gate, needing no caller credential |
| MGR-M27 | Medium | Inferred | The media proxy performs no object-level authorization and honours a caller-chosen bucket parameter spanning production and staging |
| MGR-M28 | Medium | Inferred | The production database superuser secret is bound to the Worker script also published off-zone, and one route runs unswitched |
| MGR-M29 | Medium | Inferred | The production media-serving moderation gate is configured fail-open, contradicting the in-code comment asserting production stays enforced |
| MGR-M30 | Medium | Inferred | The console’s forgot-password form renders the raw provider exception, reinstating the account-enumeration oracle its sign-in screen suppresses |
| MGR-M31 | Medium | Inferred | The service worker writes every authenticated API response into origin-scoped cache storage, and no sign-out path evicts it |
| MGR-M32 | Medium | Inferred | Any authenticated user can attach coordinates, sensor data and category tags to another user’s sighting |
| MGR-M33 | Medium | Inferred | Both single-page applications persist ID, access and refresh tokens in browser local storage |
| MGR-M34 | Medium | Inferred | Production deploy paths install dependencies without a lockfile, so the shipped dependency set cannot be reproduced |
| MGR-L24 | Low | Inferred | Accountability columns are client-writable without a server-side set clause on five permission blocks |
| MGR-L25 | Low | Inferred | The anonymous permission set is unreachable in production because the unauthorized role is named differently, leaving three grants dormant |
| MGR-L26 | Low | Inferred | The submission insert permission exposes twelve provenance columns to client assignment, held inoperative only by an unrelated bug |
| MGR-L27 | Low | Inferred | Two 32-byte secrets sit on a remote-tracking branch an ordinary clone fetches, committed by a change that removed the ignore rule |
| MGR-L28 | Low | Inferred | The API returns a per-origin allow-origin header with credentials and never sets the vary header, while four routes are publicly cacheable |
| MGR-L29 | Low | Inferred | Route handlers relay raw exception text, including whole upstream response bodies, in client-visible 500s, bypassing a correct boundary |
| MGR-L30 | Low | Inferred | Three modules attach the superuser secret with an inline fetch rather than the helper, so the earlier site count is a floor |
| MGR-L31 | Low | Inferred | Four shared-secret comparisons use ordinary string equality where the same codebases already carry a constant-time helper |
| MGR-L32 | Low | Inferred | The presigned storage PUT signs only the host header with an unsigned payload, so neither content type nor size is bound into the signature |
| MGR-L33 | Low | Inferred | The profile mask returns a user’s real name under the username key, defeating the privacy mask that is on by default |
| MGR-L34 | Low | Inferred | The offline database holding every authenticated response and unexpired presigned URLs survives both logout paths untouched |
| MGR-L35 | Low | Inferred | A database function and its metadata exist only on a divergent branch while the production pipeline applies metadata from another |
| MGR-L36 | Low | Inferred | The sensor payload column is free-form JSON with no check, size or row bound, writable by role user and echoed to every operator console |
| MGR-L37 | Low | Inferred | The operator app ships its content policy in report-only mode with no reporting endpoint, so it is neither enforced nor observed |
| MGR-L38 | Low | Inferred | Any authenticated user can write arbitrary entries into the shared transcription cache, for any video, with an empty check |
| MGR-L39 | Low | Inferred | The API accepts any string as a web-push endpoint and the scheduled fan-out posts to it |
| MGR-I05 | Informational | Inferred | The API’s audience allowlist does not provide the mobile-versus-operator separation its own comment states it provides |
| MGR-I06 | Informational | Inferred | The media-bucket allowlist retains two bucket names whose existence two source comments contradict each other about |
phenom-infra
32 findings: 1 Critical, 6 High, 16 Medium, 8 Low, 1 Informational.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-C02 | Critical | Verified | An MCP tool server with nine chat-moderation tools has no inbound authentication and queries the database as superuser |
| MGR-H17 | High | Verified | The CI deploy role reads every secret in the account and replaces the code of every function, contradicting its own scoping comment |
| MGR-H18 | High | Inferred | The development load balancer forwards every unmatched hostname to the database engine, and one public DNS name lands there |
| MGR-H19 | High | Inferred | The production action handler sends the database superuser secret and every caller’s ID token over cleartext HTTP |
| MGR-H20 | High | Verified | The pre-token Lambda mints the database engine’s reserved superuser role for the dashboard-access group |
| MGR-H21 | High | Verified | The CI trust policy accepts any ref in the repository while the role holds write on production infrastructure state |
| MGR-H22 | High | Inferred | Dispatch inputs are interpolated into a shell block in the production infrastructure apply job, after it assumes the production role |
| MGR-M43 | Medium | Inferred | The action handler is an unauthenticated public function URL outside the load-balancer lock, the firewall and the edge zone |
| MGR-M44 | Medium | Inferred | Latent: a per-room chat role of admin mints the global database superuser role, held inert only by two unset environment variables |
| MGR-M45 | Medium | Inferred | The infrastructure security gate does not scan the 29 production files it ships, and the gate action itself runs unpinned |
| MGR-M46 | Medium | Inferred | Four production identity clients leave existence-error suppression unset, including the client the web console and mobile app use |
| MGR-M47 | Medium | Verified | The sole production identity pool has self-service sign-up on, multi-factor off, and password authentication on public clients |
| MGR-M48 | Medium | Inferred | A development-tier cloud principal is granted read and list on the production media bucket |
| MGR-M49 | Medium | Inferred | The static key that presigns storage URLs on the public submission path belongs to a principal declared in no infrastructure code |
| MGR-M50 | Medium | Inferred | A storage bucket grants anonymous object reads with the policy-side public-access guardrails deliberately disabled |
| MGR-M51 | Medium | Verified | The production database JWT configuration pins neither audience nor issuer, so a token from any of eight clients is a full session |
| MGR-M52 | Medium | Inferred | Deployed artifacts are drawn from republishing and cross-organisation registries on mutable tags |
| MGR-M53 | Medium | Inferred | Four of six production-facing deploy paths carry no environment declaration while two do |
| MGR-M54 | Medium | Verified | The password-reset artifact is byte-identical across environments and points all three pools at the public production web origin |
| MGR-M55 | Medium | Inferred | The staging load balancer has no origin lock while its database is a production clone |
| MGR-M56 | Medium | Inferred | The staging identity pool was repopulated with real user identities under one shared password, with self-service sign-up on |
| MGR-M57 | Medium | Inferred | The production Matrix administration console runs a third-party image on a mutable latest tag |
| MGR-M58 | Medium | Inferred | Every firewall rule on the production load balancer defaults to observe mode, and the admin-path rule omits the database dump endpoint |
| MGR-L50 | Low | Inferred | All three load-balancer HTTPS listeners use a 2017-vintage predefined TLS policy |
| MGR-L51 | Low | Inferred | The authentication subdomain is delegated to a DNS zone that exists in no audited infrastructure code, and no CAA record constrains issuance |
| MGR-L52 | Low | Inferred | The edge cache-bypass rule names a service-worker path that does not exist and omits both real ones |
| MGR-L53 | Low | Inferred | Edge-to-origin TLS is set to full rather than strict on the four hostnames carrying authenticated origin pulls |
| MGR-L54 | Low | Inferred | Production identity clients register a plaintext localhost redirect URI, and one still permits the implicit grant |
| MGR-L55 | Low | Inferred | A registry credential is interpolated into a shell script body instead of passed through the environment |
| MGR-L56 | Low | Inferred | The reset link’s code parameter is percent-encoded by the URL builder, so the prefill has never worked and the CI guard cannot see it |
| MGR-L57 | Low | Inferred | The firewall rule that lets CI bypass the admin-path block is ordered after the block it must precede |
| MGR-I09 | Informational | Inferred | Production database CORS is set to a wildcard origin |
ghostmode-thephenom-app
22 findings: 2 High, 5 Medium, 12 Low, 3 Informational.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H04 | High | Inferred | An ALB OIDC identity is accepted with no issuer or audience binding, and the source-of-channel check is opt-in and set nowhere |
| MGR-H05 | High | Inferred | Attacker-chosen request paths reach a JavaScript string inside an inline onclick attribute through an HTML text-node encoder |
| MGR-M09 | Medium | Inferred | The anonymous health endpoint performs a blocking credentialed outbound request and a whole-file line count on the event loop |
| MGR-M10 | Medium | Inferred | The event store defaults its database identity to the Matrix homeserver’s own database and owning role, overridden nowhere |
| MGR-M11 | Medium | Inferred | The 256 KB ingest body cap is evaluated after the whole request body has been read into memory |
| MGR-M12 | Medium | Inferred | One ingested event with a non-numeric port field raises an uncaught exception in the log parser, and the poisoned line persists |
| MGR-M13 | Medium | Inferred | The detection pipeline evaluates at most 50 firewall events per zone per scan, newest first, so activity can be displaced out of the set |
| MGR-L11 | Low | Inferred | The log endpoint accepts an unbounded limit, over a file that is remotely appendable through the ingest endpoint |
| MGR-L12 | Low | Inferred | The console’s session endpoint applies no origin, referer, token or content-type check, so a cross-site page can install its own session |
| MGR-L13 | Low | Inferred | The configuration validator checks two non-security variables and reports success on a configuration whose authentication can be switched off |
| MGR-L14 | Low | Inferred | A single environment variable disables all authentication and all permission checks on the operator console |
| MGR-L15 | Low | Inferred | The documentation module hardcodes an internal vector-database endpoint as a default no caller overrides, and handles no exception anywhere |
| MGR-L16 | Low | Inferred | Two endpoints drive unvalidated, serial, blocking, credentialed geolocation lookups on the event loop, seeded by an unauthenticated attacker |
| MGR-L17 | Low | Inferred | The console container image is built from a mutable base tag with no dependency hashes and no unprivileged user |
| MGR-L18 | Low | Inferred | The operator login page loads its authentication library from a public CDN with no integrity attribute, allowlisted in its own policy |
| MGR-L19 | Low | Inferred | The console has no logout control, its logout route is defeated by a page reload, and its cookie holds the raw production ID token |
| MGR-L20 | Low | Inferred | The RSS proxy validates by name and connects by name, so the two resolutions can differ |
| MGR-L21 | Low | Inferred | The console session cookie stores the raw production ID token as its value and carries no host prefix |
| MGR-L22 | Low | Inferred | The operations ticker escapes feed values with an encoder that does not escape the double quote, then places the result in an href |
| MGR-I02 | Informational | Inferred | The estate’s only server-side HTML encoder is called by no module, and two server-side HTML sinks interpolate with no encoder |
| MGR-I03 | Informational | Inferred | Security headers are applied to five HTML responses and to nothing else; every JSON, metrics and asset response omits them |
| MGR-I04 | Informational | Inferred | Metric label values are built from a remotely-writable event field with no bound, minting a permanent time series per distinct value |
phenom-drop
22 findings: 1 Critical, 5 High, 6 Medium, 8 Low, 2 Informational.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-C01 | Critical | Inferred | Three unauthenticated endpoints write or relay a caller-asserted provenance verdict, and no server-side gate exists |
| MGR-H12 | High | Inferred | The confirm-upload endpoint is unauthenticated, presigns an arbitrary caller-supplied storage key, and appends to a production index object |
| MGR-H13 | High | Verified | The literal string REJECTED is a valid one-time passcode for any email address, bypassing the submission flow’s only authentication |
| MGR-H14 | High | Inferred | The public drop API is a single-threaded server, so one unauthenticated request holds every endpoint for its longest outbound call |
| MGR-H15 | High | Inferred | The production image is pushed with static long-lived cloud keys to a mutable tag that the runtime auto-deploys with no gate |
| MGR-H16 | High | Inferred | Production public-submission media is served from and written to a storage bucket the infrastructure code does not declare |
| MGR-M35 | Medium | Inferred | Server-level security headers are nullified for every HTML response by a location-level directive, and the declared policy is unusable anyway |
| MGR-M36 | Medium | Inferred | The production drop container runs as root and its health check cannot detect the failure mode its process model creates |
| MGR-M37 | Medium | Inferred | The backend treats the client-supplied forwarding IP header as the authoritative client address, and the proxy forwards it verbatim |
| MGR-M38 | Medium | Inferred | Upload acceptance is by file extension alone, the allowlist includes SVG, and the media proxy relays it same-origin with no sniffing guard |
| MGR-M39 | Medium | Inferred | Unauthenticated request data is interpolated unescaped into outbound HTML email sent to an attacker-chosen recipient |
| MGR-M40 | Medium | Inferred | The passcode check that authorises the upload binds no file, enforces no attempt limit and doubles the expiry window |
| MGR-L40 | Low | Inferred | The certificate export builds HTML by string interpolation and writes it into a same-origin document |
| MGR-L41 | Low | Inferred | The submitter’s IP is sent to a third-party geolocation service over cleartext HTTP, and the returned coordinates are stored unvalidated |
| MGR-L42 | Low | Inferred | Unauthenticated request values are interpolated into multipart header lines of an outbound request carrying the registry API key |
| MGR-L43 | Low | Inferred | One-time passcodes are stored in cleartext for 24 hours and compared with a SQL equality predicate |
| MGR-L44 | Low | Inferred | The trust-anchor list is served from the web root and loaded by no code path, so the application pins no first-party trust anchor |
| MGR-L45 | Low | Inferred | The registry client replays its authorization header across a cross-host redirect |
| MGR-L46 | Low | Inferred | The server-verify endpoint returns the raw exception message to an unauthenticated caller |
| MGR-L47 | Low | Inferred | The server-verify endpoint accepts an arbitrary body-supplied URL from an anonymous caller and relays it under the client’s own secret |
| MGR-I07 | Informational | Inferred | The generated certificate page renders a data-derived link opening a new context with no relationship attribute |
| MGR-I08 | Informational | Inferred | The provenance diagram sets the renderer’s security level to loose and assigns the result as raw HTML |
sablier-weblogon
14 findings: 2 High, 6 Medium, 6 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H25 | High | Inferred | Auto-provisioned developer boxes publish an IDE on host ports 8450-8599 with no password variable set |
| MGR-H26 | High | Inferred | Auto-provisioned developer boxes share a network with services that accept identity headers without verifying them |
| MGR-M63 | Medium | Inferred | The container socket is mounted into four containers, and the read-only flag on two of them does not restrict the API |
| MGR-M64 | Medium | Inferred | The voice-enrolment upload accepts any blob with no type, size or content check and hands it to an unpinned, untimed media converter |
| MGR-M65 | Medium | Inferred | The voice-enrolment upload writes a reference voice file under a caller-supplied identifier with no ownership check |
| MGR-M66 | Medium | Inferred | No configuration strips client-supplied identity headers on ingress; the boundary rests on unasserted, version-specific proxy behaviour |
| MGR-M67 | Medium | Inferred | No developer-platform session can be revoked before expiry: logout clears a client cookie and the 12-hour token carries no server state |
| MGR-M68 | Medium | Inferred | The IDE WebSocket is authorized once at upgrade and never re-evaluated, and no mechanism exists to close an established one |
| MGR-L65 | Low | Inferred | The auth router runs no middleware and the verifier treats every unmatched path as forward-auth, returning the live ID token in headers |
| MGR-L66 | Low | Inferred | The developer-platform session endpoint accepts a cross-site request with no CSRF defence |
| MGR-L67 | Low | Inferred | The box router forwards the caller’s session cookie and live ID token verbatim into the developer’s IDE on every proxied request |
| MGR-L68 | Low | Inferred | Workspace identity is derived from the email local part alone, so two distinct principals collapse onto one container and one voice identity |
| MGR-L69 | Low | Inferred | The voice-enrolment endpoint returns the raw exception string, disclosing converter stderr, container paths and internal response bytes |
| MGR-L70 | Low | Inferred | The developer-platform session cookie carries no host prefix on a registrable domain with sibling hosts |
PhenomApp
9 findings: 1 High, 3 Medium, 5 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H24 | High | Verified | Two EC P-256 private keys, one bundled with a live Cloudflare Access token and its CSR, are committed in mobile-client history |
| MGR-M60 | Medium | Inferred | Debug builds of the mobile client use production endpoints and the production identity pool, so no environment separation exists |
| MGR-M61 | Medium | Inferred | The mobile OAuth callback is a bare private-use URI scheme on a client shared with a web app and a plaintext localhost origin |
| MGR-M62 | Medium | Inferred | The mobile ID token and personal data rest in an unencrypted key-value store, and navigation state is persisted there in every build |
| MGR-L60 | Low | Inferred | Build-time plumbing that would embed a static private key and an access token pair into the client bundle survives with no runtime consumer |
| MGR-L61 | Low | Inferred | The mobile client requests every reporter’s email on five selection sets and renders its local part as that user’s public display name |
| MGR-L62 | Low | Inferred | Logout does not clear the API adapter’s cached ID token, because initialisation skips the assignment on an empty string |
| MGR-L63 | Low | Inferred | Matrix sessions are minted on every chat entry and never invalidated at the homeserver, and the clearing helper is dead code |
| MGR-L64 | Low | Inferred | Mobile crash reporting configures no scrubbing hooks while enabling native capture, and three call sites ship whole upstream response bodies |
www
9 findings: 1 Medium, 8 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M69 | Medium | Verified | The production password-reset page runs a second organisation’s script with no integrity attribute and no content policy |
| MGR-L71 | Low | Inferred | The public gateway returns the specific token-verification failure reason to the caller, and the signature is checked last |
| MGR-L72 | Low | Inferred | Production CI deliberately routes traffic off-zone to escape the edge security controls, which also removes the firewall and rate limits |
| MGR-L73 | Low | Inferred | The reset page takes the identity client it authenticates against from an unvalidated URL parameter, and the CI guard forbids an allowlist |
| MGR-L74 | Low | Inferred | The robots file is the only reference to four archived pages that publish the development Firebase project configuration |
| MGR-L75 | Low | Inferred | The translator document upload applies no file-type allowlist and signs the client-declared content type onto the stored object |
| MGR-L76 | Low | Inferred | The translator portal has no logout route or control, a 30-day absolute session with no idle timeout, and no concurrency bound |
| MGR-L77 | Low | Inferred | The translator portal applies no origin control on any route, and the magic-link login establishes a session on a GET |
| MGR-L78 | Low | Inferred | Pages Functions relay third-party error bodies and configuration state verbatim, five of the seven sites unauthenticated |
codetalker-dev
7 findings: 1 High, 2 Medium, 4 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H02 | High | Inferred | Every editor-extension setting is workspace-settable, so a cloned repository redirects the Matrix session and login token to an attacker host |
| MGR-M05 | Medium | Inferred | Any process running as the developer can post to the shared team chat room as that developer by writing a line to a polled file |
| MGR-M06 | Medium | Inferred | The extension takes its Matrix login credential from the workspace root and validates only that it has three dot-separated segments |
| MGR-L06 | Low | Inferred | The webview content-policy nonce, the sole control on script execution, is generated with a non-cryptographic random function |
| MGR-L07 | Low | Inferred | The extension sends the value of a workspace-nameable environment variable to a third-party model provider |
| MGR-L08 | Low | Inferred | A chat bubble’s typewriter animation runs one render per character over an unbounded remote-supplied string |
| MGR-L09 | Low | Inferred | An unauthenticated message handler lets any framed page write an attacker-chosen URL into the app’s own frame, inert in the shipping build |
analytics-thephenom-app
4 findings: 1 Medium, 2 Low, 1 Informational.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M03 | Medium | Inferred | The analytics Worker sets no security response header and deletes the upstream framing and content-policy headers |
| MGR-L02 | Low | Inferred | A dashboard access token is hardcoded in source and replicated into 16 build artifacts |
| MGR-L03 | Low | Inferred | The analytics session cookie meets every host-prefix precondition and does not use it, and the parser takes the first name match |
| MGR-I01 | Informational | Inferred | The analytics Worker’s session endpoint applies no origin, referer, token or content-type check |
phenom-earth-docs
4 findings: 2 Medium, 2 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M41 | Medium | Inferred | Authorization is granted on the mere presence of a Cloudflare Access assertion header, without verifying the token |
| MGR-M42 | Medium | Inferred | A machine-readable map of the whole internal documentation tree is published at a well-known URI, configured for cross-origin fetch |
| MGR-L48 | Low | Inferred | The token page returns a 90-day bearer token in an HTML body with no cache, policy or framing control, and reflects a request header |
| MGR-L49 | Low | Inferred | Token rotation does not revoke the token it replaces and there is no issuance cap, so the set of live 90-day credentials only grows |
phenom-push-sender
4 findings: 1 High, 1 Medium, 2 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H23 | High | Inferred | The push relay resolves caller-supplied identifiers as superuser and returns the result, including raw device push tokens |
| MGR-M59 | Medium | Inferred | No logging, alerting or rate limit exists in front of the static secret that gates superuser database access from the push relay |
| MGR-L58 | Low | Inferred | The push relay constructs its provider clients per request, so both documented token caches are dead and every request mints fresh credentials |
| MGR-L59 | Low | Inferred | The push relay relays upstream error text into its own responses, disclosing production schema detail |
adsb-archive
3 findings: 2 Medium, 1 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M01 | Medium | Inferred | A production cloud component is provisioned outside the control plane: state in another organisation’s storage, no CI, unsigned artifact |
| MGR-M02 | Medium | Inferred | The archive bucket’s read grant and CORS policy exist only as hand-applied live configuration, while three documents assert they are codified |
| MGR-L01 | Low | Inferred | Every object in the presign-only archive bucket is stamped with a one-year immutable cache lifetime under a 300-second capability |
Buzzard-Android
3 findings: 1 High, 1 Medium, 1 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H01 | High | Inferred | Three Google service-account private keys and the release signing keystore are committed, one into the live Firebase project |
| MGR-M04 | Medium | Inferred | A second service-account private key on the live App Distribution account is in Android repository history |
| MGR-L05 | Low | Inferred | A third Android signing keystore and its passphrase in plaintext are reachable from two tags a default clone fetches |
dev-environment
2 findings: 2 Medium.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M07 | Medium | Inferred | The developer image fetches and executes five remote installers with no integrity verification |
| MGR-M08 | Medium | Inferred | The developer image installs a privileged editor extension from a mutable release pointer, with a byte count as the only integrity check |
dev-environment-installer
2 findings: 1 High, 1 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-H03 | High | Inferred | The macOS installer embeds a GitHub token in the clone URL, persisting it in cleartext in a world-readable git config |
| MGR-L10 | Low | Inferred | The macOS installer passes a cloud secret key and two API tokens as command-line arguments, exposing them in the process list |
mlx-whisper-stt
2 findings: 1 Medium, 1 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-M14 | Medium | Inferred | Voice-enrolment audio crosses the network in plaintext to an unauthenticated transcription endpoint bound to all interfaces |
| MGR-L23 | Low | Inferred | The transcription service returns the raw exception message to an unauthenticated caller in its 500 response |
analytics-thephenom-app+ ghostmode-thephenom-app
1 finding: 1 Low.
| Ref | Severity | Confidence | Title |
|---|---|---|---|
| MGR-L04 | Low | Inferred | Login CSRF on the session endpoint of two Workers: cross-site POST accepted with no origin, referer, content-type or token check |
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.