Skip to content

Extension Security

1. Using Strict Content Security Policies.

Writing stricter Content Security Policies (CSPs) for Google Chrome Extensions helps enhance security by preventing Cross-Site Scripting (XSS) and other code injection attacks. Stricter CSP's limits the sources from which the content can be loaded.

  • Chrome Extensions run in privileged contexts. A compromised extension can:

  • Access sensitive browser APIs.

  • Steal user data.

  • Execute arbitrary code.

For MV3, the default CSP is:

  "content_security_policy": {
  "extension_pages": "script-src 'self'; object-src 'self'"
  }

This is stricter than MV2 (which often allowed unsafe-eval) but can still be tightened further.

  • Ways to tigthen CSPs:

    1. Disallow Inline Scripts

    2. Restrict img-src, media-src, and others

    "content_security_policy": { "extension_pages": "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; object-src 'none';" } Explanation:

    default-src 'none': blocks all by default

    cript-src 'self': only allow internal JS

    connect-src 'self': allow fetch/XHR to self

    img-src 'self': only internal images

    style-src 'self': disallow inline styles and external stylesheets

    object-src 'none': completely block plugins

2. Minimizing Permissions

Minimizing permissions in a Google Chrome extension is crucial for security because of the privileged access that extensions can have to a user's browser and data.

  1. Reducing Attack Surface:
    • Every permission that is granted is a potential entry point for an attacker.
    • Fewer permissions means less ways for bad actors to exploit the extension.

2.Preventing Privelege Escalation: In a compromised extension, excessive permissions can let the attacker: * Access sensitive data (emails, cookies, bookmarks) * Control browser actions * Manipulate web requests * Restricting permissions helps contain damage.

  1. Easier Maintenance and Auditing With fewer permissions:
    • Code reviews are simpler
    • Security audits are faster
    • It's easier to reason about what the extension is allowed to do
       Best Practices:                                 |   Why it helps:
       Use host_permissions selectively            |   Don’t request <all_urls> unless necessary. Use specific domains.
       Use optional permissions (optional_permissions) |   Only request permissions when needed, and ask at runtime.
       Avoid persistent background scripts if possible |   Use service workers (Manifest V3) to reduce runtime exposure.
       Use declarative APIs (declarativeNetRequest)    |   Safer than webRequest, which can expose full request/response data.
       Audit permissions regularly                     |   Refactor or remove unnecessary permissions as features change.
      

3. Regular Updates and Monitoring

