Skip to content

[codex] Harden update enumeration and attachment reads#2057

Merged
riderx merged 9 commits intomainfrom
codex/fix-update-enumeration-oracle
May 8, 2026
Merged

[codex] Harden update enumeration and attachment reads#2057
riderx merged 9 commits intomainfrom
codex/fix-update-enumeration-oracle

Conversation

@riderx
Copy link
Copy Markdown
Member

@riderx riderx commented May 7, 2026

Summary (AI generated)

  • Added an IP-scoped cache guard for repeated /updates app-id misses.
  • Required update-issued read keys for public attachment download paths.
  • Added regression coverage for update enumeration limiting and signed attachment reads.

Motivation (AI generated)

GHSA-4pq5-xr4m-6gxx reported that /updates could be used as an unauthenticated app-id oracle and that attachment reads were not validating caller access or the update-issued download key.

Business Impact (AI generated)

This reduces cross-tenant bundle exposure risk and limits unauthenticated customer/app reconnaissance while keeping existing updater download URLs compatible.

Test Plan (AI generated)

  • bun lint
  • bun lint:backend
  • bunx eslint tests/update-oracle-guard.unit.test.ts tests/files-app-read-guard.unit.test.ts tests/files-security.test.ts
  • bunx vitest run tests/update-oracle-guard.unit.test.ts tests/files-app-read-guard.unit.test.ts
  • bun run supabase:with-env -- bunx vitest run tests/updates.test.ts tests/files-security.test.ts
  • bun typecheck

Generated with AI

Summary by CodeRabbit

  • New Features

    • Implemented update-enumeration rate limiting; clients that exceed the distinct-miss threshold now receive an immediate 429 response.
  • Tests

    • Added unit tests covering the enumeration guard, limits, and response behavior.
  • Chores

    • Changed local bundle naming to use a "beta.local" fallback.
    • Made test fixture package dependency versions exact for more consistent test setups.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces an IP-based update-enumeration guard that tracks distinct missing app_id requests per client IP and returns HTTP 429 when thresholds are exceeded, plus updates default bundle version naming to use locally-scoped beta identifiers and aligns test fixture dependencies to exact versions.

Changes

Update Enumeration Rate Limiting

Layer / File(s) Summary
Configuration and Environment Parsing
supabase/functions/_backend/utils/updateOracleGuard.ts
Parses RATE_LIMIT_UPDATE_ENUMERATION_MISSES environment variable with positive integer validation and default of 5.
App ID Hashing and Bucket Mapping
supabase/functions/_backend/utils/updateOracleGuard.ts
Normalizes app_id (trim/lowercase), hashes via SHA-256 or HMAC-SHA-256 with optional secrets, and deterministically maps to one of 256 buckets.
Cache Entry and IP Binding
supabase/functions/_backend/utils/updateOracleGuard.ts
Constructs per-IP and per-IP/per-bucket cache keys with 15-minute TTL; skips processing for unknown client IPs.
Enumeration Limit Checking
supabase/functions/_backend/utils/updateOracleGuard.ts
Queries per-IP "limit" cache entry to short-circuit already-limited IPs and return early with resetAt timestamp.
Distinct Miss Counting
supabase/functions/_backend/utils/updateOracleGuard.ts
Reads all per-IP bucket entries, aggregates unique app hashes, and computes distinct miss count with maximum resetAt.
Bucket Payload Updates
supabase/functions/_backend/utils/updateOracleGuard.ts
Appends only unseen app hashes to per-IP/per-bucket cache entries and truncates to the most recent 64 entries.
recordUpdateEnumerationMiss Implementation
supabase/functions/_backend/utils/updateOracleGuard.ts
End-to-end miss recording: validates input, hashes/buckets app_id, checks early-limit status, writes deduped bucket entries, counts distinct misses, and optionally writes per-IP limit entry when threshold is met.
Limited Response Generation
supabase/functions/_backend/utils/updateOracleGuard.ts
Returns fixed HTTP 429 JSON response with error code on_premise_app.
Update Endpoint Integration
supabase/functions/_backend/utils/update.ts
Integrates enumeration guard: imports guard functions, adds early limit checks, records enumeration misses for cached-onprem and missing-appOwner paths, and returns 429 when limited.
Test Harness
tests/update-oracle-guard.unit.test.ts
Creates in-memory cache mock and Hono test app exposing /updates and /limited endpoints that exercise enumeration guard functions.
Test Setup and Configuration
tests/update-oracle-guard.unit.test.ts
Configures per-test hooks to stub global caches API and set RATE_LIMIT_UPDATE_ENUMERATION_MISSES environment variable.
Unit Tests
tests/update-oracle-guard.unit.test.ts
Validates distinct miss blocking at threshold, known app non-blocking, per-IP limit short-circuiting, and distinctness behavior (repeated same app_id does not increment count).

