| 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 aa34d1738bce9562ba6e16443ef210fbc399a878..fbb3fe3fc93d8bf1b7e7d25c554764cc971831e5 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,18 +124,57 @@ 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().
|
| // emk::kApp,
|
|
|
| // Documented in https://developer.chrome.com/extensions/manifest but not
|
| // implemented anywhere. Still, a lot of apps use it.
|
| "author",
|
|
|
| - // TBD
|
| - // emk::kBluetooth,
|
| + // Allows inspection of page contents, not enabled on stable anyways except
|
| + // for whitelist.
|
| + // emk::kAutomation,
|
|
|
| - // TBD
|
| - // emk::kCommands,
|
| + // TODO(isandrk): Ask Mattias for comments on entries without a comment.
|
| + // See crbug.com/650672.
|
| + "background",
|
| +
|
| + emk::kBackgroundPageLegacy,
|
| +
|
| + 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).
|
| @@ -147,20 +186,38 @@ const char* const kSafeManifestEntries[] = {
|
| // Just a display string.
|
| emk::kDescription,
|
|
|
| - // TBD, looks unsafe
|
| + // Access to web content.
|
| + // emk::kDevToolsPage,
|
| +
|
| + // Restricted to whitelist already.
|
| + emk::kDisplayInLauncher,
|
| +
|
| + emk::kDisplayInNewTabPage,
|
| +
|
| + // 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,
|
|
|
| // Shared Modules configuration: Allow other extensions to access resources.
|
| emk::kExport,
|
|
|
| - // TBD
|
| - // emk::kExternallyConnectable,
|
| + emk::kExternallyConnectable,
|
|
|
| - // TBD
|
| - // emk::kFileHandlers,
|
| + emk::kFileBrowserHandlers,
|
|
|
| - // TBD
|
| - // emk::kFileSystemProviderCapabilities,
|
| + // Extension file handlers are restricted to whitelist which only contains
|
| + // quickoffice.
|
| + emk::kFileHandlers,
|
| +
|
| + emk::kFileSystemProviderCapabilities,
|
| +
|
| + emk::kHomepageURL,
|
|
|
| // Just UX.
|
| emk::kIcons,
|
| @@ -168,19 +225,37 @@ const char* const kSafeManifestEntries[] = {
|
| // Shared Modules configuration: Import resources from another extension.
|
| emk::kImport,
|
|
|
| + 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,
|
|
|
| - // Special-cased in IsPlatformAppSafeForPublicSession().
|
| + // Whitelisted to only allow Google Now.
|
| + emk::kLauncherPage,
|
| +
|
| + // Special-cased in IsSafeForPublicSession().
|
| // emk::kManifestVersion,
|
|
|
| - // Descriptive statement about the app.
|
| + emk::kMIMETypes,
|
| +
|
| + // Whitelisted to only allow browser tests and PDF viewer.
|
| + emk::kMimeTypesHandler,
|
| +
|
| emk::kMinimumChromeVersion,
|
|
|
| // NaCl modules are bound to app permissions just like the rest of the app
|
| @@ -190,22 +265,44 @@ const char* const kSafeManifestEntries[] = {
|
| // Just a display string.
|
| emk::kName,
|
|
|
| - // TBD, doc missing
|
| - // emk::kOAuth2,
|
| + // 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
|
| @@ -215,18 +312,27 @@ const char* const kSafeManifestEntries[] = {
|
| // Just a display string.
|
| emk::kShortName,
|
|
|
| - // TBD, doc missing
|
| + // 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,
|
| + // (Note: Using string literal since extensions::manifest_keys only has
|
| + // constants for sub-keys.)
|
| + "storage",
|
| +
|
| + // Only Hangouts is whitelisted.
|
| + 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
|
| @@ -236,11 +342,10 @@ 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,
|
| @@ -248,6 +353,8 @@ const char* const kSafeManifestEntries[] = {
|
| // Just a display string.
|
| emk::kVersionName,
|
|
|
| + emk::kWebAccessibleResources,
|
| +
|
| // Webview has no special privileges or capabilities.
|
| emk::kWebview,
|
| };
|
| @@ -405,6 +512,16 @@ const char* const kSafePermissionDicts[] = {
|
| "socket",
|
| };
|
|
|
| +// List of safe entries for the "app" dict in manifest.
|
| +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 +542,21 @@ 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 +626,15 @@ bool IsPlatformAppSafeForPublicSession(const extensions::Extension* extension) {
|
| << permission_string;
|
| safe = false;
|
| }
|
| - // "app" may only contain "background".
|
| } 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 +643,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();
|
| @@ -597,11 +727,10 @@ bool DeviceLocalAccountManagementPolicyProvider::UserMayLoad(
|
| return true;
|
| }
|
|
|
| - // Allow force-installed platform app if all manifest contents are
|
| - // whitelisted.
|
| + // Allow force-installed extension if all manifest contents are 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) {
|
|
|