Skip to main content

Overview

The Permission Warnings API converts Chrome extension manifest permissions into human-readable warning messages. It implements Chromium’s permission warning logic to help users understand the security implications of installing extensions.
This implementation is derived from Chromium’s source code:
  • Rules logic: chrome/common/extensions/permissions/chrome_permission_message_rules.cc
  • Message strings: chrome/app/generated_resources.grd

Why Permission Warnings Matter

When users install browser extensions, they need to understand what capabilities they’re granting. Permission warnings:
  • Inform users about data access and browser capabilities
  • Prevent malicious extensions from gaining access without user awareness
  • Follow Chrome’s precedence rules for permission message priority
  • Group related permissions to avoid overwhelming users with too many warnings

API Reference

getPermissionWarnings()

Processes manifest permissions and generates user-facing warning messages.
function getPermissionWarnings(
  manifestPermissions: string[],
  hostPermissions?: string[]
): string[]

Parameters

  • manifestPermissions (string[]): Array of permission strings from manifest.json
    • Examples: ["tabs", "storage", "history", "bookmarks"]
  • hostPermissions (string[], optional): Array of host permission strings
    • Examples: ["<all_urls>", "https://*.google.com/*"]

Returns

  • string[]: Array of user-facing warning messages
See: modules/extensions/permission-warnings.ts:597

Usage Examples

Basic Permission Warnings

import { getPermissionWarnings } from "@/modules/extensions/permission-warnings";

// Extension with common permissions
const manifestPermissions = ["tabs", "storage", "history"];
const warnings = getPermissionWarnings(manifestPermissions);

console.log(warnings);
// Output:
// [
//   "Read your Browse history"
// ]

All Sites Permission

const manifestPermissions = ["tabs", "storage"];
const hostPermissions = ["<all_urls>"];

const warnings = getPermissionWarnings(
  manifestPermissions,
  hostPermissions
);

console.log(warnings);
// Output:
// [
//   "Read and change all your data on all websites"
// ]
The <all_urls> permission is one of the most powerful permissions. It allows extensions to:
  • Read and modify content on any website
  • Intercept network requests
  • Access sensitive user data
Always carefully review extensions requesting this permission.

Specific Host Permissions

const manifestPerms = ["tabs", "activeTab", "scripting"];
const hostPerms = [
  "https://www.google.com/*",
  "https://developer.chrome.com/*"
];

const warnings = getPermissionWarnings(manifestPerms, hostPerms);

console.log(warnings);
// Output:
// [
//   "Read your Browse history",
//   "Access your data on specific sites"
// ]

Chrome Web Store Integration

Flow Browser uses this API when displaying extension installation dialogs:
import { getPermissionWarnings } from "@/modules/extensions/permission-warnings";
import { dialog } from "electron";

await installChromeWebStore({
  beforeInstall: async (details) => {
    const manifest = details.manifest;
    
    // Get permission warnings
    const warnings = getPermissionWarnings(
      manifest.permissions || [],
      manifest.host_permissions || []
    );
    
    // Build permission message
    let message = `Add "${details.localizedName}"?`;
    
    if (warnings.length > 0) {
      message += "\n\nThis extension can:\n";
      warnings.forEach(warning => {
        message += `• ${warning}\n`;
      });
    }
    
    // Show dialog
    const result = await dialog.showMessageBox({
      title: "Install Extension",
      message,
      icon: details.icon,
      buttons: ["Cancel", "Add Extension"]
    });
    
    return { action: result.response === 0 ? "deny" : "allow" };
  }
});
See: loaded-profiles-controller/index.ts:230

Permission Categories

High-Impact Permissions

These permissions have the highest precedence and generate prominent warnings:
PermissionWarning Message
debuggerDebug extensions and pages
<all_urls>Read and change all your data on all websites
managementManage your apps, extensions, and themes

Browser Data Access

PermissionWarning Message
historyRead and change your Browse history on all your signed-in devices
tabsRead your Browse history
bookmarksRead and change your bookmarks
readingListRead and change your reading list
downloadsManage your downloads
downloads.openOpen files that you have downloaded

Clipboard and Input

PermissionWarning Message
clipboardRead + clipboardWriteRead and modify data you copy and paste
clipboardReadRead data you copy and paste
clipboardWriteModify data you copy and paste
inputMonitor keyboard input

Media Capture

PermissionWarning Message
audioCapture + videoCaptureCapture audio and video
audioCaptureCapture audio
videoCaptureCapture video
desktopCaptureCapture content of your screen

Location and Identity

PermissionWarning Message
geolocationDetect your physical location
identity.emailKnow your email address

Network and Connectivity

PermissionWarning Message
proxyRead and modify proxy settings
vpnProviderManage VPN connections
declarativeNetRequestBlock network requests
declarativeWebRequestBlock parts of web pages

Device Access

PermissionWarning Message
usbDevicesAccess USB devices
bluetooth + serialAccess Bluetooth and serial devices
bluetoothAccess Bluetooth devices
serialAccess serial devices
u2fDevicesAccess U2F security keys

Privacy and Settings

PermissionWarning Message
privacyChange privacy-related settings
contentSettingsChange settings that control websites’ access to features

Permission Precedence Rules

The API follows Chromium’s precedence rules:
  1. Higher-impact permissions suppress lower ones
    • <all_urls> absorbs many other permissions like tabs, webNavigation
    • Combined permissions generate a single warning
  2. Required and optional permissions
    • Each rule specifies required permissions that must all be present
    • Optional permissions are consumed if the rule matches
  3. First match wins
    • Rules are processed in order
    • Once a permission is consumed, it won’t trigger later rules
