Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature/confidential-protection] Confidential Content Protection #1430

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

hosy
Copy link
Collaborator

@hosy hosy commented Dec 13, 2024

Description

Confidential View and Screenshot Protection

This update introduces screenshot protection for confidentially marked views in the app and the share sheet extension. When a screenshot is taken, confidential views will not display their content in the screenshot.

To discourage taking photos of confidential views, these views now include a watermark displaying the account’s email and username.

Screenshot protection can be enabled via an MDM parameter.

File or path names displayed in UI elements that are difficult to watermark are redacted after the third character. This ensures the user can identify the file or path name to some extent, but it remains unreadable for security.

Additionally, to prevent sharing confidential data when screenshot protection or confidential view marking is enabled, the following features are disabled:

  • File Provider access
  • Shortcuts Intents
  • System sharing dialog actions
  • Copying files
  • Text recognition on images

This behavior can be overridden using an MDM parameter; however, overriding it is not recommended.

MDM Parameter

MDM Parameter Description
confidential.allow-screenshots Controls whether screenshots are allowed or not. If not allowed confidential views will be marked as sensitive and are not visible in screenshots.
confidential.mark-confidential-views Controls if views which contains sensitive content contains a watermark or not.
confidential.allow-overwrite-confidential-mdm-settings Controls if confidential related MDM settings can be overwritten.

Screenshots

Confidential View

File List Content View Spaces File Provider Shortcuts
Simulator Screenshot - iPhone 16 Plus - 2024-12-16 at 16 05 16 Simulator Screenshot - iPhone 16 Plus - 2024-12-16 at 14 46 09 Simulator Screenshot - iPhone 16 Plus - 2024-12-16 at 14 18 19 Simulator Screenshot - iPhone 16 Plus - 2024-12-16 at 14 18 51 Simulator Screenshot - iPhone 16 Plus - 2024-12-16 at 14 19 39

Screenshot Protection

App Share Extension
IMG_0089 IMG_0088

Testing

Add at least one of the following MDM parameters to the Branding.plist:

Key Type Value
confidential.allow-screenshots Boolean NO
confidential.mark-confidential-views Boolean YES

If you want to allow File Provider access or Actions set the key confidential.allow-overwrite-confidential-mdm-settings to Boolean YES.

Screenshot protection is only working on a physical device!

What to test:

  • Light/dark appearance
  • File Provider access
  • Share sheet
  • Shortcuts
  • All content and editing views
  • Device rotation
  • Multi window environment (iPad)
  • Menu sheets
  • Sidebar
  • Screenshot protection should not show any file names, folders or document content
  • Confidential views (file names, folders, or document content) should contain watermarks, or names should be redacted.

Related Issue

Motivation and Context

How Has This Been Tested?

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • Added an issue with details about all relevant changes in the iOS documentation repository.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • Added changelog files for the fixed issues in folder changelog/unreleased

hosy added 3 commits December 13, 2024 10:41
This update introduces screenshot protection for confidentially marked views in the app and the share sheet extension. When a screenshot is taken, confidential views will not display their content in the screenshot.

To discourage taking photos of confidential views, these views now include a watermark displaying the account’s email and username.
Screenshot protection can be enabled via an MDM parameter.

Additionally, to prevent sharing confidential data when screenshot protection or confidential view marking is enabled, the following features are disabled:
- File Provider access
- Shortcuts Intents
- System sharing dialog actions
- Copying files
- Text recognition on images
This behavior can be overridden using an MDM parameter; however, overriding it is not recommended.
- Adjusted watermark angle for improved alignment
- Updated GitHub Action workflow:
  - Fetch the latest available OS version
  - Retrieve iPhone simulator device for the selected OS version
@DeepDiver1975
Copy link
Member

To fix CI I suggest to use this action https://github.com/marketplace/actions/mxcl-xcodebuild

In a second step let's define different combinations which we want to build and test in the future

hosy added 2 commits December 16, 2024 14:56
- Updated default values for confidential MDM settings
- Adjusted rotation angle for confidential text
- Added a subtitle to small confidential views and modified text color opacity
- Preserved accessory views by ensuring watermarks are not applied to them
- Added missing file from the last commit
@hosy hosy changed the title [feature/confidential-protection] Confidential View and Screenshot Protection [feature/confidential-protection] Confidential Content Protection Dec 16, 2024
@hosy hosy marked this pull request as ready for review December 17, 2024 09:50
@hosy hosy self-assigned this Dec 17, 2024
@hosy hosy added this to the 12.4-Next milestone Dec 17, 2024
@jesmrec
Copy link
Contributor