Bundle Naming and Test Fixture Updates

Layer / File(s) Summary
Bundle Version Naming
cli/src/bundle/upload.ts, cli/src/bundle/zip.ts
Changes default bundle name from 0.0.1-beta.<uuid> to 0.0.1-beta.local-<uuid> when no explicit bundle or package version is available.
Fixture Dependency Versions
cli/test/fixtures/setup-test-projects.sh
Updates all test fixture @capgo/capacitor-updater dependencies across npm, yarn, pnpm, bun, and multiple monorepo setups from caret ranges (^$PACKAGE_VERSION) to exact versions ($PACKAGE_VERSION).
Fake-Version-Trap Fixture Structure
cli/test/fixtures/setup-test-projects.sh
Restructures fake-version-trap monorepo to include @capgo/capacitor-updater at root package.json with exact version; app-level dependency is later manipulated to simulate version mismatch.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 With guards and buckets now in place,
And bundles branded "beta.local" with grace,
Missing apps are tracked per IP thread,
While fixtures hold versions exact instead.
Rate limits keep chaos at bay,
The update enumeration holds sway! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: hardening update enumeration (adding IP-scoped cache guard) and attachment reads (adding required update-issued read keys).
Description check ✅ Passed The description includes a summary explaining the security improvements, motivation tied to a specific vulnerability, business impact, and a detailed test plan with checkmarks showing tests were executed.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/fix-update-enumeration-oracle

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 7, 2026

Merging this PR will not alter performance

✅ 28 untouched benchmarks


Comparing codex/fix-update-enumeration-oracle (3dd9714) with main (fb0482a)

Open in CodSpeed

@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from d0b55e4 to e326a52 Compare May 7, 2026 08:56
@riderx riderx marked this pull request as ready for review May 7, 2026 09:16
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
supabase/functions/_backend/files/files.ts (1)

467-470: 💤 Low value

Use optional chaining for cleaner null check.

Per static analysis, the conditional can be simplified using optional chaining.