Example:
// These permissions...
const perms = ["tabs", "webNavigation", "<all_urls>"];

// Generate only ONE warning because <all_urls> absorbs the others:
const warnings = getPermissionWarnings(perms);
// ["Read and change all your data on all websites"]

// Instead of three separate warnings
See: modules/extensions/permission-warnings.ts:266

Advanced Examples

Content Script Permissions

// Extension with content scripts on specific sites
const manifest = {
  permissions: ["activeTab", "scripting"],
  host_permissions: [
    "https://github.com/*",
    "https://gitlab.com/*"
  ]
};

const warnings = getPermissionWarnings(
  manifest.permissions,
  manifest.host_permissions
);
// ["Access your data on specific sites"]

Extension with Multiple Capabilities

const permissions = [
  "tabs",
  "bookmarks",
  "history",
  "clipboardRead",
  "clipboardWrite",
  "notifications"
];

const warnings = getPermissionWarnings(permissions);
console.log(warnings);
// [
//   "Read and change your Browse history on all your signed-in devices",
//   "Read and change your bookmarks",
//   "Read and modify data you copy and paste",
//   "Display notifications"
// ]

Debugger Extension

const permissions = ["debugger", "tabs", "<all_urls>"];
const warnings = getPermissionWarnings(permissions);

console.log(warnings);
// ["Debug extensions and pages"]
// Note: This is a very high-privilege permission

Implementation Details

Permission Mapping

The module maintains mappings from manifest permission strings to internal permission IDs:
const permissionMapping: Record<string, string> = {
  kDebugger: "debugger",
  kTab: "tabs",
  kHistory: "history",
  kBookmark: "bookmarks",
  // ... many more
};
See: modules/extensions/permission-warnings.ts:133

Permission Messages

Messages are stored in a lookup table:
const permissionMessages: Record<string, string> = {
  IDS_EXTENSION_PROMPT_WARNING_HISTORY: 
    "Read and change your Browse history",
  IDS_EXTENSION_PROMPT_WARNING_TABS: 
    "Read your Browse history",
  IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS: 
    "Read and change your bookmarks",
  // ... hundreds more
};
See: modules/extensions/permission-warnings.ts:17

Host Permission Detection

The API detects specific host patterns:
function isSpecificHostPermission(permission: string): boolean {
  return permission.includes("://") || permission.startsWith("*");
}

// Examples:
isSpecificHostPermission("<all_urls>")                  // true
isSpecificHostPermission("https://*.google.com/*")      // true
isSpecificHostPermission("*://example.com/*")           // true
isSpecificHostPermission("tabs")                        // false
See: modules/extensions/permission-warnings.ts:585

Limitations

Known LimitationsThis implementation has some differences from Chromium:
  1. No dynamic formatting: Uses static messages instead of formatting with host lists
  2. Simplified host handling: Specific host permissions use generic placeholder messages
  3. Best-effort mapping: Some C++ API permission IDs may not map perfectly to manifest strings
  4. No placeholder replacement: Messages with <ph> tags show raw text
  5. Default environment: Assumes non-ChromeOS environment for conditional messages
See: modules/extensions/permission-warnings.ts:9

ChromeOS-Specific Permissions

Some permissions are specific to ChromeOS:
const chromeOSPermissions = [
  "chromeos.telemetry",
  "chromeos.diagnostics",
  "chromeos.events",
  "enterprise.platformKeys",
  "enterprise.deviceAttributes"
];

const warnings = getPermissionWarnings(chromeOSPermissions);
// These will show appropriate warnings even on non-ChromeOS platforms
See: modules/extensions/permission-warnings.ts:543

Enterprise Permissions

Enterprise extensions may request special permissions:
PermissionWarning Message
enterprise.deviceAttributesSee device information, such as its serial number or asset ID
enterprise.platformKeysPerform security-related tasks for your organization
enterprise.reportingPrivateRead information about your browser, OS, and device
enterprise.networkingAttributesSee network information, such as your IP or MAC address

Best Practices

For Extension Developers

Request Minimal PermissionsOnly request permissions your extension actually needs:
// Bad: Requesting unnecessary permissions
{
  "permissions": ["<all_urls>", "tabs", "history", "bookmarks"]
}

// Good: Minimal permissions
{
  "permissions": ["activeTab", "storage"]
}
Users are more likely to install extensions with fewer permission warnings.

For Browser Developers

// Always show permission warnings before installation
import { getPermissionWarnings } from "@/modules/extensions/permission-warnings";

async function showInstallDialog(manifest, extensionName) {
  const warnings = getPermissionWarnings(
    manifest.permissions || [],
    manifest.host_permissions || []
  );
  
  if (warnings.length === 0) {
    return await simpleConfirmDialog(extensionName);
  }
  
  return await detailedPermissionDialog(extensionName, warnings);
}

Testing Permission Warnings

import { getPermissionWarnings } from "@/modules/extensions/permission-warnings";

// Test different permission combinations
const testCases = [
  {
    name: "Minimal extension",
    perms: ["storage"],
    expected: [] // storage doesn't generate warnings
  },
  {
    name: "History access",
    perms: ["history"],
    expected: ["Read and change your Browse history on all your signed-in devices"]
  },
  {
    name: "All sites",
    perms: [],
    hosts: ["<all_urls>"],
    expected: ["Read and change all your data on all websites"]
  }
];

testCases.forEach(({ name, perms, hosts, expected }) => {
  const warnings = getPermissionWarnings(perms, hosts);
  console.log(`${name}:`, warnings);
  console.assert(
    JSON.stringify(warnings) === JSON.stringify(expected),
    `Expected ${expected} but got ${warnings}`
  );
});

Build docs developers (and LLMs) love