🌐 US-Proxy
class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
Skip to content

fix(coderd): scope provisioner module file downloads to the daemon's org - #26635

Merged
sreya merged 5 commits into
mainfrom
provisionerd-server-download
Jun 24, 2026
Merged

fix(coderd): scope provisioner module file downloads to the daemon's org#26635
sreya merged 5 commits into
mainfrom
provisionerd-server-download

Conversation

@sreya

@sreya sreya commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

DownloadFile now verifies the requested module file belongs to a template version in the calling daemon's own organization. Cross-org requests get the same "is not a modules file" error.

The DownloadFile gRPC handler authorized module-file downloads using only
file.CreatedBy == uuid.Nil and Mimetype == application/x-tar, which every
organization's cached Terraform module archive satisfies. A provisioner key
scoped to one organization could supply another organization's file UUID and
receive its full Terraform module source.

Add HasTemplateVersionsUsingCachedModuleFileInOrg to verify the requested
module file is referenced by a template version in the calling daemon's
organization, and gate the download on it. Cross-org requests return the same
error as the metadata check so the handler does not confirm file existence in
other organizations.

Ref: ANT-2026-22440
@sreya

sreya commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Chat: Review posted | View chat
Requested: 2026-06-23 23:14 UTC by @sreya
Spend: $66.81 / $100.00

Review history
  • R1 (2026-06-23): 19 reviewers, 1 Nit, 2 P3, COMMENT. Review
  • R2 (2026-06-23), 1 Nit, 2 P3, COMMENT. Review
  • R3 (2026-06-23): 9 reviewers, 1 Nit, 2 P3, APPROVE. Review

deep-review v0.9.0 | Round 3 | 51591e3..b4e6d8f

Last posted: Round 3, 3 findings (2 P3, 1 Nit), APPROVE. Review

Finding inventory

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P3 Author accepted R3 (migration duration risk) templateversionterraformvalues.sql:37 No index on cached_module_files; seq-scan on every module-file download R1 Razor P3, Knuckle P3, Hisoka Note, Kite Note, Meruem Note, Ryosuke Note, Knov Note Yes
CRF-2 P3 Author fixed (5943884) provisionerdserver.go:1598 No server-side diagnostic log for org-isolation rejection R1 Leorio Yes
CRF-3 Nit Author fixed (b4e6d8f) provisionerdserver_test.go:5540 crypto/rand.Read error check is dead code since Go 1.24 R1 Ging-Go Yes
CRF-4 Nit Dropped by orchestrator (deliberate security traceability practice) provisionerdserver.go:1590 External audit ID ANT-2026-22440 in comment R1 Gon No
CRF-5 Nit Dropped by orchestrator (deliberate security traceability practice) download_file_test.go:118 External audit ID ANT-2026-22440 in test comment R1 Gon No
CRF-6 Nit Dropped by orchestrator (marginal style preference; comment carries correct content and matches codebase pattern) dbauthz.go:5701 dbauthz comment mixes mechanism narration with code-visible fact R1 Gon No
CRF-7 Nit Dropped by orchestrator (intent clear from context; aligned vs unaligned test contrast) download_file_test.go:170 Unnamed offset 512 in test data size R1 Gon No

Contested and acknowledged

CRF-1 (P3, templateversionterraformvalues.sql:37) - No index on cached_module_files

  • Finding: Seven reviewers flagged the missing index on cached_module_files. The EXISTS query seq-scans template_version_terraform_values on every module-file download. On the rejection path (cross-org), no short-circuit occurs and the entire table is scanned. A partial index WHERE cached_module_files IS NOT NULL was proposed.
  • Author defense: @sreya: "We're going to skip the index for now since it may result in an unintentionally long migration when people upgrade." The concern is that adding an index in a migration could cause a long lock on the table during upgrades for deployments with many template versions.
  • Author accepted (R3): Human author decision. The tradeoff is understood: seq-scan at current scale vs migration risk. No ticket filed.

Round log

Round 1

Panel (19 reviewers). 0 P0, 0 P1, 0 P2, 2 P3, 1 Nit new. 4 dropped (Nit). Reviewed against 51591e3..13bb844.

Round 2

BLOCKED. CRF-1 and CRF-3 silent. CRF-2 addressed. No review.

Round 3

Panel (9 reviewers). CRF-2 and CRF-3 fixes verified. CRF-1 accepted (human decision). 0 new findings. Reviewed against 51591e3..b4e6d8f.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@coder-agents-review coder-agents-review 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.

Well-scoped security fix. The org check sits between the metadata pre-filter and data streaming, uses the same error to avoid confirming file existence across orgs, and the tests verify both rejection and the absence of data leakage. File deduplication (shared file IDs via hash) is handled correctly through relationship-based authorization. 19 reviewers, strong consensus: the fix is correct and proportional.

2 P3, 1 Nit.

"Oh, this is a clean stone." (Bisky)

Pre-existing observation: GetFileByID at line 1576 loads the full file (including binary data) before any authorization check. A cross-org probe allocates memory for the entire archive, then discards it on rejection. Not introduced by this PR; the metadata check was already after the load. Worth knowing if module archives grow large and cross-org probing becomes a concern.

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/database/queries/templateversionterraformvalues.sql
Comment thread coderd/provisionerdserver/provisionerdserver.go
Comment thread coderd/provisionerdserver/download_file_test.go Outdated
sreya added 2 commits June 23, 2026 22:32
…d fix

Add a debug-level log before the org-isolation rejection so operators have a
breadcrumb without leaking file existence to the calling provisioner. Move the
DownloadFile regression test into provisionerdserver_test.go and rename it to
TestDownloadFile to match the existing per-RPC test naming.
@sreya

sreya commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

/coder-agents-review

@sreya
sreya requested a review from johnstcn June 23, 2026 23:06

@coder-agents-review coder-agents-review 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.

Further review is blocked until the following findings receive a response. The full review panel will not re-run until these are addressed, acknowledged, or contested.

CRF-1 (P3, templateversionterraformvalues.sql:37): No index on cached_module_files. The thread was resolved without a code change or explanation. If the index is intentionally omitted (table is small enough at expected scale), please say so. If a follow-up is planned, file a ticket. Otherwise, add the partial index in a migration.

CRF-3 (Nit, provisionerdserver_test.go:5540): crypto/rand.Read error check is dead code since Go 1.24. The test was moved from download_file_test.go to provisionerdserver_test.go, but the pattern persists at lines 5540 and 5574. GitHub marked the thread as outdated due to the file move; the finding's substance was not addressed.

CRF-2 (diagnostic log) was addressed: Warn-level log added in 5943884.

🤖 This review was automatically generated with Coder Agents.

@sreya

sreya commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

/coder-agents-review

@coder-agents-review coder-agents-review 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.

All prior findings resolved. CRF-2 (diagnostic log) and CRF-3 (dead error check) fixes verified by all 9 reviewers. CRF-1 (missing index) accepted by human author citing migration lock risk.

The security boundary is correctly implemented: org check runs before data streaming, error is opaque to prevent cross-org file existence probing, and tests verify both rejection and absence of data leakage. Komugi stress-tested with -race -count=20 -parallel=16 at GOMAXPROCS=2: no races.

"The two-query flow runs outside a transaction. This is safe: cached_module_files is write-once (INSERT only, no UPDATE queries exist), and the FK uses default RESTRICT, preventing file deletion while referenced. A concurrent template_version CASCADE delete would make the org check return false, which is a safe rejection, not a false approval." (Knuckle)

🤖 This review was automatically generated with Coder Agents.

Comment thread coderd/database/dbauthz/dbauthz.go Outdated
Comment thread coderd/provisionerdserver/provisionerdserver_test.go Outdated
…rg and use real DRPC stream in test

Switch the HasTemplateVersionsUsingCachedModuleFileInOrg authorization from
ResourceSystem to ResourceFile.InOrg, a least-privilege check that the caller
can read files in the target organization. Replace the hand-rolled
DownloadFile mock stream with a real in-memory DRPC client/server pipe and the
production HandleReceivingDataUpload reassembly path.
@sreya
sreya merged commit 1961908 into main Jun 24, 2026
29 of 30 checks passed
@sreya
sreya deleted the provisionerd-server-download branch June 24, 2026 17:09
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants