Skip to content

GEE auth and expression helpers copy-pasted identically across 4 Edge Functions — security patches will be missed #10

@tg12

Description

@tg12

Summary

The GEE authentication helpers (createJwt, getGeeAccessToken) and the expression flattener (flattenExpression) are copied verbatim across four Edge Functions. A security fix, a bug fix, or a behavior change in any of these routines must be applied in four separate files, and there is no mechanism to ensure consistency.

Evidence

The following functions are identically duplicated across analyze-field/index.ts, gee-analytics/index.ts, gee-ndvi-tiles/index.ts, and ndvi-timeseries/index.ts:

function base64url(data: Uint8Array): string { ... }          // 4 copies
async function createJwt(...): Promise<string> { ... }        // 4 copies
async function getGeeAccessToken(): Promise<string> { ... }   // 4 copies
function flattenExpression(nested: any): { ... } { ... }      // 4 copies

The duplication is literal: the same 50+ lines of JWT/OAuth implementation appear in four files with no variation. gee-analytics additionally duplicates computeValue and makeGeometry/reduceRegion which also appear in ndvi-timeseries.

Why this matters

  1. Security patch gap: If a vulnerability is found in the JWT signing logic or the base64url implementation, the fix must be consciously applied to all 4 files. There is no shared dependency to update.
  2. Divergence over time: As the project evolves, the copies will drift. Already, gee-analytics passes (token, projectId) as explicit parameters to computeValue, while analyze-field captures them via closure — same logic, different API, guaranteed to confuse.
  3. Maintenance overhead: Any change to GEE project ID fallback behavior (|| "earthengine-legacy") must be applied 4 times.
  4. No test coverage: The duplicated JWT implementation is untested. A single shared module would be a natural place to add unit tests.

Root cause

Supabase Edge Functions are isolated Deno scripts and do not natively support local shared modules without a specific import path setup. The developer copied the helpers rather than setting up a shared utility module.

Recommended fix

Create a shared utility module using Deno's local import support:

supabase/functions/_shared/gee-auth.ts
supabase/functions/_shared/gee-expression.ts

Supabase Edge Functions support relative imports within the supabase/functions/ directory. Import in each function:

import { getGeeAccessToken } from "../_shared/gee-auth.ts";
import { flattenExpression, computeValue } from "../_shared/gee-expression.ts";

The _shared/ directory (with underscore prefix) is excluded from Supabase's function deployment scanning, allowing it to be used as a shared library.

Acceptance criteria

  • createJwt, getGeeAccessToken, base64url, and flattenExpression exist in exactly one place under supabase/functions/_shared/
  • All four GEE functions import from the shared module rather than copying the code
  • Unit tests exist for createJwt and getGeeAccessToken in the shared module

Suggested labels

bug

Priority

P2

Severity

Medium — not an immediate security vulnerability, but a confirmed maintenance risk that will cause security patches to be missed.

Confidence

Confirmed — identical code blocks present in 4 separate files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions