Skip to content

test(queue): verify concurrent cross-tenant execution isolation - #6299

Merged
loopover-orb[bot] merged 1 commit into
mainfrom
review/rent-a-loop-execution-sandboxing
Jul 16, 2026
Merged

test(queue): verify concurrent cross-tenant execution isolation#6299
loopover-orb[bot] merged 1 commit into
mainfrom
review/rent-a-loop-execution-sandboxing

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

Closes #4793. Per its acceptance criterion — "a deliberately adversarial test run (attempting to access another tenant's data or gittensory's own infrastructure) fails to escape the sandbox" — this required two things: an audit, and proof.

The audit. Systematically reviewed every module-level mutable-state candidate:

  • All ~96 let/var/Map/Set module-level declarations across src/github/**, src/queue/**, src/review/**, src/selfhost/**, src/signals/**, src/db/**. The vast majority are static read-only allowlists (hardcoded string vocab, never mutated). The real candidates — the installation-token cache, the GitHub REST response cache, inFlightGraphQlPosts single-flight map — are all correctly keyed by installation/auth-identity + URL (verified by reading each key-derivation function directly, e.g. responseCacheKey in src/github/client.ts embeds both the auth identity and the full URL). The rest are deployment-wide singletons by design (Sentry/OTel SDK clients, the AI-provider health streak, the global kill-switch's process-local cache) — correctly global, not tenant data.
  • packages/loopover-miner's own module-level state (the default*Store singleton pattern used throughout its lib files) is safe by construction: per Multi-tenant hosted architecture spec #4783's architecture, each rented loop run is an independent CLI process invocation, never a shared long-lived instance serving multiple tenants — module state can't leak across runs that don't share a process.

No code changes were needed anywhere — every candidate was already either correctly scoped or safely global.

The proof. Added a stronger, more direct test than #4794's narrower credential-cache-only coverage: two different installations' real pull_request webhooks driven through the actual processJob entry point, running truly concurrently (Promise.all), sharing one Worker isolate's module-level state end-to-end. Every GitHub write (the reviewing-placeholder post and the final comment) is checked against both tenants' identifying data — repo full name and PR title never cross-contaminate, and each write carries only its own installation's minted token.

Test plan

  • npx tsc --noEmit clean
  • npm run test:ci (full local gate incl. drift checks, coverage, engine parity, MCP/miner packs, UI build): green, verified via literal captured exit code
  • test/unit/queue.test.ts in isolation: 166/166 passed
  • Rebased onto latest origin/main, no conflicts

…Job (#4793)

Rent-a-Loop's #4793 asked for a deliberately adversarial test proving one
tenant's execution can't reach another tenant's data. Audited every
module-level mutable state candidate across src/ (github, queue, review,
selfhost, signals, db -- ~96 declarations) plus packages/loopover-miner's
execution runtime: everything is either a static read-only allowlist, a
correctly tenant/token-keyed cache (verified via existing key-derivation
code, e.g. the GitHub response cache's auth-identity+URL key), a
deployment-wide singleton by design (SDK clients, health counters,
kill-switch cache), or -- for the miner's own execution runtime -- safe by
construction since each rented loop run is a fresh CLI process per the
architecture #4783 already established, not a shared long-lived instance.

Adds a stronger end-to-end proof than #4794's narrower credential-cache
test: two different installations' real pull_request webhooks driven
through the actual processJob entry point CONCURRENTLY, sharing one
Worker isolate's module-level state, with every GitHub write checked
against both tenants' identifying data. No code changes were needed --
the isolation already held.
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@JSONbored JSONbored self-assigned this Jul 16, 2026
@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 16, 2026
@loopover-orb

loopover-orb Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-16 00:43:25 UTC

1 file · 1 AI reviewer · no blockers · readiness 86/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR adds a single test verifying two tenants' pull_request webhooks processed concurrently via the real processJob entry point don't cross-contaminate shared Worker-isolate module state — each installation mints its own token, writes are authenticated with the correct token, and final comments don't leak the other tenant's title/repo. The test is well-constructed (real concurrency via Promise.all, a shared fetch stub simulating both tenants' API surfaces, and assertions on both credential isolation and content leakage) and closes #4793 per its stated acceptance criterion. No production code changes are included since the audit found no scoping defects, which is consistent with a pure-verification PR.

Nits — 6 non-blocking
  • The fetch stub's fallback `return Response.json({})` for unmatched URLs (test/unit/queue.test.ts) could silently mask a request going to an unexpected endpoint instead of failing loudly.
  • aiReviewMode is set to "off" for both tenants, so this test doesn't exercise cross-tenant isolation of any AI-review-specific caches/state — worth a follow-up test with aiReviewMode enabled if those caches carry per-installation risk.
  • The comment explaining the empty GET-comments response causing a fresh POST instead of PATCH is helpful but could be simplified since it duplicates reasoning already covered by the acceptance-criterion comment above the test.
  • Consider parameterizing the tenant fixtures (test/unit/queue.test.ts) into a shared helper if more cross-tenant isolation tests are added later, to avoid duplicating the fetch-stub routing logic.
  • Add a version of this test with aiReviewMode enabled to also cover any AI-provider response cache or health-streak state for cross-tenant leakage.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #4793
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ❌ 8/20 High review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 42 registered-repo PR(s), 34 merged, 401 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 42 PR(s), 401 issue(s).
Improvement ℹ️ Insufficient signal risk: clean · value: insufficient-signal · LLM: moderate
Linked issue satisfaction

Not yet addressed
The issue asks for a sandboxing mechanism enforced for every loop execution (process/OS-level isolation, e.g. per #4783's tenancy model) plus an adversarial escape test, and is explicitly blocked on #4783 with a note that it needs dedicated security review, not just a passing test; this PR instead adds a unit test asserting that module-level in-memory state (caches, single-flight maps) doesn't lea

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, Ruby, Go, JavaScript, MDX, Shell, Solidity
  • Official Gittensor activity: 42 PR(s), 401 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Then work through the remaining 2 steps in the Signals table above.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 74832d4 into main Jul 16, 2026
15 checks passed
@loopover-orb
loopover-orb Bot deleted the review/rent-a-loop-execution-sandboxing branch July 16, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Per-tenant execution sandboxing

1 participant