HTTP Request Fails Trying to Report Unwanted Communication Report via API

214 Views Asked by At

I created an Unwanted Communication Reporting Extension as per described here: https://developer.apple.com/documentation/sms_and_call_reporting/sms_and_call_spam_reporting

Followed the instructions and was able to get the report callback in my extension class, but when I try to make an API request to my HTTPS server, somewhere along the console log I get

nw_resolver_can_use_dns_xpc_block_invoke Sandbox does not allow access to com.apple.dnssd.service

and

Task <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1> finished with error [-1003] Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={_kCFStreamErrorCodeKey=-72000, NSUnderlyingError=0x282d5c600 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, _kCFStreamErrorCodeKey=-72000, _kCFStreamErrorDomainKey=10}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <C31ADB51-B5C3-4E85-800E-405781F6A9ED>.<1>"), NSLocalizedDescription=A server with the specified hostname could not be found., NSErrorFailingURLStringKey=https://sub.domain.com/debug, NSErrorFailingURLKey=https://sub.domain.com/debug, _kCFStreamErrorDomainKey=10}

So basically the dns lookup fails due to a sandbox restriction, but I was not able to allow the app sandbox access, that seems like a OSX specific capability.

Here is my code example that is in charge of the API reporting:

func reportToAPI(for request: ILClassificationRequest) {
    
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        return
    }
    
    var request = URLRequest(url: url)
    
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try? JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    
    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data, error == nil else {
            return
        }
        
        do {
            let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print(response)
        } catch {
            
        }
    }
    task.resume()
}

I also have my associated domains set up on both extension and main app's target as classificationreport:sub.domain.com and domain.com, as well as my apple-app-site-association file uploaded as this:

{
"classificationreport": {
    "apps": ["L***.com.b***.smsreporting.unwantedreporting","L***.com.b***.smsreporting"]
}

Any help and guidance is appreciated as I am stuck at this point and lack of documentation on this is making things harder.

Edit: I am testing this on my own developer account, which is an individual membership, not organizational, if that matters.

2

There are 2 best solutions below

5
KerryDong On BEST ANSWER

It seems you call reportToAPI() in Unwanted Communication Reporting Extension.

However if you add apple-app-site-association and Association Domain in .entitlement correctly. There is no need to create URLRequest by yourself. Apple will send the API on your behalf. (I think it's for privacy reasons, like Message Filter Extension.)

So classificationResponse should look like this:

override func classificationResponse(for request:ILClassificationRequest) -> ILClassificationResponse {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    let action: ILClassificationAction = .reportJunk  // or .none, .reportNotJunk, .reportJunkAndBlockSender
    let response = ILClassificationResponse(action: action)
    response.userInfo = payload

    return response
}
1
Anay On

The error message suggests that the DNS lookup fails due to sandbox restrictions. The error you encountered, "Sandbox does not allow access to com.apple.dnssd.service," indicates that your app is restricted from accessing DNS services within the sandbox environment.

You need to allow your app sandbox access to the necessary capabilities. Enabling capabilities required by your app might not be possible for an individual developer account. You may need an organizational membership.

Regarding your code, everything seems to be in order. However, I would suggest making a few improvements to handle errors. Here's an updated version of your code:

func reportToAPI(for request: ILClassificationRequest) {
    let payload: [String: AnyHashable] = [
        "data": "OK",
        "test": "payload"
    ]
    
    guard let url = URL(string: "https://sub.domain.com/debug") else {
        print("Invalid URL")
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: payload, options: .fragmentsAllowed)
    } catch {
        print("Failed to serialize payload")
        return
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if let error = error {
            print("Error: \(error.localizedDescription)")
            return
        }
        
        guard let data = data else {
            print("No data received")
            return
        }
        
        do {
            let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print("API response: \(json)")
        } catch {
            print("Failed to parse API response: \(error.localizedDescription)")
        }
    }
    
    task.resume()
}

Changes

  1. Improved error handling:
  • Added a do-catch block around the serialization of the payload to catch any serialization errors.
  • Added error handling for the case where no data is received from the API request.
  • Added error handling for parsing the API response.
  • Printed specific error descriptions when errors occur.
  1. Modified the print statement to provide more informative feedback, such as printing the API response or indicating the failure reason.