-
Notifications
You must be signed in to change notification settings - Fork 13
Install GitHub plugins when Git is unavailable #127
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 | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,15 @@ | ||||||||||||||||||||||||||||||||||||
| export const PLUGIN_SOURCE_FILE = '.feedback-plugin-source.json'; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| export function parseGitHubRepository(value: string): { owner: string; repo: string } | null { | ||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| const url = new URL(value); | ||||||||||||||||||||||||||||||||||||
| const parts = url.pathname.replace(/^\/+|\/+$/g, '').split('/'); | ||||||||||||||||||||||||||||||||||||
| if (url.protocol !== 'https:' || url.hostname.toLowerCase() !== 'github.com' || parts.length !== 2) return null; | ||||||||||||||||||||||||||||||||||||
| const owner = parts[0]; | ||||||||||||||||||||||||||||||||||||
| const repo = parts[1].replace(/\.git$/, ''); | ||||||||||||||||||||||||||||||||||||
| if (!/^[A-Za-z0-9_.-]+$/.test(owner) || !/^[A-Za-z0-9_.-]+$/.test(repo)) return null; | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+3
to
+10
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. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win Reject URLs containing credentials.
Proposed fix- if (url.protocol !== 'https:' || url.hostname.toLowerCase() !== 'github.com' || parts.length !== 2) return null;
+ if (url.protocol !== 'https:' || url.hostname.toLowerCase() !== 'github.com' ||
+ url.username || url.password || parts.length !== 2) return null;📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||
| return { owner, repo }; | ||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| const test = require('node:test'); | ||
| const assert = require('node:assert/strict'); | ||
| const { loadTs } = require('./_load-ts'); | ||
|
|
||
| const { parseGitHubRepository } = loadTs('src/main/plugin-source.ts'); | ||
|
|
||
| test('recognizes public GitHub repository URLs used by archive installs', () => { | ||
| assert.deepEqual(parseGitHubRepository('https://github.com/balki97/feedforge-connect'), { | ||
| owner: 'balki97', repo: 'feedforge-connect', | ||
| }); | ||
| assert.deepEqual(parseGitHubRepository('https://github.com/balki97/feedforge-connect.git'), { | ||
| owner: 'balki97', repo: 'feedforge-connect', | ||
| }); | ||
| assert.equal(parseGitHubRepository('https://example.com/balki97/feedforge-connect'), null); | ||
| assert.equal(parseGitHubRepository('file:///tmp/feedforge-connect'), null); | ||
| assert.equal(parseGitHubRepository('https://github.com/balki97/feedforge-connect/releases'), null); | ||
| }); |
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.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: got-feedBack/feedBack-desktop
Length of output: 258
🏁 Script executed:
Repository: got-feedBack/feedBack-desktop
Length of output: 1262
🏁 Script executed:
Repository: got-feedBack/feedBack-desktop
Length of output: 7702
🌐 Web query:
Node.js global fetch default timeout no abort controller arrayBuffer buffers entire response💡 Result:
In Node.js, the global fetch API—powered by undici—has a default timeout of 300 seconds [1][2][3]. This applies to both headers and the body, and is not a per-request configurable timeout in the traditional sense, but rather a default configuration within the undici dispatcher [1][2]. There is no global setting to change this default; to enforce a shorter timeout, the standard and recommended approach is to use AbortSignal.timeout passed within the fetch options [4][5][3]. Regarding arrayBuffer, calling response.arrayBuffer does indeed buffer the entire response body into memory [6]. The method is designed to read the response stream to completion and resolve with an ArrayBuffer containing the full data [6]. Because this process consumes the entire body into memory, it is not suitable for large payloads where memory efficiency is a concern; for large data, using the response body as a stream is the recommended approach [7][8].
Citations:
🏁 Script executed:
Repository: got-feedBack/feedBack-desktop
Length of output: 4792
Bound archive downloads.
installGitHubArchive()usesresponse.arrayBuffer()without any size limit and does not pass anAbortSignal, so stalled GitHub downloads can hang and large archives can block memory before being written to disk. Stream the archive to a temp file with a configurable byte limit and an abort timeout.🧰 Tools
🪛 ast-grep (0.45.0)
[warning] 86-86: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.writeFileSync(archivePath, Buffer.from(await response.arrayBuffer()))
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename-typescript)
🤖 Prompt for AI Agents