Featured Post

Browser Extension Security: Review the Code You Ship

A practical review of extension permissions, page input, stored data and release artifacts, with examples for Chrome extension developers.

RiskyPlugins Team
Security
#security#extensions#best-practices#development

Start a security review with the packaged extension. Check its manifest and the code it actually loads. A repository can pass tests while the release archive contains an old dependency, a debug credential or an unexpected script.

For each feature, establish what it reads and where that data goes. Then check whether the permissions allow more access than the feature requires.

Keep page data away from executable markup

Text taken from a webpage or a message is untrusted input. Assigning it to innerHTML asks the browser to interpret it as markup. If you only need to display text, use a text node:

element.textContent = userInput;

If the feature requires HTML, define which markup it accepts and use a maintained sanitizer. Validation still matters for values passed to other destinations, such as URLs or extension messages. A value safe to display as text may be unsafe as a navigation target.

A Content Security Policy provides another restriction on what extension pages can load. Keep executable code in the package and review the policy alongside every new integration. A strict policy does not make unsafe message handling harmless.

Ask for access when the feature needs it

Avoid broad host permissions when a user-triggered action on the current tab will do. Review permissions again when removing a feature; old access often outlives the code that requested it.

Chrome requires optional permissions to be declared before they can be requested. For a feature that optionally sends notifications, the relevant manifest entry is:

{
	"optional_permissions": ["notifications"]
}

Request it from a user gesture and handle refusal without repeatedly prompting:

notificationButton.addEventListener('click', async () => {
	const granted = await chrome.permissions.request({
		permissions: ['notifications']
	});

	if (!granted) {
		return;
	}

	enableNotifications();
});

Here enableNotifications is the application's feature handler. The permissions API documentation explains declaration and request requirements.

Store less sensitive data

Extension storage needs an explicit plan for handling credentials. Decide which contexts need access, how long values should remain and what is removed on sign-out. Avoid syncing secrets between devices simply because sync storage is convenient.

Chrome provides different storage areas and access controls. Check the storage documentation before choosing one. Keeping a decryption key beside encrypted data does little to protect it from code that can read both.

For network requests, use HTTPS and send only the fields the feature needs. Review the receiving service too: an encrypted connection protects transport, but it does not explain what happens to the data after arrival.

Review updates as releases

Compare the outgoing package with the approved version. New executables and changed network destinations deserve an explanation. So do permission additions, even when the corresponding feature sounds harmless.

Run dependency checks, inspect lockfile changes and exercise the affected behaviour before publishing. An automatic update command is not a security review. Protect publisher accounts and require approval for release workflows according to the project's risk.

The Dark Mode Google Docs investigation shows a small advertising addition after an ownership change. The Nx Console case shows a loader hidden inside an otherwise familiar bundle. Comparing versions makes both changes easier to locate.

Test denied permissions and malformed messages. Exercise expired sessions and unavailable remote services. Check that failures do not expose credentials or silently expand access.

Keep the reviewed artifact and the reason it was approved. When a later finding arrives, that record lets you determine which version users received and what needs to be revisited.