Getting a basic URL Filter to work

I haven’t been able to get this to work at any level! I’m running into multiple issues, any light shed on any of these would be nice:

  1. I can’t implement a bloom filter that produces the same output as can be found in the SimpleURLFilter sample project, after following the textual description of it that’s available in the documentation. No clue what my implementation is doing wrong, and because of the nature of hashing, there is no way to know. Specifically:
    1. The web is full of implementations of FNV-1a and MurmurHash3, and they all produce different hashes for the same input. Can we get the proper hashes for some sample strings, so we know which is the “correct” one?
    2. Similarly, different implementations use different encodings for the strings to hash. Which should we use here?
    3. The formulas for numberOfBits and numberOfHashes give Doubles and assign them to Ints. It seems we should do this conversing by rounding them, is this correct?
    4. Can we get a sample correct value for the combined hash, so we can verify our implementations against it?
    5. Or ignoring all of the above, can we have the actual code instead of a textual description of it? 😓
  2. I managed to get Settings to register my first attempt at this extension in beta 1. Now, in beta 2, any other project (including the sample code) will redirect to Settings, show the Allow/Deny message box, I tap Allow, and then nothing happens. This must be a bug, right?
  3. Whenever I try to enable the only extension that Settings accepted (by setting its isEnabled to true), its status goes to .stopped and the error is, of course, .unknown. How do I debug this?
  4. While the extension is .stopped, ALL URL LOADS are blocked on the device. Is this to be expected? (shouldFailClosed is set to false)
  5. Is there any way to manually reload the bloom filter? My app ships blocklist updates with background push, so it would be wasteful to fetch the filter at a fixed interval. If so, can we opt out of the periodic fetch altogether?
  6. I initially believed the API to be near useless because I didn’t know of its “fuzzy matching” capabilities, which I’ve discovered by accident in a forum post. It’d be nice if those were documented somewhere!

Thanks!!

Answered by beacham in 877878022

@DTS Engineer I am still getting this when pushing to Testflight:

Invalid Info.plist value. The value of the NSExtensionPointIdentifier key, com.apple.url-filter-provider, in the Info.plist of “PledgeLock.app/PlugIns/URLFilterExtension.appex” is invalid. Please refer to the App Extension Programming Guide at https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Action.html#/apple_ref/doc/uid/TP40014214-CH13-SW1. (ID: cf6bb55a-0673-41b4-8aaa-d64c2f36ce9c) error: exportArchive Validation failed. Invalid Info.plist value. The value of the NSExtensionPointIdentifier key, com.apple.url-filter-provider, in the Info.plist of “PledgeLock.app/PlugIns/URLFilterExtension.appex” is invalid. Please refer to the App Extension Programming Guide at https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Action.html#/apple_ref/doc/uid/TP40014214-CH13-SW1. (ID: cf6bb55a-0673-41b4-8aaa-d64c2f36ce9c).

@KayleeSC For PIR server, did you created new one or reused https://github.com/apple/pir-service-example/tree/main/Sources before submitting OHTTP form, have you done any special kind of configuration for backend PIR service. Because my OHTTP form is been rejected by apple, may be it will be a great help if you can provide some checklist

I started from that code yeah. Of course there was a lot of configuration involved to stand up the server 😅

I don’t know how to help, I guess I just got lucky and did it right the first time. I was never formally accepted or rejected, but apparently I was accepted in effect.

@KayleeSC I mean before submitting request, how did you make sure that everything is as expected. We have 2 different things PIR service and OHTTP gateway.

I didn’t, I got lucky!

@KayleeSC I got below feedback from Apple

1️⃣ Checking DNS TXT record for protectus-pirservice-iso-dfcxfmbkghc9a7hu.northeurope-01.azurewebsites.net... ✗ DNS TXT record is missing or incorrect Expected: "apple-url-filter=com.example.apple-samplecode.SimpleURLFilter3978B9P5X5" 2️⃣ Checking OHTTP Gateway SSL/TLS configuration for protectus-ohttp-gateway-gqdqa3hackhcf9c3.northeurope-01.azurewebsites.net... ✗ HTTP/2 (h2) protocol is NOT supported ✓ Certificate chain appears valid ✓ SSL/TLS connection successful 3️⃣ Checking OHTTP key configuration at https://protectus-ohttp-gateway-gqdqa3hackhcf9c3.northeurope-01.azurewebsites.net... ✗ Failed to fetch OHTTP keys: HTTP 404 Please see https://swiftpackageindex.com/apple/pir-service-example/main/documentation/pirservice/onboarding to learn more about the requirements and OHTTP.

