The project is in pre-MVP development. Security fixes apply to the active main branch until release branches exist.
Do not open a public issue for vulnerabilities involving authentication, authorization, data isolation, Firestore rules, account deletion, synchronization data loss, or exposed secrets.
Report privately to the repository owner.
Include:
- Affected area.
- Reproduction steps.
- Expected impact.
- Any logs, screenshots, or proof of concept that can be shared safely.
- Firebase Authentication and the local owner adoption boundary.
- Firestore security rules, including per-field range validation.
- User data isolation under
users/{uid}. - Account deletion ordering.
- Offline synchronization and tombstone handling.
- Analytics event payloads and user properties.
- Logging redaction in release builds.
- Secrets, tokens, signing credentials, and CI configuration.
Changes in these areas require explicit human review (AGENTS.md).
Allowed in the repository:
-
google-services.jsonandGoogleService-Info.plist. These are client configuration, not secrets, provided the corresponding API keys are restricted in the Google Cloud console by package name, bundle id and signing certificate.Since
D-34the repository is public, so that proviso is a precondition rather than good practice: anyone can read those keys the moment the files are committed. E0-07 restricted the development keys in the Google Cloud console before committing either file; the completed evidence is indocs/handoff-E0-07.md. Every future app registration MUST repeat that ordering.Under
D-41, the Android development key is restricted to the debug application ID and the owner's current local debug signing certificate. The iOS development key is restricted to the debug bundle identifier. Moving Android development to another machine requires an explicit additional fingerprint; restrictions MUST NOT be widened automatically.Under
D-54, the restricted development configurations are build-specific:androidApp/src/debug/google-services.jsonandiosApp/Config/Debug/GoogleService-Info-Debug.plist. They MUST NOT be included in release artifacts. Release builds fail closed until E4-04 supplies separately reviewed production configuration.
Never committed:
- Keystores and
*.jks,*.keystore. - Apple
*.p8,*.p12, provisioning profiles. - Service-account JSON of any kind.
local.properties.- Any token, password or private key.
Requirements:
.gitignoreMUST cover the entries above from the first commit.- Secret scanning MUST be enabled on the repository.
- Product tests in CI run against the Firestore emulator and MUST NOT hold Firebase client or
administrator credentials or write to a real Firebase project. D-66 permits one short-lived
GitHub OIDC identity whose custom role contains only
cloudfunctions.functions.get; it can read the deployed runtime and cannot read application data or mutate the project. - If a secret is committed, treat it as compromised: rotate it first, then rewrite history.
- Crash reports MUST NOT contain UID, tokens, notes, exact odometer values, exact costs, raw Firestore payloads or free-text user content.
- Broad billing-account role on one isolated identity (
D-69). A personal Cloud Billing account cannot host a custom IAM role, andbilling.resourceAssociations.deleteis available to the cutoff through the broad standardroles/billing.adminrole. The role belongs only to the keylessdevelopment-billing-cutoffidentity. Its project role contains only project read, billing-assignment deletion and service use; itsroles/run.invokerbinding is scoped only to thestopbillingCloud Run service so Eventarc can deliver the CloudEvent. It has no Auth, Firestore, Storage or product-data role. A Cloud Monitoring alert sends every billing-account administrative change to the owner, and the runbook records every deliberate billing-state transition. - Production Cloud Functions transitive advisory GHSA-w5hq-g745-h8pq (
D-68). The official Functions graph containsuuid@9.0.1through Firebase Admin's Cloud Storage dependency, and a production-only audit reports seven moderate entries.firebase-admincannot be removed because Firebase Functions 7.3.2 declares it as a mandatory peer. The executable full-trigger test proves thatstopBillingreaches the Billing disable operation without loading Cloud Storage oruuid, so the affected UUID v3/v5/v6 buffer path is unreachable. CI displays moderate findings and fails on high or critical. The dated, expiring acceptance and current-state history live indocs/SECURITY_ADVISORY_REGISTER.mdand are reviewed through TD-01. - Moderate Firebase CLI transitive advisories in the E3-01 test harness (
D-52). At acceptance,npm auditreports five moderate dependency entries representing two advisories below the pinned Firebase CLI 15.28.1: OpenTelemetry W3C baggage allocation and old UUID buffer APIs. The CLI runs only the local Firestore emulator against repository-owned fixtures; those paths are unused and none of the npm packages ships in the Android or iOS app. Re-evaluate on any high or critical advisory, affected-path expansion or reviewed Firebase CLI update. - App Check is an abuse control, not authorization (
D-67). Authentication and Firestore enforce App Check because billing converts frictionless anonymous-authentication abuse into a direct cost vector. Firestore Rules remain load-bearing: App Check does not prove owner identity, validate schema or authorize a document path. - No general Cloud Functions-mediated database access in the MVP (
docs/SPECIFICATION.md §3.3). The only MVP server/Admin operations are theD-23user-requested account deletion and theD-63anonymous identity/data-cleanup paths. Server-side validation before remote writes, authenticated identity and authorization checks before remote reads, rate limiting, abuse monitoring and broader privileged server-side product operations require a future story or ADR before implementation. - No receipt, odometer image or OCR processing in the MVP (
docs/SPECIFICATION.md §3.3). Future local AI text recognition must keep receipt images, odometer images, recognized raw text and extracted fields local unless a later explicit owner decision changes the privacy model. - Last-write-wins backup collision handling can lose one whole-document update if the same account is actively edited on multiple devices. Active multi-device editing is not a supported MVP workflow. Documented in
docs/SPECIFICATION.md §9.5. - Anonymous data loss if the user uninstalls, clears the retained Firebase Auth session or
reaches native automatic cleanup eligibility before linking a permanent provider. Anonymous
identity is device-bound, and the risk is disclosed through
D-62foreground notices. Documented indocs/SPECIFICATION.md §4anddocs/CONTRACTS.md §11.2. - One temporary Cloud Functions 1st gen dependency.
onAnonymousUserDeletedis the only permitted exception because Authentication user-deletion events have no 2nd gen equivalent. The exact migration surface, quarterly owner review and prohibition on additional 1st gen functions are tracked indocs/TECHNICAL_PLAN.md §13(TD-01). - Cloud Billing controls are delayed best effort, not a hard cap. The D-66 EUR 10 budget sends notifications and the project-local function removes billing after reported actual cost reaches 100%. Cost reporting can arrive late, so charges can exceed the budget. The intended development response is a complete project outage followed by owner-led manual recovery. Production MUST NOT inherit this automatic cutoff.
- Analytics collection is disabled by default and requires an explicit opt-in.
- Analytics events carry no odometer, volume, cost, notes, entity IDs or UID.
- Release logs never contain the Firebase UID, notes, exact odometer values or costs.
- In-app account deletion is available and uses the
D-23Firebase Admin server operation to delete remote data before the auth account. Mobile clients never receive a Firestore hard-delete permission. - App Check debug tokens are secrets. They MUST NOT be committed, printed by CI or embedded in a distributed build. Debug-provider dependencies and factories are forbidden in release variants.
- The GitHub OIDC provider admits only the immutable
davidru85/carApprepository identity, the protected runtime-verification environment and approved main/PR contexts. Its service account has a custom role containing exactlycloudfunctions.functions.getand no broader project role.