For depveloperes it is very important to patch any newly found vulnerabilities promptly.

  1. Monitor security advisories (e.g., Chromium Blog, CVE databases) for:

     * JavaScript vulnerabilities
     * Extension API changes
     * Third-party library issues
    
     Fix identified issues immediately!
    

    2.Updating Manifest and Dependencies:

     * Ensure you're using the latest stable Manifest version (Manifest V3 is currently required).
     * Reghularly udpate and audit third-party libraries
    
       You can use tools like "npm audit" or "Snyk"
    

    3.Use Semantic Versioning:

     * What is Semantic Versioning?
    
     Semantic Versioning (SemVer) is a structured way to version software using a three-part number:
    
        MAJOR.MINOR.PATCH 
     For Example:
    
        1.4.2
    
     Each segment conveys meaning about the update's impact:
    
     | Segment   | When to Increment         | Description                                                              |
     | --------- | ------------------------- | ------------------------------------------------------------------------ |
     | **MAJOR** | Breaking changes          | Incompatible API or behavior changes                                     |
     | **MINOR** | New features              | Backward-compatible feature additions                                    |
     | **PATCH** | Bug fixes / small changes | Backward-compatible fixes, performance improvements, or security patches |
    
     * The use of SemVer in Extensions:
    
        * Helps users know what kind of changes to expect.
        * Makes it easier for Google reviewers to track meaningful updates.
    
     * Helps Security Patch management:
    
        * Clear PATCH version increases make it easier to distinguish security updates from new features.
    
     * Aids in Automation:
    
        * Automated deployment tools and CI/CD pipelines can detect when to trigger updates based on version increments.
    

    How to Apply Semantic Versioning in Your Extension?:

     1. Update manifest.json version
    
              "version": "2.3.1"
    
        This is required by Chrome and is the official version used for auto-updates.
    
     2. Match It with CHANGELOG.md
    
              ## [2.3.1] - 2025-05-30
              ### Fixed
              - Patched a bug that caused login tokens to persist incorrectly.
              - Fixed performance issue in background script.
    
              ## [2.3.0] - 2025-05-25
              ### Added
              - New feature: Ability to export settings as JSON.
    
              ## [2.0.0] - 2025-05-01
              ### Changed
              - Switched from Manifest V2 to V3. This is a breaking change.
              - Dropped support for Chrome < 90.
    
     Make sure the logs are structure consistently.
    
     3. Version Bumping Strategy
    
           | Situation                               | New Version      | Why                             |
           | --------------------------------------- | ---------------- | ------------------------------- |
           | You fix a bug in a stable release       | `1.2.3 → 1.2.4`  | PATCH update                    |
           | You add a feature (e.g., dark mode)     | `1.2.3 → 1.3.0`  | MINOR update                    |
           | You migrate to Manifest V3              | `1.2.3 → 2.0.0`  | MAJOR update                    |
           | You fix a security vulnerability        | `1.3.2 → 1.3.3`  | PATCH update (critical)         |
           | You refactor internal code (no changes) | *No bump needed* | Optional, if behavior unchanged |
    
     4. Security Best Practices Using SemVer:
    
           | Action                           | Benefit                               |
           | -------------------------------- | ------------------------------------- |
           | Use PATCH for all security fixes | Easier to isolate and track in audits |
           | Avoid skipping MAJOR bumps       | Prevent breaking user experience      |
           | Communicate changes clearly      | Reduces user confusion/trust issues   |
           | Document deprecated features     | Helps manage risky transitions        |
    
     5. Automation Tools for SemVer5:
    
           | Tool                  | Use Case                      |
           | --------------------- | ----------------------------- |
           | **standard-version**  | Auto-bump version + changelog |
           | **semantic-release**  | Full CI-based release mgmt    |
           | **npm version patch** | Quick version bump            |
    

4. Monitoring – Code & Setup

  1. Capture and Report Errors:

    background.js

           self.onerror = function (message, source, lineno, colno, error) {
             fetch("https://your-logging-endpoint.com/log", {
               method: "POST",
               headers: {
                 "Content-Type": "application/json"
               },
               body: JSON.stringify({
                 message,
                 source,
                 lineno,
                 colno,
                 stack: error ? error.stack : null
               })
             });
           };
    

    This logs any uncaught errors in your background service worker.

    1. Log User Behavior (non-sensitive):

      Example: Track Feature Usage:

             function logFeatureUsage(featureName) {
              fetch("https://your-logging-endpoint.com/feature-usage", {
                method: "POST",
                body: JSON.stringify({ feature: featureName, time: Date.now() })
              });
            }
      
            // Usage
            logFeatureUsage("clicked_sync_button");
      

      Ensure you're not collecting PII (Personally Identifiable Information) without explicit user consent.

    2. Monitor for Malicious Behavior (e.g., Extension Hijack):

      Detect unexpected API usage or content injection:

            chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
              if (changeInfo.status === 'complete') {
                chrome.scripting.executeScript({
                  target: { tabId: tabId },
                  func: () => {
                    if (document.querySelector('iframe[src*="malicious-site.com"]')) {
                      alert('Suspicious iframe detected.');
                    }
                  }
                });
              }
            });
      
      1. Security Checklist (Code-Focused):

        Task Code Reference
        Use Manifest V3 manifest.json
        Remove inline scripts Move to external .js
        Enforce CSP "content_security_policy"
        Log errors securely fetch error handler
        Sanitize inputs sanitizeInput()
        Test core logic Jest/Mocha unit tests
        CI/CD pipeline GitHub Actions YAML
        Patch dependencies npm audit fix

5. Validate and Sanitize Input

  1. Why Input Sanitization & Validation Matter?

Chrome extensions often:

  • Accept user input (e.g., popup forms, options pages)
  • Inject content scripts into webpages
  • Make API calls and handle responses

Without sanitization/validation:

  • A user could inject