Really not sure why you’re asking me, but if I had to guess... Well the DNS record issue should be pretty obvious, the rest I imagine is because azure puts your server behind some sort of proxy? Literally spitballing over here tho

It would be extremely useful if this API tried all subdomains... as in, they keys c.com and b.c.com should both block the load of http://a.b.c.com/whatever.

When I read the docs, who said that loading https://www.example.com/a/b/c?id=123#fragment would be matched against both example.com and www.example.com, I assumed that meant that subdomains didn’t matter. But in testing I discovered it literally only applies to www 😅

I think I can infer why this API was introduced based on its design; however wouldn’t that use case require pretty strong anti-evasion features?

Hi everyone,

I've been following this thread closely — it's been extremely helpful for getting NEURLFilterManager working.

I'm now facing the pirSkipRegistration = NO blocker. My setup:

  • Filter extension activates and deactivates correctly (cycle works end-to-end on iOS 26.5)

  • configurationInvalid is resolved (trailing slash fix + correct usecase name)

  • PIR server deployed at https://dropbet-pir.fly.dev/ (Swift PIR Service, 4 shards, ~208K domains)

  • Usecase: com.dropbet.DropBet.url.filtering

  • Entitlement url-filter-provider confirmed on both app and extension targets

  • Privacy Pass disabled server-side for dev testing

The filter is active but never sends /queries to my server — because pirSkipRegistration = NO, iOS requires Privacy Pass via Apple's OHTTP relay before forwarding any PIR queries.

My question: what is the exact process to register a PIR server with Apple's OHTTP relay? Is there a form, a DTS request, or a specific Apple program to apply to? I haven't found any documentation on this step.

Any help appreciated.

iOS 27 beta 1 brings a brand new error which ends up resulting in a state of .serverSetupIncomplete:

<NEPIRChecker: 0x7de6c79b60>: -[NEPIRChecker start:responseQueue:completionHandler:]_block_invoke - PIR status returned error <Error Domain=com.apple.CipherML Code=1100 "Unable to query status due to errors: Error details were logged and redacted." UserInfo={NSLocalizedDescription=Unable to query status due to errors: Error details were logged and redacted., NSUnderlyingError=0x7de712f4e0 {Error Domain=com.apple.CipherML Code=1800 "Error details were logged and redacted." UserInfo={NSLocalizedDescription=Error details were logged and redacted.}}}>

<NEAgentURLFilterExtension: 0x7de6d24e60>: -[NEAgentURLFilterExtension startURLFilter]_block_invoke - Failed to startFilter <Error Domain=NEMembershipCheckerErrorDomain Code=3 "(null)">

What’s a NEMembershipChecker? Member of what?

Digging deeper I found these:

Failed to prefetch tokens for group 'site.kaylees.Wipr2': Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi, LQM: good, NSErrorFailingURLKey=https://pirissuer.kaylees.site/token-key-for-user-token, NSUnderlyingError=0x7517125a40 {Error Domain=NSPOSIXErrorDomain Code=50 "Network is down" UserInfo={NSDescription=Network is down}}, _NSURLErrorPrivacyProxyFailureKey=true, NSLocalizedDescription=The Internet connection appears to be offline.}

queryStatus(for:options:) threw an error: Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={_NSURLErrorNWPathKey=satisfied (Path is satisfied), interface: en0[802.11], ipv4, dns, uses wifi, LQM: good, NSErrorFailingURLKey=https://pirissuer.kaylees.site/token-key-for-user-token, NSUnderlyingError=0x7517125b00 {Error Domain=NSPOSIXErrorDomain Code=50 "Network is down" UserInfo={NSDescription=Network is down}}, _NSURLErrorPrivacyProxyFailureKey=true, NSLocalizedDescription=The Internet connection appears to be offline.}

The connection and the URL mentioned are fine of course, but "Network is down” now?

This new problem only affects the App Store version of my app – not present if I install from Xcode.

This new problem only affects the App Store version of my app

Well, that’s not good. For problems like this — where a working app fails on an early beta release — it’s best to go straight to Feedback Assistant.

Please post your bug number, just for the record.

ps You might want to consider putting your next follow-up in a new thread. Forums is happier with more, shorter threads. And as long as you use the same subtopic and tags as this thread, I’ll see it go by.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Getting a basic URL Filter to work
 
 
Q