fix: improve Blueprint asset handling#1713
Conversation
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 44 minutes and 52 seconds.Comment |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
8792b58 to
6b956dc
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@meteor/server/api/blueprints/api.ts`:
- Around line 134-138: The path traversal check in api.ts using assetsDir and
assetPath can be bypassed via sibling directory names; update the validation in
the asset lookup code to resolve real filesystem paths (use fs.realpath or
fs.realpathSync on assetsDir and assetPath), then compute
path.relative(assetsDirReal, assetPathReal) and reject the request if the
relative path starts with '..' or is equal to '..' (and also reject if
path.isAbsolute(relative) is true); ensure you reference the existing assetsDir,
assetPath and fileId variables and perform this stronger check before serving
the file.
- Around line 115-119: The current path traversal check using
assetPath.startsWith(assetsDir) is bypassable; update the containment check for
assetsDir/assetPath (where assetsDir, assetPath, fileId are used) to a robust
sibling-safe test — for example compute path.relative(assetsDir, assetPath) and
reject if it begins with '..' or equals ''/'. Ensure you normalize/resolved both
paths first (using path.resolve) and use a path separator-aware comparison (or
ensure the relative result is not outside the asset directory) before allowing
access.
In `@meteor/server/api/blueprints/http.ts`:
- Around line 203-210: The catch block in the HTTP handler currently returns 501
for retrieval failures; change the logic to return a proper status: detect
path-traversal errors thrown by retrieveBlueprintAsset (e instanceof Error &&
/path[\s-]*traversal/i.test(e.message) or another identifying message) and set
ctx.statusCode = 403 (and log via logger.warn including the error), treat
missing file (e.code === 'ENOENT') as 404 as existing, and for any other
unexpected errors set ctx.statusCode = 500 and log the full error with
logger.error; update the logger messages in this block to include the error
details and use the symbols retrieveBlueprintAsset, logger.warn/logger.error,
and ctx.statusCode to find the code.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: de827cc1-924c-47b8-bff5-fad590cbe226
📒 Files selected for processing (4)
meteor/server/api/blueprints/api.tsmeteor/server/api/blueprints/http.tspackages/webui/src/client/lib/Components/BlueprintAssetIcon.tsxpackages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx
6b956dc to
87ca6b1
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
meteor/server/api/blueprints/http.ts (1)
203-213:⚠️ Potential issue | 🟠 MajorUse correct status codes for traversal and unexpected failures.
Line 212 returning
501is semantically wrong here; retrieval runtime failures should be500, and traversal attempts (Line 207-209) should be403. Also, unexpected failures should log withlogger.errorto preserve incident visibility.Suggested patch
} catch (e) { if (e instanceof Error && 'code' in e && e.code === 'ENOENT') { logger.warn('Blueprint asset not found: ' + e) ctx.statusCode = 404 } else if (e instanceof Error && e.message.includes('outside of asset storage path')) { logger.warn('Blueprint asset path traversal attempt: ' + e) - ctx.statusCode = 400 + ctx.statusCode = 403 } else { - logger.warn('Blueprint asset retrieval failed: ' + e) - ctx.statusCode = 501 + logger.error('Blueprint asset retrieval failed: ' + e) + ctx.statusCode = 500 } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@meteor/server/api/blueprints/http.ts` around lines 203 - 213, In the catch block in meteor/server/api/blueprints/http.ts that handles blueprint asset retrieval (the try/catch around asset reads), change the response codes and logging as follows: keep the ENOENT branch returning 404 with logger.warn, change the "outside of asset storage path" branch (path traversal) to set ctx.statusCode = 403 and use logger.warn, and change the final fallback branch to set ctx.statusCode = 500 and call logger.error instead of logger.warn so unexpected runtime failures are logged as errors.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@meteor/server/api/blueprints/http.ts`:
- Around line 203-213: In the catch block in
meteor/server/api/blueprints/http.ts that handles blueprint asset retrieval (the
try/catch around asset reads), change the response codes and logging as follows:
keep the ENOENT branch returning 404 with logger.warn, change the "outside of
asset storage path" branch (path traversal) to set ctx.statusCode = 403 and use
logger.warn, and change the final fallback branch to set ctx.statusCode = 500
and call logger.error instead of logger.warn so unexpected runtime failures are
logged as errors.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: eb595e1b-a934-4ee6-846b-18ba69f039d7
📒 Files selected for processing (4)
meteor/server/api/blueprints/api.tsmeteor/server/api/blueprints/http.tspackages/webui/src/client/lib/Components/BlueprintAssetIcon.tsxpackages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx
✅ Files skipped from review due to trivial changes (1)
- packages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/webui/src/client/lib/Components/BlueprintAssetIcon.tsx
- meteor/server/api/blueprints/api.ts
87ca6b1 to
620ad0a
Compare
08aeebd to
e9300e5
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
meteor/server/api/blueprints/api.ts (1)
115-119:⚠️ Potential issue | 🟠 Major
startsWith()still doesn't stop symlink escapes.This only constrains the lexical path. If a symlink already exists anywhere under
assets/, afileIdlikelinked-dir/file.pngstill passes the prefix check whilewriteFile/createReadStreamfollow the symlink outside the asset root. Please canonicalize withrealpathand compare withpath.relative(...)against the canonical asset directory before reading or writing.Also applies to: 134-138
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@meteor/server/api/blueprints/api.ts` around lines 115 - 119, The current prefix check using assetsDir and assetPath can be bypassed by symlinks; replace the lexical check in the asset lookup/write paths (references: assetsDir, assetPath, fileId) with a canonicalization-based check: resolve the real paths using fs.promises.realpath (or fs.realpathSync) for both the assets directory and the target asset path, then compute path.relative(realAssetsDir, realAssetPath) and throw if the result starts with '..' or is equal to '..' (or if the relative path is absolute), ensuring you perform this canonical check in both places that currently use startsWith (the asset read path and the asset write path).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@meteor/server/api/blueprints/api.ts`:
- Around line 115-119: The current prefix check using assetsDir and assetPath
can be bypassed by symlinks; replace the lexical check in the asset lookup/write
paths (references: assetsDir, assetPath, fileId) with a canonicalization-based
check: resolve the real paths using fs.promises.realpath (or fs.realpathSync)
for both the assets directory and the target asset path, then compute
path.relative(realAssetsDir, realAssetPath) and throw if the result starts with
'..' or is equal to '..' (or if the relative path is absolute), ensuring you
perform this canonical check in both places that currently use startsWith (the
asset read path and the asset write path).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0d245aff-507f-4ff0-85ba-b6f9cbfab1fd
📒 Files selected for processing (6)
meteor/server/api/blueprints/__tests__/api.test.tsmeteor/server/api/blueprints/__tests__/http.test.tsmeteor/server/api/blueprints/api.tsmeteor/server/api/blueprints/http.tspackages/webui/src/client/lib/Components/BlueprintAssetIcon.tsxpackages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx
✅ Files skipped from review due to trivial changes (1)
- packages/webui/src/client/lib/Components/BlueprintAssetIcon.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/webui/src/client/ui/PreviewPopUp/PreviewPopUpContext.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@meteor/server/api/blueprints/http.ts`:
- Around line 203-213: The try/catch can't catch async stream errors from
retrieveBlueprintAsset (which calls createReadStream), so change the response
flow to wait for the stream to open and handle its 'error' event before
assigning to ctx.body: call retrieveBlueprintAsset to get the ReadStream, attach
a one-time 'error' handler that maps ENOENT to ctx.statusCode=404,
path-traversal messages to 400 and other errors to 500, and attach a one-time
'open' handler (or use stream.promises/stream.finished) to only set ctx.body =
stream once the stream is ready; also remove reliance on synchronous exceptions
in the try/catch around retrieveBlueprintAsset and ensure any stream errors
clean up the stream and don't leak unhandled exceptions.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e6cc3915-3575-4d7b-9807-fb610fdf3b54
📒 Files selected for processing (5)
meteor/server/api/blueprints/__tests__/api.test.tsmeteor/server/api/blueprints/__tests__/http.test.tsmeteor/server/api/blueprints/api.tsmeteor/server/api/blueprints/http.tspackages/webui/src/client/lib/Components/BlueprintAssetIcon.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/webui/src/client/lib/Components/BlueprintAssetIcon.tsx
- meteor/server/api/blueprints/api.ts
- meteor/server/api/blueprints/tests/http.test.ts
- meteor/server/api/blueprints/tests/api.test.ts
…result in the assets route
About the Contributor
Type of Contribution
This is a:
Bug fix
Current Behavior
Blueprint assets can be stored in invalid locations, it's possible to use directory traversal attacks to read and write files using the Blueprint API, upload/download failures result in obscure errors. Blueprint asset URLs contain double slashes.
New Behavior
The simplest error (Not found) is correctly reported, directory traversal is not possible beyond Blueprint asset directory.
Testing
Affected areas
This PR affects Blueprint asset API
Time Frame
We intend to finish the development on this feature in two weeks time.
Other Information
Status