jesmrec commented Dec 19, 2024

First, preliminary and exploratory testing, with commit 35fa8a981

Assumed: protection only affects to:

  • Files (name and other parameters)
  • Folders name in navigation
  • File contents
  • Spaces (name and other parameters)

is that right?

1. Screenshot protection:

Using the following set up:

<key>confidential.allow-screenshots</key>
<false/>
  • Side menu is screen-shooted (shouldn't?). I caught a video, the content is blank due to the protection. I took two screenshots: the first one over the list of files is blank (correct ✅ ), the second one over the side menu shows the info
ScreenRecording_12-18-2024.12-22-30_1.MP4

are the username and the account sensible information?

the issue is even more visible in iPad, where the sidebar menu is always in foreground.

  • It's not posible to share content with other users or by link. It's posible in the web and in Android app. That causes a regression.

2. Watermarking

no issues detected at this point.

3. confidential.allow-overwrite-confidential-mdm-settings

true: I wasn't able to test the correct access to the FP's because i always get the following error:

Screenshot 2024-12-19 at 10 35 10

false: FP access has been disabled by the administrator

that was just a first preliminary testing, final testing will be done when CR passed. This first step helped to design the feature test plan.

@hosy
Copy link
Collaborator Author

hosy commented Dec 20, 2024

@hosy There is a redraw error when switching the collection view layout from list to grid or other formats. This issue needs to be fixed.

@@ -0,0 +1,101 @@
//
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears this code / ConfidentalManager (without i) is not used, has been implemented in ownCloudAppFramework/ConfidentialManager (with i) instead and this entire file can be removed.

}

- (BOOL)allowScreenshots {
id value = [ConfidentialManager classSettingForOCClassSettingsKey:OCClassSettingsKeyAllowScreenshots];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the proper type (NSNumber * instead of id) here.

}

- (BOOL)markConfidentialViews {
id value = [ConfidentialManager classSettingForOCClassSettingsKey:OCClassSettingsKeyMarkConfidentialViews];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the proper type (NSNumber * instead of id) here.


- (BOOL)allowOverwriteConfidentialMDMSettings {
BOOL confidentialSettingsEnabled = self.confidentialSettingsEnabled;
id value = [ConfidentialManager classSettingForOCClassSettingsKey:OCClassSettingsKeyAllowOverwriteConfidentialMDMSettings];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the proper type (NSNumber * instead of id) here.

@property (assign, readonly) BOOL markConfidentialViews;
@property (assign, readonly) BOOL allowOverwriteConfidentialMDMSettings;
@property (assign, readonly) BOOL confidentialSettingsEnabled;
@property (nonatomic, readonly, nullable) NSArray<NSString *> *disallowedActions;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use NSArray<OCExtensionIdentifier> * instead of NSArray<NSString *> * to make it easier to understand what that property returns.

return secureView
}

let view = UIView()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this line of code is reached, no screenshot-protecting CanvasView could be found and there will not be any screenshot protection.

Returning a UIView here will keep the view structure intact, but nothing will prevent a screenshot from being taken.

Something to discuss: should the app have this fallback and continue to work even if the protection no longer is in place? Should the app crash? Should that decision be determined by us (and hardcoded) - or be configurable?

@@ -86,6 +86,12 @@ open class MoreViewHeader: UIView {

private func render() {
cssSelectors = [.more, .header]

let secureView = SecureTextField().secureContainerView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestions about unifying the code to inject a secure container that I made in BrowserNavigationViewController.swift would also apply here.

@@ -172,6 +172,9 @@ public class ClientLocationPicker : NSObject {
}

allowedLocationFilter = { (targetLocation, context) in
OnMainThread {
self.headerView?.secureView(core: context?.core)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of self here might create a retain-loop.
Also view management code shouldn't be placed into this closure, if only because it could be called more than once and a new watermark view would be added on every call.

@@ -259,7 +259,18 @@ open class ShareViewController: CollectionViewController, SearchViewControllerDe

open override func viewDidLoad() {
super.viewDidLoad()


let secureView = SecureTextField().secureContainerView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestions about unifying the code to inject a secure container that I made in BrowserNavigationViewController.swift would also apply here.

@@ -167,10 +167,14 @@ open class CollectionViewController: UIViewController, UICollectionViewDelegate,
public override func loadView() {
super.loadView()

let secureView = SecureTextField().secureContainerView
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The suggestions about unifying the code to inject a secure container that I made in BrowserNavigationViewController.swift would also apply here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants