Skip to content

Security Enhancements - #272

Open
Shashwat803 wants to merge 327 commits into
Netflix-Skunkworks:masterfrom
goSprinto:fix/security-issue-shashwatmishra-final
Open

Security Enhancements #272
Shashwat803 wants to merge 327 commits into
Netflix-Skunkworks:masterfrom
goSprinto:fix/security-issue-shashwatmishra-final

Conversation

@Shashwat803

Copy link
Copy Markdown

Overview

Changes Made

1. Enhanced DLL Security in start.js

// Added secure DLL search paths and safe loading mode
if (IS_WIN) {
  app.setPath('module', path.join(app.getAppPath(), 'node_modules'));
  
  app.on('ready', () => {
    const trustedPaths = [
      app.getAppPath(),
      path.join(app.getAppPath(), 'node_modules'),
      path.join(app.getPath('exe'), '..'),
    ];
    
    trustedPaths.forEach(trustedPath => {
      app.addPath('module', trustedPath);
    });
  });
}

2. Added app.manifest for Windows Security

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="*"
    name="DrSprinto.App"
    type="win32"
  />
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware>true</dpiAware>
      <longPathAware>true</longPathAware>
      <heapType>SegmentHeap</heapType>
    </windowsSettings>
  </application>
</assembly>

3. Updated package.json Build Configuration

{
  "build": {
    "win": {
      "signAndEditExecutable": true,
      "signDlls": true,
      "requestedExecutionLevel": "asInvoker",
      "manifestPath": "app.manifest",
      "rfc3161TimeStampServer": "http://timestamp.digicert.com"
    },
    "nsis": {
      "oneClick": false,
    }
  }
}

4. Implemented comprehensive CSP to protect against XSS and injection attacks:

<meta http-equiv="Content-Security-Policy" content="
  default-src 'self';
  script-src 'self' 'unsafe-eval' http://127.0.0.1:37370;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  connect-src 'self' http://127.0.0.1:37370 ws://127.0.0.1:37370;
  font-src 'self';
  object-src 'none';
  media-src 'self';
  frame-src 'none';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  upgrade-insecure-requests;
  block-all-mixed-content;
">

5. Permission and Navigation Controls (src/start.js)

Added permission handling and navigation security:

// Permission request handler
session.defaultSession.setPermissionRequestHandler((webContents, permission, callback, details) => {
  const url = details.requestingUrl;
  const trustedOrigins = ['drsprinto://', 'file://', 'http://localhost:', 'https://sprinto.com'];
  
  // Only allow permissions from trusted origins
  const isTrusted = trustedOrigins.some(origin => url.startsWith(origin));
  
  if (!isTrusted) {
    log.warn(`Blocked permission request from untrusted origin: ${url}`);
    callback(false);
    return;
  }
});

// Permission check handler
session.defaultSession.setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
  const trustedOrigins = ['drsprinto://', 'file://', 'http://localhost:', 'https://sprinto.com'];
  return trustedOrigins.some(origin => requestingOrigin.startsWith(origin));
});

6. Protocol Handler Security (src/lib/protocolHandlers.js)

Enhanced security for all protocol handlers:

// URL validation utility
const validateAndSanitizeUrl = (url, protocol) => {
  try {
    const decodedUrl = decodeURIComponent(url);
    const urlWithoutProtocol = decodedUrl.replace(`${protocol}://`, '');
    return urlWithoutProtocol.replace(/[^\w\-\.\s]/g, '');
  } catch (e) {
    log.error(`Invalid URL format: ${e.message}`);
    return null;
  }
};

// Secure protocol handlers
protocol.registerHttpProtocol('link', (request, cb) => {
  const url = request.url.replace('link://', '');
  if (isTrustedUrl(url)) {
    shell.openExternal(url);
  } else {
    log.warn(`Blocked untrusted URL in link protocol: ${url}`);
  }
});

7. URL Validation Utility (src/lib/isTrustedUrl.js)

Created a centralized URL validation function:

export function isTrustedUrl(urlString) {
  try {
    const url = new URL(urlString);
    
    const allowedProtocols = ['https:', 'http:', 'file:', 'drsprinto:'];
    if (!allowedProtocols.includes(url.protocol)) {
      return false;
    }

    const allowedDomains = ['sprinto.com', 'localhost', '127.0.0.1'];
    return allowedDomains.some(domain => 
      url.hostname === domain || url.hostname.endsWith(`.${domain}`)
    );
  } catch (err) {
    console.error('Invalid URL:', err);
    return false;
  }
}

8. Added the following resolutions to package.json:

"resolutions": {
  "string-width": "^4.2.0",
  "wrap-ansi": "^7.0.0",
  "nanoid": "^3.3.8",
  "path-to-regexp": "^6.2.1"
}

9. Build Configuration (package.json)

     "linux": {
       "extraResources": [
         "src/practices"
       ],
      "buildFlags": [
        "-Wl,-z,relro,-z,now,-z,noexecstack"
      ]
     },

10. Runtime Security (src/start.js)

if (process.platform === 'linux') {
  // Use absolute paths for libraries
  const absoluteLibPath = path.resolve(app.getAppPath(), 'lib');
  
  // Set DT_RUNPATH instead of DT_RPATH
  process.env.LD_RUN_PATH = absoluteLibPath;
}

11. Added permission request handler that:

app.on("ready", () => {
  session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
    const url = webContents.getURL();
    const trustedOrigins = ["drsprinto://", "file://", "http://localhost:"]; 
    const { hostname } = new URL(url);
    const isTrusted = trustedOrigins.some(origin => url.startsWith(origin)) || 
                     hostname.endsWith('.sprinto.com');
    
    if (isTrusted) {
      callback(true);
    } else {
      console.log(`Permission '${permission}' denied for URL: ${url}`);
      callback(false);
    }
  });
});

Abhaya Agarwal and others added 30 commits May 22, 2021 09:56
- Add a button to open the status recording page in Sprinto app
- Add the api endpoint to record the time of last successful status
recording
- Rework the UI to match Sprinto colors
Manoj Jadhav and others added 30 commits January 18, 2025 09:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants