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

Add Privacy Report #457

Merged
merged 8 commits into from
Mar 7, 2024
Merged

Add Privacy Report #457

merged 8 commits into from
Mar 7, 2024

Conversation

GLinnik21
Copy link
Collaborator

@GLinnik21 GLinnik21 commented Feb 12, 2024

Privacy Accessed APIs

The stat function requires declaration as NSPrivacyAccessedAPICategoryFileTimestamp. According to Apple guidelines, we must declare the reason even if we do not use it for the file timestamp. The purpose of its use is the determination of the type and size of the file, which is part of C617.1.

Details

static bool deletePathContents(const char* path, bool deleteTopLevelPathAlso)
{
struct stat statStruct = {0};
if(stat(path, &statStruct) != 0)
{
KSLOG_ERROR("Could not stat %s: %s", path, strerror(errno));
return false;
}
if(S_ISDIR(statStruct.st_mode))

else if(S_ISREG(statStruct.st_mode))
{
ksfu_removeFile(path, false);
}

struct stat st;
if(stat(path, &st) < 0)
{
KSLOG_ERROR("Could not stat %s: %s", path, strerror(errno));
goto done;
}

if(bytesToRead == 0 || bytesToRead >= (int)st.st_size)
{
bytesToRead = (int)st.st_size;
}

The NSFileSystemSize requires declaration as NSPrivacyAccessedAPICategoryDiskSpace. In our case, it falls under 7D9E.1 as we send this information off the device in crash reports. However, Apple requires this part of the crash report to be optional as the user should approve usage of disk space information.
Therefore, an opt-out mechanism should be implemented on KSCrash side.

Details

static uint64_t getStorageSize(void)
{
NSNumber* storageSize = [[[NSFileManager defaultManager] attributesOfFileSystemForPath:NSHomeDirectory() error:nil] objectForKey:NSFileSystemSize];
return storageSize.unsignedLongLongValue;
}

The NSUserDefaults requires a declaration as NSPrivacyAccessedAPICategoryUserDefaults. According to Apple documentation, there are no restrictions on sending data off the device, so it falls under CA92.1.

Details

- (NSString*) quincyInstallUUID
{
static NSString *installUUID = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate,
^{
NSString *priorValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyUUIDUserDefault];
if (priorValue)
{
installUUID = priorValue;
}
else
{
CFUUIDRef uuidObj = CFUUIDCreate(NULL);
installUUID = (NSString*) CFBridgingRelease(CFUUIDCreateString(NULL, uuidObj));
CFRelease(uuidObj);
[[NSUserDefaults standardUserDefaults] setObject:installUUID forKey:kQuincyUUIDUserDefault];
[[NSUserDefaults standardUserDefaults] synchronize];
}
});
return installUUID;
}

Collected Data Types

  • NSPrivacyCollectedDataTypeCrashData is used for crash reporting purposes, as it is the main function of the KSCrash library. Not used for linking or tracking. Used for NSPrivacyCollectedDataTypePurposeAppFunctionality.
  • NSPrivacyCollectedDataTypePerformanceData is used to collect the launch time of the app in crash reports. This information is stored in the app_start_time field of our JSON crash format. This is exactly specified in the Apple docs. Not used for linking or tracking. Used for NSPrivacyCollectedDataTypePurposeAppFunctionality.
  • NSPrivacyCollectedDataTypeDeviceID is utilized to generate app_uuid and device_app_hash in our JSON crash format, which function as device-level identifiers. Additionally, there is a UUID for identifying an installation and potentially sending it from the device in Quincy/Hockey module. It is important to note that KSCrash cannot link this ID to the identity of the user or use it for tracking. This data is collected solely for NSPrivacyCollectedDataTypePurposeAppFunctionality.

@GLinnik21
Copy link
Collaborator Author

GLinnik21 commented Feb 12, 2024

Another issue is the use of sysctlbyname to obtain system boot time. Although Apple's documentation does not require this API to be declared, it is strictly prohibited to send boot time off the device that is obtained by other APIs.

g_systemData.kernelVersion = stringSysctl("kern.version");
g_systemData.osVersion = stringSysctl("kern.osversion");
g_systemData.isJailbroken = isJailbroken();
g_systemData.bootTime = dateSysctl("kern.boottime");
g_systemData.appStartTime = dateString(time(NULL));
g_systemData.executablePath = cString(getExecutablePath());
g_systemData.executableName = cString(infoDict[@"CFBundleExecutable"]);

UPDATE:
There is a 3D61.1 reason that allows sending the boot time as optional content of the bug report, but it requires that it be displayed to the user.

@GLinnik21 GLinnik21 marked this pull request as draft February 12, 2024 16:39
@GLinnik21
Copy link
Collaborator Author

GLinnik21 commented Feb 27, 2024

Will create opt-out mechanism for disc space in a distinct PR.

@GLinnik21 GLinnik21 marked this pull request as ready for review February 27, 2024 15:50
@@ -43,6 +43,9 @@ let package = Package(
"Monitors",
"Tools"
],
resources: [
.copy("PrivacyInfo.xcprivacy")
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For now, I added a kind of "monilit" privacy report in this module, since SPM modules need work. It shows the data collected in all KSCrash submodules.

@bamx23
Copy link
Collaborator

bamx23 commented Mar 3, 2024

@GLinnik21 thanks a lot for such an extensive report on why KCrash uses these privacy-sensitive features. Everything seems correct to me. Great job done 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.

2 participants