-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add proxy extension #1
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 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Signed-off-by: kryptocodes <srivatsantb@gmail.com>
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,87 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Bright Data Proxy Extension - API Configured | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const CONFIG_URL = "http://127.0.0.1:10001/proxy/config"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let proxyConfig = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Fetch proxy configuration from API | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function fetchProxyConfig() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await fetch(CONFIG_URL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!response.ok) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("Failed to fetch proxy config:", response.status); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return await response.json(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error("Error fetching proxy config:", error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+20
to
+33
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. Avoid clearing proxy settings on transient API failures. Any fetch error currently returns 🛠️ Suggested fix async function fetchProxyConfig() {
try {
const response = await fetch(CONFIG_URL);
- if (!response.ok) {
- console.error("Failed to fetch proxy config:", response.status);
- return null;
- }
+ if (response.status === 404 || response.status === 204) {
+ return null; // explicitly disabled
+ }
+ if (!response.ok) {
+ console.error("Failed to fetch proxy config:", response.status);
+ return undefined;
+ }
return await response.json();
} catch (error) {
console.error("Error fetching proxy config:", error);
- return null;
+ return undefined;
}
}
async function checkAndApplyConfig() {
const config = await fetchProxyConfig();
+ if (config === undefined) return;
const newHash = hashConfig(config);
const stored = await chrome.storage.local.get(["lastConfigHash"]);Also applies to: 76-85 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Apply proxy settings | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function applyProxySettings(config) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!config || !config.host || !config.port) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("No valid proxy config, disabling proxy"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chrome.proxy.settings.clear({ scope: "regular" }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| proxyConfig = config; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chrome.proxy.settings.set({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mode: "fixed_servers", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rules: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| singleProxy: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scheme: config.scheme || "http", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| host: config.host, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| port: config.port | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bypassList: config.bypassList || ["localhost", "127.0.0.1"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| scope: "regular" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Proxy configured:", config.host + ":" + config.port); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+48
to
+74
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. Validate proxy port before applying settings.
✅ Proposed validation await chrome.storage.local.set({ proxyConfig: config, lastConfigHash: hashConfig(config) });
cachedCredentials = config;
+ const port = Number.parseInt(config.port, 10);
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
+ console.error("Invalid proxy port:", config.port);
+ return;
+ }
+
chrome.proxy.settings.set({
value: {
mode: "fixed_servers",
rules: {
singleProxy: {
scheme: config.scheme || "http",
host: config.host,
- port: parseInt(config.port, 10)
+ port
},
bypassList: config.bypassList || ["localhost", "127.0.0.1"]
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Handle proxy authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chrome.webRequest.onAuthRequired.addListener( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| (details, callbackFn) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (proxyConfig && proxyConfig.username && proxyConfig.password) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Auth required, providing credentials"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callbackFn({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| authCredentials: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| username: proxyConfig.username, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| password: proxyConfig.password | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Auth required but no credentials available"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callbackFn({ cancel: false }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { urls: ["<all_urls>"] }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ["asyncBlocking"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
93
to
121
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🌐 Web query:
💡 Result: In
Notes:
Citations:
🏁 Script executed: # Check if there are any existing security checks in the codebase
rg -i "isProxy|challenger" brightdata-proxy-extension/Repository: reclaimprotocol/popcorn-images Length of output: 56 🏁 Script executed: # Look for any comments or documentation about auth handling
rg -i "auth|credential" brightdata-proxy-extension/background.js -A 2 -B 2Repository: reclaimprotocol/popcorn-images Length of output: 575 🏁 Script executed: rg "proxyConfig\s*=" brightdata-proxy-extension/background.js -B 3 -A 3Repository: reclaimprotocol/popcorn-images Length of output: 367 🏁 Script executed: rg "proxyConfig" brightdata-proxy-extension/background.js -B 2 -A 2 | head -40Repository: reclaimprotocol/popcorn-images Length of output: 615 🏁 Script executed: rg "proxyConfig\." brightdata-proxy-extension/background.js | sort | uniqRepository: reclaimprotocol/popcorn-images Length of output: 227 🏁 Script executed: # Look for the config object structure or where it's used
rg "config\." brightdata-proxy-extension/background.js -B 2 -A 2 | head -50Repository: reclaimprotocol/popcorn-images Length of output: 646 Restrict auth handling to proxy challenges to prevent credential leakage.
🔒 Suggested hardening chrome.webRequest.onAuthRequired.addListener(
(details, callbackFn) => {
+ if (!details.isProxy) {
+ callbackFn({ cancel: false });
+ return;
+ }
+ if (proxyConfig?.host && details.challenger?.host && details.challenger.host !== proxyConfig.host) {
+ callbackFn({ cancel: false });
+ return;
+ }
if (proxyConfig && proxyConfig.username && proxyConfig.password) {
console.log("Auth required, providing credentials");
callbackFn({
authCredentials: {
username: proxyConfig.username,
password: proxyConfig.password
}
});
} else {
console.log("Auth required but no credentials available");
callbackFn({ cancel: false });
}
},
{ urls: ["<all_urls>"] },
["asyncBlocking"]
);🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Initialize and poll for config changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async function init() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const config = await fetchProxyConfig(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (config) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| applyProxySettings(config); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Poll for config changes every 30 seconds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setInterval(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const config = await fetchProxyConfig(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (config && JSON.stringify(config) !== JSON.stringify(proxyConfig)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Proxy config changed, updating..."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| applyProxySettings(config); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, 30000); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log("Bright Data Proxy Extension loaded (API-configured)"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "name": "Bright Data Proxy Auth", | ||
| "version": "1.0.0", | ||
| "manifest_version": 3, | ||
| "description": "Proxy authentication for Bright Data", | ||
| "permissions": [ | ||
| "proxy", | ||
| "webRequest", | ||
| "webRequestAuthProvider" | ||
| ], | ||
| "host_permissions": [ | ||
| "<all_urls>" | ||
| ], | ||
| "background": { | ||
| "service_worker": "background.js" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,138 @@ | ||||||||||||||||||||||||||||||||||||||
| package api | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||
| "encoding/json" | ||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||
| "sync" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| "github.com/onkernel/kernel-images/server/lib/logger" | ||||||||||||||||||||||||||||||||||||||
| oapi "github.com/onkernel/kernel-images/server/lib/oapi" | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const proxyConfigPath = "/chromium/proxy-config.json" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| var ( | ||||||||||||||||||||||||||||||||||||||
| proxyConfigMu sync.RWMutex | ||||||||||||||||||||||||||||||||||||||
| proxyConfig *oapi.ProxyConfig | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // GetProxyConfig returns the current proxy configuration. | ||||||||||||||||||||||||||||||||||||||
| func (s *ApiService) GetProxyConfig(ctx context.Context, _ oapi.GetProxyConfigRequestObject) (oapi.GetProxyConfigResponseObject, error) { | ||||||||||||||||||||||||||||||||||||||
| log := logger.FromContext(ctx) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| proxyConfigMu.RLock() | ||||||||||||||||||||||||||||||||||||||
| defer proxyConfigMu.RUnlock() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // If we have a cached config, return it | ||||||||||||||||||||||||||||||||||||||
| if proxyConfig != nil { | ||||||||||||||||||||||||||||||||||||||
| log.Info("returning cached proxy config", "host", stringVal(proxyConfig.Host)) | ||||||||||||||||||||||||||||||||||||||
| return oapi.GetProxyConfig200JSONResponse(*proxyConfig), nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Try to load from file | ||||||||||||||||||||||||||||||||||||||
| data, err := os.ReadFile(proxyConfigPath) | ||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||
| if os.IsNotExist(err) { | ||||||||||||||||||||||||||||||||||||||
| // Return empty config if file doesn't exist | ||||||||||||||||||||||||||||||||||||||
| log.Info("no proxy config found, returning empty config") | ||||||||||||||||||||||||||||||||||||||
| return oapi.GetProxyConfig200JSONResponse(oapi.ProxyConfig{}), nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to read proxy config", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.GetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to read proxy config"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| var cfg oapi.ProxyConfig | ||||||||||||||||||||||||||||||||||||||
| if err := json.Unmarshal(data, &cfg); err != nil { | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to parse proxy config", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.GetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to parse proxy config"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| log.Info("returning proxy config from file", "host", stringVal(cfg.Host)) | ||||||||||||||||||||||||||||||||||||||
| return oapi.GetProxyConfig200JSONResponse(cfg), nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // SetProxyConfig sets the proxy configuration. | ||||||||||||||||||||||||||||||||||||||
| func (s *ApiService) SetProxyConfig(ctx context.Context, request oapi.SetProxyConfigRequestObject) (oapi.SetProxyConfigResponseObject, error) { | ||||||||||||||||||||||||||||||||||||||
| log := logger.FromContext(ctx) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if request.Body == nil { | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "request body required"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| cfg := request.Body | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Validate required fields | ||||||||||||||||||||||||||||||||||||||
| if cfg.Host == nil || *cfg.Host == "" { | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "host is required"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| if cfg.Port == nil || *cfg.Port == 0 { | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "port is required"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+65
to
+71
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. Validate proxy port range (1–65535). Line 69 accepts negative or >65535 ports, which will serialize but fail downstream. Add a range check. ✅ Proposed fix- if cfg.Port == nil || *cfg.Port == 0 {
+ if cfg.Port == nil || *cfg.Port < 1 || *cfg.Port > 65535 {
return oapi.SetProxyConfig400JSONResponse{BadRequestErrorJSONResponse: oapi.BadRequestErrorJSONResponse{Message: "port is required"}}, nil
}🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Set default scheme if not provided | ||||||||||||||||||||||||||||||||||||||
| if cfg.Scheme == nil { | ||||||||||||||||||||||||||||||||||||||
| defaultScheme := oapi.Http | ||||||||||||||||||||||||||||||||||||||
| cfg.Scheme = &defaultScheme | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Set default bypass list if not provided | ||||||||||||||||||||||||||||||||||||||
| if cfg.BypassList == nil { | ||||||||||||||||||||||||||||||||||||||
| cfg.BypassList = &[]string{"localhost", "127.0.0.1"} | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| proxyConfigMu.Lock() | ||||||||||||||||||||||||||||||||||||||
| defer proxyConfigMu.Unlock() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Save to file | ||||||||||||||||||||||||||||||||||||||
| data, err := json.MarshalIndent(cfg, "", " ") | ||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to marshal proxy config", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to marshal proxy config"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Ensure the directory exists | ||||||||||||||||||||||||||||||||||||||
| if err := os.MkdirAll("/chromium", 0o755); err != nil { | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to create chromium dir", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to create chromium dir"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if err := os.WriteFile(proxyConfigPath, data, 0o644); err != nil { | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to write proxy config", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to write proxy config"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+95
to
+103
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. Restrict proxy config file permissions to protect credentials. Line 100 writes with 🔐 Proposed fix- if err := os.WriteFile(proxyConfigPath, data, 0o644); err != nil {
+ if err := os.WriteFile(proxyConfigPath, data, 0o600); err != nil {
log.Error("failed to write proxy config", "error", err)
return oapi.SetProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to write proxy config"}}, nil
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Update cache | ||||||||||||||||||||||||||||||||||||||
| proxyConfig = cfg | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| log.Info("proxy config saved", "host", *cfg.Host, "port", *cfg.Port) | ||||||||||||||||||||||||||||||||||||||
| return oapi.SetProxyConfig200JSONResponse(*cfg), nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // DeleteProxyConfig clears the proxy configuration. | ||||||||||||||||||||||||||||||||||||||
| func (s *ApiService) DeleteProxyConfig(ctx context.Context, _ oapi.DeleteProxyConfigRequestObject) (oapi.DeleteProxyConfigResponseObject, error) { | ||||||||||||||||||||||||||||||||||||||
| log := logger.FromContext(ctx) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| proxyConfigMu.Lock() | ||||||||||||||||||||||||||||||||||||||
| defer proxyConfigMu.Unlock() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Clear cache | ||||||||||||||||||||||||||||||||||||||
| proxyConfig = nil | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // Remove file | ||||||||||||||||||||||||||||||||||||||
| if err := os.Remove(proxyConfigPath); err != nil && !os.IsNotExist(err) { | ||||||||||||||||||||||||||||||||||||||
| log.Error("failed to remove proxy config file", "error", err) | ||||||||||||||||||||||||||||||||||||||
| return oapi.DeleteProxyConfig500JSONResponse{InternalErrorJSONResponse: oapi.InternalErrorJSONResponse{Message: "failed to remove proxy config file"}}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| log.Info("proxy config cleared") | ||||||||||||||||||||||||||||||||||||||
| return oapi.DeleteProxyConfig204Response{}, nil | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // stringVal returns the value of a string pointer or empty string if nil | ||||||||||||||||||||||||||||||||||||||
| func stringVal(s *string) string { | ||||||||||||||||||||||||||||||||||||||
| if s == nil { | ||||||||||||||||||||||||||||||||||||||
| return "" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return *s | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
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.
Fix table divider spacing to satisfy markdownlint MD060.
✅ Proposed formatting fix
📝 Committable suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)
181-181: Table column style
Table pipe is missing space to the right for style "compact"
(MD060, table-column-style)
181-181: Table column style
Table pipe is missing space to the left for style "compact"
(MD060, table-column-style)
181-181: Table column style
Table pipe is missing space to the right for style "compact"
(MD060, table-column-style)
181-181: Table column style
Table pipe is missing space to the left for style "compact"
(MD060, table-column-style)
🤖 Prompt for AI Agents