♻️ Suggested refactor
-    const app = await getAppByAppIdPg(c, signedScopedPath.app_id, drizzleClient)
-    if (!app || app.owner_org !== signedScopedPath.owner_org) {
+    const app = await getAppByAppIdPg(c, signedScopedPath.app_id, drizzleClient)
+    if (app?.owner_org !== signedScopedPath.owner_org) {
       quickError(404, 'not_found', 'Not found')
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/files/files.ts` around lines 467 - 470, Replace
the two-step null and owner_org check with a single optional-chaining
conditional to simplify the logic: in the block using getAppByAppIdPg and
quickError, change the if-statement so it uses app?.owner_org instead of
separate existence check (e.g., if (app?.owner_org !==
signedScopedPath.owner_org) quickError(...)), keeping the same quickError call
and behavior; ensure you reference getAppByAppIdPg, app,
signedScopedPath.owner_org, and quickError when making the change.
supabase/functions/_backend/plugins/updates.ts (1)

18-23: ⚡ Quick win

Run the IP guard before request body parsing

isUpdateEnumerationLimited() is body-independent, so checking it before parseBody() avoids extra parse/validation work for already-limited traffic on /updates.

Proposed reorder diff
 app.post('/', async (c) => {
-  const body = await parseBody<AppInfos>(c)
-  cloudlog({ requestId: c.get('requestId'), message: 'post updates body', body })
   const updateEnumerationLimit = await isUpdateEnumerationLimited(c)
   if (updateEnumerationLimit.limited) {
     return updateEnumerationLimitedResponse(c)
   }
+  const body = await parseBody<AppInfos>(c)
+  cloudlog({ requestId: c.get('requestId'), message: 'post updates body', body })
   if (isLimited(c, body.app_id)) {
     return simpleRateLimit(body)
   }
As per coding guidelines: “Plugin endpoints (`/updates`, `/stats`, `/channel_self`) are extremely hot paths...”.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/plugins/updates.ts` around lines 18 - 23, Move
the update-enumeration guard ahead of body parsing so we avoid unnecessary
parse/validation on hot `/updates` traffic: call isUpdateEnumerationLimited(c)
and, if limited, immediately return updateEnumerationLimitedResponse(c) before
invoking parseBody<AppInfos>(c) or emitting cloudlog for the body; keep existing
requestId usage when checking the guard so logging/metrics remain intact in the
early-return path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 59-67: The cache read calls in isUpdateEnumerationLimited (and the
analogous cache accesses later) currently let exceptions from
buildUpdateEnumerationCacheRequest or cacheEntry.helper.matchJson bubble up and
break the /updates guard; wrap the entire cache lookup and JSON match in a
try/catch so any thrown error causes an early return of { limited: false }
(best-effort fail-open) and optionally log the error for diagnostics; apply the
same try/catch pattern to the other cache access sites referenced (the
functions/blocks using buildUpdateEnumerationCacheRequest and
cacheEntry.helper.matchJson around the other guarded checks) so cache API
failures never turn into request failures.
- Around line 110-114: The cloudlog call in updateOracleGuard.ts is logging the
raw appId (variable appId) in the reconnaissance-handling path; change the
payload so it does not include plaintext appId and instead logs appIdHash (or a
short prefix/sanitized substring of appIdHash) and remove or redact appId from
the cloudlog arguments (the cloudlog(...) invocation that currently includes
requestId, message, appId, count). Ensure you update any variable references
used in that cloudlog call (e.g., appId -> appIdHash or appIdHash.slice(0,8)) so
only non-sensitive hashed/shortened tenant identifiers are emitted.

---

Nitpick comments:
In `@supabase/functions/_backend/files/files.ts`:
- Around line 467-470: Replace the two-step null and owner_org check with a
single optional-chaining conditional to simplify the logic: in the block using
getAppByAppIdPg and quickError, change the if-statement so it uses
app?.owner_org instead of separate existence check (e.g., if (app?.owner_org !==
signedScopedPath.owner_org) quickError(...)), keeping the same quickError call
and behavior; ensure you reference getAppByAppIdPg, app,
signedScopedPath.owner_org, and quickError when making the change.

In `@supabase/functions/_backend/plugins/updates.ts`:
- Around line 18-23: Move the update-enumeration guard ahead of body parsing so
we avoid unnecessary parse/validation on hot `/updates` traffic: call
isUpdateEnumerationLimited(c) and, if limited, immediately return
updateEnumerationLimitedResponse(c) before invoking parseBody<AppInfos>(c) or
emitting cloudlog for the body; keep existing requestId usage when checking the
guard so logging/metrics remain intact in the early-return path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9913ff26-7059-4161-9010-e58defbb4670

📥 Commits

Reviewing files that changed from the base of the PR and between fd81385 and e326a52.

📒 Files selected for processing (9)
  • supabase/functions/_backend/files/files.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/utils/updateOracleGuard.ts
  • tests/files-app-read-guard.unit.test.ts
  • tests/files-local-read-proxy.unit.test.ts
  • tests/files-r2-error.test.ts
  • tests/files-security.test.ts
  • tests/update-oracle-guard.unit.test.ts

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts
Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e326a5275e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/files/files.ts Outdated
@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from e326a52 to 44a10f4 Compare May 7, 2026 09:24
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 101-107: The current non-atomic flow that reads with
cacheEntry.helper.matchJson<UpdateEnumerationData>(...) then computes and writes
back with putJson can lose increments under concurrency; update the logic in
buildUpdateEnumerationCacheRequest / callers (where matchJson and putJson are
used, and around UpdateEnumerationData) to perform an atomic upsert keyed by
window+IP+appHash (or use your store's transactional primitive / durable object)
so each miss increments exactly once per window; specifically replace the
matchJson→compute→putJson sequence with a single atomic operation (or a
compare-and-swap / transaction API on cacheEntry.helper) that merges increments
server-side, or implement retry CAS if your helper exposes a version/token,
ensuring uniqueness by the combined key.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fe9ef3a4-4871-4a70-b172-9df3f48abcce

📥 Commits

Reviewing files that changed from the base of the PR and between e326a52 and 44a10f4.

📒 Files selected for processing (9)
  • supabase/functions/_backend/files/files.ts
  • supabase/functions/_backend/plugins/updates.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/utils/updateOracleGuard.ts
  • tests/files-app-read-guard.unit.test.ts
  • tests/files-local-read-proxy.unit.test.ts
  • tests/files-r2-error.test.ts
  • tests/files-security.test.ts
  • tests/update-oracle-guard.unit.test.ts
✅ Files skipped from review due to trivial changes (2)
  • tests/update-oracle-guard.unit.test.ts
  • tests/files-security.test.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/files-local-read-proxy.unit.test.ts
  • supabase/functions/_backend/plugins/updates.ts
  • tests/files-app-read-guard.unit.test.ts

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44a10f40ba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from 44a10f4 to b30b6e8 Compare May 7, 2026 09:51
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b30b6e80c3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/files/files.ts Outdated
Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
supabase/functions/_backend/utils/updateOracleGuard.ts (1)

127-132: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wrap limited-marker cache writes to keep the guard fail-open.

putJson() at Line 128 can still throw and fail /updates even after computing limited. This should follow the same best-effort error handling used elsewhere.

Suggested hardening
   if (limited) {
-    await cacheEntry.helper.putJson(
-      buildUpdateEnumerationLimitRequest(cacheEntry.helper, cacheEntry.ip),
-      { resetAt: bucketState.resetAt ?? resetAt },
-      UPDATE_ENUMERATION_TTL_SECONDS,
-    )
+    try {
+      await cacheEntry.helper.putJson(
+        buildUpdateEnumerationLimitRequest(cacheEntry.helper, cacheEntry.ip),
+        { resetAt: bucketState.resetAt ?? resetAt },
+        UPDATE_ENUMERATION_TTL_SECONDS,
+      )
+    }
+    catch (error) {
+      cloudlog({
+        requestId: c.get('requestId'),
+        message: 'Update enumeration guard limit write failed',
+        error,
+      })
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/utils/updateOracleGuard.ts` around lines 127 -
132, The write of the "limited" marker using cacheEntry.helper.putJson (with
buildUpdateEnumerationLimitRequest and UPDATE_ENUMERATION_TTL_SECONDS) can throw
and must be made best-effort so the guard stays fail-open; wrap the await
cacheEntry.helper.putJson(...) call in a try/catch around the limited branch,
catch and swallow/log the error (using the existing logger or cacheEntry.helper
logger) without rethrowing so failures to write the cache do not fail the
/updates path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/files/files.ts`:
- Around line 479-482: The current early return that allows
isAttachmentExistenceProbe to bypass auth (the if block checking
!isUploadAttachmentRoute(c) && isAttachmentExistenceProbe(c)) must be removed so
unauthenticated callers cannot infer existence or fetch ranges; instead, enforce
the same signed-read/auth gate used for normal attachment fetches by removing
the bypass and routing such probes through the existing signed-read verification
path (i.e., have attachment probes pass through the same authentication check
used by the attachment GET handler), ensuring functions like
isAttachmentExistenceProbe and isUploadAttachmentRoute no longer allow
unauthenticated short-circuits.

In `@supabase/functions/_backend/utils/update.ts`:
- Around line 131-134: The code calls setAppStatus even for requests already
marked limited by recordUpdateEnumerationMiss; move the early return so you
check updateEnumerationLimit.limited immediately after calling
recordUpdateEnumerationMiss and return updateEnumerationLimitedResponse(c)
before calling setAppStatus(c, app_id, 'onprem', true). Update the flow in the
same function to call recordUpdateEnumerationMiss(...), if limited -> return
updateEnumerationLimitedResponse(...); otherwise proceed to setAppStatus(...)
and continue.

In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 37-40: The current getUpdateEnumerationBucket logic (and the
similar checks at the other spots referenced) is vulnerable because it
deterministically maps app IDs to buckets and counts occupied buckets rather
than distinct app IDs; to fix it, stop relying on plain sha256(appId) % N as the
anti-enumeration signal and instead (1) track uniqueness by hashed app ID
(store/compare H(appId) or HMAC(secret, appId)) when counting updates so you
count distinct app IDs, and (2) make the bucket selection unpredictable to
attackers by using a server-side secret (e.g., HMAC with a rotating secret) when
computing the bucket in getUpdateEnumerationBucket so precomputation is
infeasible; update all corresponding guard checks (the other blocks at 64-67 and
111-113) to use the new distinct-hash tracking and keyed bucket mapping.

---

Duplicate comments:
In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 127-132: The write of the "limited" marker using
cacheEntry.helper.putJson (with buildUpdateEnumerationLimitRequest and
UPDATE_ENUMERATION_TTL_SECONDS) can throw and must be made best-effort so the
guard stays fail-open; wrap the await cacheEntry.helper.putJson(...) call in a
try/catch around the limited branch, catch and swallow/log the error (using the
existing logger or cacheEntry.helper logger) without rethrowing so failures to
write the cache do not fail the /updates path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 05c52510-46b4-4c68-8572-f31df0ca4f26

📥 Commits

Reviewing files that changed from the base of the PR and between 44a10f4 and b30b6e8.

📒 Files selected for processing (8)
  • supabase/functions/_backend/files/files.ts
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/utils/updateOracleGuard.ts
  • tests/files-app-read-guard.unit.test.ts
  • tests/files-local-read-proxy.unit.test.ts
  • tests/files-r2-error.test.ts
  • tests/files-security.test.ts
  • tests/update-oracle-guard.unit.test.ts

Comment thread supabase/functions/_backend/files/files.ts Outdated
Comment thread supabase/functions/_backend/utils/update.ts
Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from b30b6e8 to 89bbbdb Compare May 7, 2026 10:05
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89bbbdb212

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/files/files.ts Outdated
Comment thread supabase/functions/_backend/files/files.ts Outdated
@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from 89bbbdb to 2cee9e7 Compare May 7, 2026 10:17
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2cee9e732c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/files/files.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 269fb5a50b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/utils/update.ts
Comment thread supabase/functions/_backend/files/files.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
supabase/functions/_backend/utils/updateOracleGuard.ts (1)

194-199: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the limit-marker write fail-open.

Line 195 is the one remaining cache write outside the guarded best-effort path. If putJson() throws after the threshold is reached, recordUpdateEnumerationMiss() will bubble an exception and /updates returns a 500 instead of a limited response.

Suggested hardening
   if (limited) {
-    await cacheEntry.helper.putJson(
-      buildUpdateEnumerationLimitRequest(cacheEntry.helper, cacheEntry.ip),
-      { resetAt: missState.resetAt ?? resetAt },
-      UPDATE_ENUMERATION_TTL_SECONDS,
-    )
+    try {
+      await cacheEntry.helper.putJson(
+        buildUpdateEnumerationLimitRequest(cacheEntry.helper, cacheEntry.ip),
+        { resetAt: missState.resetAt ?? resetAt },
+        UPDATE_ENUMERATION_TTL_SECONDS,
+      )
+    }
+    catch (error) {
+      cloudlog({
+        requestId: c.get('requestId'),
+        message: 'Update enumeration guard limit write failed',
+        error,
+      })
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/functions/_backend/utils/updateOracleGuard.ts` around lines 194 -
199, The cache write at cacheEntry.helper.putJson (invoked with
buildUpdateEnumerationLimitRequest and resetAt) must be made fail-open: wrap the
await cacheEntry.helper.putJson(...) call in a try/catch so any thrown error is
swallowed or logged but not re-thrown, ensuring
recordUpdateEnumerationMiss()/the /updates response does not bubble a 500;
update the code in updateOracleGuard.ts around the limited branch to catch
exceptions from putJson and proceed as a best-effort operation.
🧹 Nitpick comments (1)
tests/update-oracle-guard.unit.test.ts (1)

77-79: ⚡ Quick win

Assert the limited payload exactly.

toMatchObject({ error: 'on_premise_app' }) still passes when extra keys are added, so these tests would miss a response-shape regression on the cache-sensitive 429 contract. An exact equality assertion would lock that down.

Suggested assertion change
-    await expect(blocked.json()).resolves.toMatchObject({ error: 'on_premise_app' })
+    await expect(blocked.json()).resolves.toEqual({ error: 'on_premise_app' })
-    await expect(blocked.json()).resolves.toMatchObject({ error: 'on_premise_app' })
+    await expect(blocked.json()).resolves.toEqual({ error: 'on_premise_app' })

As per coding guidelines, "Maintain cache-specific response codes and body shapes for plugin endpoints (/updates, /stats, /channel_self): return 429 + {error: 'on_premise_app'} or {error: 'need_plan_upgrade'} to trigger Cloudflare snippet caching; do not change these without updating the Cloudflare snippet and app status logic".

Also applies to: 130-131

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/update-oracle-guard.unit.test.ts` around lines 77 - 79, The test
currently uses a loose shape check (await
expect(blocked.json()).resolves.toMatchObject({ error: 'on_premise_app' }))
which allows extra keys; change it to an exact equality assertion such as await
expect(blocked.json()).resolves.toEqual({ error: 'on_premise_app' }) or
toStrictEqual to lock the 429 response body shape, and apply the same change to
the other occurrence mentioned (the assertion around lines 130-131) so the
cache-sensitive contract is enforced; locate the assertions using the blocked
variable and the blocked.json() call in update-oracle-guard.unit.test.ts to
update them.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 215-216: The function updateEnumerationLimitedResponse currently
returns a body with { error: 'on_premise_app', message: 'On-premise app
detected' } which breaks the cache-compatible shape; change the response to
return only { error: 'on_premise_app' } with the same 429 status code (i.e.,
update the c.json(...) call in updateEnumerationLimitedResponse to emit only the
error property) so the /updates cache handling and Cloudflare snippet continue
to work as expected.

---

Duplicate comments:
In `@supabase/functions/_backend/utils/updateOracleGuard.ts`:
- Around line 194-199: The cache write at cacheEntry.helper.putJson (invoked
with buildUpdateEnumerationLimitRequest and resetAt) must be made fail-open:
wrap the await cacheEntry.helper.putJson(...) call in a try/catch so any thrown
error is swallowed or logged but not re-thrown, ensuring
recordUpdateEnumerationMiss()/the /updates response does not bubble a 500;
update the code in updateOracleGuard.ts around the limited branch to catch
exceptions from putJson and proceed as a best-effort operation.

---

Nitpick comments:
In `@tests/update-oracle-guard.unit.test.ts`:
- Around line 77-79: The test currently uses a loose shape check (await
expect(blocked.json()).resolves.toMatchObject({ error: 'on_premise_app' }))
which allows extra keys; change it to an exact equality assertion such as await
expect(blocked.json()).resolves.toEqual({ error: 'on_premise_app' }) or
toStrictEqual to lock the 429 response body shape, and apply the same change to
the other occurrence mentioned (the assertion around lines 130-131) so the
cache-sensitive contract is enforced; locate the assertions using the blocked
variable and the blocked.json() call in update-oracle-guard.unit.test.ts to
update them.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 12900c53-26a5-41fb-9445-6753def77943

📥 Commits

Reviewing files that changed from the base of the PR and between b30b6e8 and 61986d9.

📒 Files selected for processing (6)
  • cli/src/bundle/upload.ts
  • cli/src/bundle/zip.ts
  • cli/test/fixtures/setup-test-projects.sh
  • supabase/functions/_backend/utils/update.ts
  • supabase/functions/_backend/utils/updateOracleGuard.ts
  • tests/update-oracle-guard.unit.test.ts
✅ Files skipped from review due to trivial changes (1)
  • cli/src/bundle/upload.ts

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 61986d9b82

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Fixed
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 357f11fb3d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread supabase/functions/_backend/utils/updateOracleGuard.ts Outdated
@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from 28233e0 to 032c01b Compare May 7, 2026 13:06
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@riderx riderx force-pushed the codex/fix-update-enumeration-oracle branch from 4cbcb48 to 3dd9714 Compare May 7, 2026 22:47
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 7, 2026

@riderx riderx merged commit dc1ae02 into main May 8, 2026
52 checks passed
@riderx riderx deleted the codex/fix-update-enumeration-oracle branch May 8, 2026 00:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant