Index: chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc |
diff --git a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc |
index e0b1c08fbfea7504256b791470fcc1abbf302da2..aceff3e75b4efffb0133554c7fdecd7f52f005a1 100644 |
--- a/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc |
+++ b/chrome/browser/chromeos/extensions/device_local_account_management_policy_provider.cc |
@@ -124,112 +124,214 @@ const char* const kPublicSessionWhitelist[] = { |
// List of manifest entries from https://developer.chrome.com/apps/manifest. |
// Unsafe entries are commented out and special cases too. |
const char* const kSafeManifestEntries[] = { |
- // Special-cased in IsPlatformAppSafeForPublicSession(). |
+ emk::kAboutPage, |
+ |
+ // Special-cased in IsSafeForPublicSession(). |
+ // Only allow hosted_app, platform_app. |
// emk::kApp, |
- // Special-cased in IsPlatformAppSafeForPublicSession(). |
- // emk::kManifestVersion, |
+ // Documented in https://developer.chrome.com/extensions/manifest but not |
+ // implemented anywhere. Still, a lot of apps use it. |
+ "author", |
- // Just a display string. |
- emk::kName, |
+ // Allows inspection of page contents, not enabled on stable anyways except |
+ // for whitelist. |
+ // emk::kAutomation, |
- // Just a display string. |
- emk::kShortName, |
+ "background", |
Thiemo Nagel
2016/09/26 15:10:29
Why is there no string constant for it? Is it eve
Ivan Šandrk
2016/09/27 08:40:45
Needs more investigation, may be the same case as
|
- // Version string (for app updates). |
- emk::kVersion, |
+ emk::kBackgroundPageLegacy, |
- // Name of directory containg default strings. |
- emk::kDefaultLocale, |
+ emk::kBackgroundPersistent, |
+ |
+ emk::kBluetooth, |
+ |
+ emk::kBrowserAction, |
+ |
+ // Allows to replace the search provider which is somewhat risky - need to |
+ // double check how the search provider policy behaves in PS. |
+ emk::kSettingsOverride, |
+ |
+ // Custom bookmark managers - I think this is fair game, bookmarks should be |
+ // URLs only, and it's restricted to whitelist on stable. |
+ emk::kUIOverride, |
+ |
+ // Bookmark manager, history, new tab - should be safe. |
+ emk::kChromeURLOverrides, |
+ |
+ // General risk of capturing user input, but key combos must include Ctrl or |
+ // Alt, so I think this is safe. |
+ emk::kCommands, |
+ |
+ // General risk of capturing user input, but key combos must include Ctrl or |
+ // Alt, so I think this is safe. |
+ emk::kContentCapabilities, |
+ |
+ // Access to web content. |
+ emk::kContentScripts, |
+ |
+ emk::kContentSecurityPolicy, |
+ |
+ // Access to web content. |
+ emk::kConvertedFromUserScript, |
// An implementation detail (actually written by Chrome, not the app |
// author). |
emk::kCurrentLocale, |
+ // Name of directory containg default strings. |
+ emk::kDefaultLocale, |
+ |
// Just a display string. |
emk::kDescription, |
- // Just UX. |
- emk::kIcons, |
+ // Access to web content. |
+ emk::kDevToolsPage, |
- // Documented in https://developer.chrome.com/extensions/manifest but not |
- // implemented anywhere. Still, a lot of apps use it. |
- "author", |
+ // Restricted to whitelist already. |
+ emk::kDisplayInLauncher, |
- // TBD |
- // emk::kBluetooth, |
- |
- // TBD |
- // emk::kCommands, |
+ emk::kDisplayInNewTabPage, |
- // TBD, looks unsafe |
+ // This allows to declaratively filter web requests and content, matching on |
+ // content data. Doesn't allow direct access to request/content data. Can be |
+ // used to brute-force e.g. cookies (reload with filter rules adjusted to |
+ // match all possible cookie values) - but that's equivalent to an |
+ // off-device brute-force attack. |
+ // Looks safe in general with one exception: There's an action that allows |
+ // to insert content scripts on matching content. We can't allow this, need |
+ // to check whether there's also a host permission required for this case. |
// emk::kEventRules, |
- // TBD |
- // emk::kExternallyConnectable, |
+ // Shared Modules configuration: Allow other extensions to access resources. |
+ emk::kExport, |
- // TBD |
- // emk::kFileHandlers, |
+ emk::kExternallyConnectable, |
- // TBD |
- // emk::kFileSystemProviderCapabilities, |
+ emk::kFileBrowserHandlers, |
+ |
+ // Extension file handlers are restricted to whitelist which only contains |
+ // quickoffice. |
+ emk::kFileHandlers, |
+ |
+ emk::kFileSystemProviderCapabilities, |
+ |
+ emk::kHomepageURL, |
+ |
+ // Just UX. |
+ emk::kIcons, |
// Shared Modules configuration: Import resources from another extension. |
emk::kImport, |
- // Shared Modules configuration: Allow other extensions to access resources. |
- emk::kExport, |
+ emk::kIncognito, |
+ |
+ // Keylogging. |
+ emk::kInputComponents, |
// Shared Modules configuration: Specify extension id for development. |
emk::kKey, |
- // Descriptive statement about the app. |
+ emk::kKiosk, |
+ |
emk::kKioskEnabled, |
- // Contradicts the purpose of running inside a Public Session. |
- // emk::kKioskOnly, |
+ // Not useful since it will prevent app from running, but we don't care. |
+ emk::kKioskOnly, |
+ |
+ emk::kKioskRequiredPlatformVersion, |
+ |
+ // Not useful since it will prevent app from running, but we don't care. |
+ emk::kKioskSecondaryApps, |
+ |
+ // Whitelisted to only allow Google Now. |
+ emk::kLauncherPage, |
+ |
+ // Special-cased in IsSafeForPublicSession() (value == 2). |
+ // emk::kManifestVersion, |
+ |
+ emk::kMIMETypes, |
+ |
+ // Whitelisted to only allow browser tests and PDF viewer. |
+ emk::kMimeTypesHandler, |
- // Descriptive statement about the app. |
emk::kMinimumChromeVersion, |
// NaCl modules are bound to app permissions just like the rest of the app |
// and thus should not pose a risk. |
emk::kNaClModules, |
- // TBD, doc missing |
- // emk::kOAuth2, |
+ // Just a display string. |
+ emk::kName, |
+ |
+ // Used in conjunction with the identity API - not really used when there's |
+ // no GAIA user signed in. |
+ emk::kOAuth2, |
+ |
+ // Generally safe (i.e. only whitelist apps), except for the policy to |
+ // whitelist apps for auto-approved token minting (we should just ignore |
+ // this in public sessions). Risk is that admin mints OAuth tokens to access |
+ // services on behalf of the user silently. |
+ // emk::kOAuth2AutoApprove, |
- // Descriptive statement about the app. |
emk::kOfflineEnabled, |
- // Special-cased in IsPlatformAppSafeForPublicSession(). |
+ // A bit risky as the extensions sees all keystrokes entered into the |
+ // omnibox after the search key matches, but generally we deem URLs fair |
+ // game. |
+ // emk::kOmnibox, |
+ |
+ // Special-cased in IsSafeForPublicSession(). Subject to permission |
+ // restrictions. |
// emk::kOptionalPermissions, |
- // Special-cased in IsPlatformAppSafeForPublicSession(). |
+ emk::kOptionsPage, |
+ |
+ emk::kOptionsUI, |
+ |
+ emk::kPageAction, |
+ |
+ // Special-cased in IsSafeForPublicSession(). Subject to permission |
+ // restrictions. |
// emk::kPermissions, |
- // No constant in manifest_constants.cc. |
+ // No constant in manifest_constants.cc. Declared as a feature, but unused. |
// "platforms", |
- // Descriptive statement about the app. |
+ // N/A on Chrome OS, so we don't care. |
+ emk::kPlugins, |
+ |
+ // Stated 3D/WebGL/plugin requirements of an app. |
emk::kRequirements, |
// Execute some pages in a separate sandbox. (Note: Using string literal |
// since extensions::manifest_keys only has constants for sub-keys.) |
"sandbox", |
- // TBD, doc missing |
+ // Just a display string. |
+ emk::kShortName, |
+ |
+ // Doc missing. Declared as a feature, but unused. |
// emk::kSignature, |
// Network access. |
emk::kSockets, |
- // TBD. (Note: Using string literal since extensions::manifest_keys only |
- // has constants for sub-keys.) |
- // "storage", |
+ // Just provides dictionaries, no access to content. |
+ emk::kSpellcheck, |
- // TBD, doc missing |
- // emk::kSystemIndicator, |
+ // Update comment. (Note: Using string literal since |
+ // extensions::manifest_keys only has constants for sub-keys.) |
+ "storage", |
+ |
+ // Only hangouts is whitelisted. |
Thiemo Nagel
2016/09/26 15:10:29
Nit: Hangouts is spelled with a capital H.
Ivan Šandrk
2016/09/27 08:40:45
Done.
|
+ emk::kSystemIndicator, |
+ |
+ emk::kTheme, |
+ |
+ // Might need this for accessibilty, but has content access. Manual |
+ // whitelisting might be reasonable here? |
+ // emk::kTtsEngine, |
// TODO(tnagel): Ensure that extension updates query UserMayLoad(). |
// https://crbug.com/549720 |
@@ -239,15 +341,19 @@ const char* const kSafeManifestEntries[] = { |
// app author has proven ownership of to the Web Store. (Chrome starts the |
// app instead of fulfilling the navigation.) This is only safe for apps |
// that have been loaded from the Web Store and thus is special-cased in |
- // IsPlatformAppSafeForPublicSession(). |
+ // IsSafeForPublicSession(). |
// emk::kUrlHandlers, |
- // TBD |
- // emk::kUsbPrinters, |
+ emk::kUsbPrinters, |
+ |
+ // Version string (for app updates). |
+ emk::kVersion, |
// Just a display string. |
emk::kVersionName, |
+ emk::kWebAccessibleResources, |
+ |
// Webview has no special privileges or capabilities. |
emk::kWebview, |
}; |
@@ -405,6 +511,16 @@ const char* const kSafePermissionDicts[] = { |
"socket", |
}; |
+// List of allowed app strings. |
+const char* const kSafeAppStrings[] = { |
+ "background", |
+ "content_security_policy", |
+ "icon_color", |
+ "isolation", |
+ "launch", |
+ "linked_icons", |
+}; |
+ |
// Return true iff |entry| is contained in |char_array|. |
bool ArrayContainsImpl(const char* const char_array[], |
size_t entry_count, |
@@ -425,15 +541,20 @@ bool ArrayContains(const char* const (&char_array)[N], |
return ArrayContainsImpl(char_array, N, entry); |
} |
-// Returns true for platform apps that are considered safe for Public Sessions, |
+// Returns true for extensions that are considered safe for Public Sessions, |
// which among other things requires the manifest top-level entries to be |
// contained in the |kSafeManifestEntries| whitelist and all permissions to be |
// contained in |kSafePermissionStrings| or |kSafePermissionDicts|. Otherwise |
// returns false and logs all reasons for failure. |
-bool IsPlatformAppSafeForPublicSession(const extensions::Extension* extension) { |
+bool IsSafeForPublicSession(const extensions::Extension* extension) { |
bool safe = true; |
- if (extension->GetType() != extensions::Manifest::TYPE_PLATFORM_APP) { |
- LOG(ERROR) << extension->id() << " is not a platform app."; |
+ if (!extension->is_extension() && |
+ !extension->is_hosted_app() && |
+ !extension->is_platform_app() && |
+ !extension->is_shared_module() && |
+ !extension->is_theme()) { |
+ LOG(ERROR) << extension->id() << " is not of a supported type. " |
+ << "Extension type: " << extension->GetType(); |
safe = false; |
} |
@@ -503,8 +624,18 @@ bool IsPlatformAppSafeForPublicSession(const extensions::Extension* extension) { |
<< permission_string; |
safe = false; |
} |
- // "app" may only contain "background". |
+ // "app" may contain one of: background, content_security_policy, |
+ // icon_color, isolation, launch, linked_icons. |
+ // "app" is only allowed for hosted_app or platform_app. |
} else if (it.key() == emk::kApp) { |
+ if (!extension->is_hosted_app() && |
+ !extension->is_platform_app()) { |
+ LOG(ERROR) << extension->id() |
+ << ": app manifest entry is allowed only for" |
+ << "hosted_app or platform_app extension type. " |
+ << "Current extension type: " << extension->GetType(); |
+ safe = false; |
+ } |
const base::DictionaryValue *dict_value; |
if (!it.value().GetAsDictionary(&dict_value)) { |
LOG(ERROR) << extension->id() << ": app is not a dictionary."; |
@@ -513,7 +644,7 @@ bool IsPlatformAppSafeForPublicSession(const extensions::Extension* extension) { |
} |
for (base::DictionaryValue::Iterator it2(*dict_value); |
!it2.IsAtEnd(); it2.Advance()) { |
- if (it2.key() != "background") { |
+ if (!ArrayContains(kSafeAppStrings, it2.key())) { |
LOG(ERROR) << extension->id() |
<< " has non-whitelisted manifest entry: " |
<< it.key() << "." << it2.key(); |
@@ -601,7 +732,7 @@ bool DeviceLocalAccountManagementPolicyProvider::UserMayLoad( |
// whitelisted. |
if ((extension->location() == extensions::Manifest::EXTERNAL_POLICY_DOWNLOAD |
|| extension->location() == extensions::Manifest::EXTERNAL_POLICY) |
- && IsPlatformAppSafeForPublicSession(extension)) { |
+ && IsSafeForPublicSession(extension)) { |
return true; |
} |
} else if (account_type_ == policy::DeviceLocalAccount::TYPE_KIOSK_APP) { |