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).

It’s been another month and a half, any updates? At least about the "App Store Connect auto-rejects apps with URL Filter extension” issue?

I’ve no info to share right now, but lemme go ping some folks…

Share and Enjoy

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

OK, I got a response, which is good, but I can’t share a concrete timeline [1]. What I can say is that:

  • Your bug is with the right folks.
  • They understand the urgency of this.
  • That urgency will only increase as more developers complete their URL filter projects and receive approval for their relays.

I will continue to monitor this situation but, honestly, you might hear about the fix via Feedback Assistant before I notice it.

Share and Enjoy

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

[1] There’s nothing special about that; it’s just our standard rules of engagement here on the forums. See tip 3 in Quinn’s Top Ten DevForums Tips.

Should I take that to mean that the relay validation thing is happening, now? I’ve submitted mine in August; should I submit another one or does my first submission still have a chance to be looked at?

Should I take that to mean that the relay validation thing is happening, now?

There are two things in play here:

  • Your request for relay support (r. 159656262)
  • The App Store submission problem (FB19582905)

My understanding is that the first is done with, that is, you are approved to use the relay. That leaves the second, which is what I was talking about in Friday’s post.

Share and Enjoy

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

Wow, a) I’d assumed they’d tell me something if I was approved, and b) I cannot believe I got the configuration right on the first try without being able to test 😅

I’d assumed they’d tell me something if I was approved

Indeed. We’re still working out the kinks in this process.

Share and Enjoy

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

It's mid February and I am trying to upload an app (just to TestFlight) with a url-content-filter. I am getting the same error:

Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, value 'url-filter-provider' for key 'com.apple.developer.networking.networkextension'

Is this just still not available? How do we proceed with using this entitlement?

@DTS Engineer It's mid February and I am trying to upload an app (just to TestFlight) with a url-content-filter. I am getting the same error: Your application bundle's signature contains code signing entitlements that are not supported on iOS. Specifically, value 'url-filter-provider' for key 'com.apple.developer.networking.networkextension' Is this just still not available? How do we proceed with using this entitlement?

I figured this out I think:

  26 -    <string>com.apple.networkextension.url-filter            
     --control</string>                                        
  26 +    <string>com.apple.networkextension.url-filter            
     +</string>     

The correct value to put in the entitlement is url-filter-provider. Annoyingly, this hasn’t yet made it to the documentation (r. 164079609) but Xcode’s Signing & Capabilities editor does the right thing.

Regarding KayleeSC’s bug about app submission (FB19582905) I continue to monitor that internally, but I’ve nothing concrete about its status other than that it remains un-fixed )-:

Share and Enjoy

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

@KayleeSC How did you get the bloomFilter hash correct? I followed your process from earlier in this thread. I used the MurmurHash3 swift library, but the standard FNV-1a implementation instead of the inverted order of operations you suggested. (An apple dev told me to do it this way)

The hash this produces still isn't blocking sites for me.

Is this the hash you got for the 10 example websites in the starter code? UzDsxTWvY7Y/grhkQS1KZe8SslPAGOFK

@DTS Engineer I think that was the EXExtensionPointIdentifier in the info.plist of the URL FIlter, not entitlements.

@beacham haven’t had a chance to try this, but wouldn’t changing the extension point identifier prevent the extension from being recognized at all? Like, can you upload the app to TestFlight and have the extension function?

@KayleeSC , Please take another run at submitting your app. I just checked on FB19582905 and there’s signs of movement there [1].

Share and Enjoy

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

[1] Our bugs system should officially notify you of this soon, but I figured you’d appreciate a heads up as soon as possible.

Ok, I was able to upload a build containing the extension! I will release it to TestFlight soon, even tho the actual filtering doesn’t work atm, due to the server part.

I’m using @ameshkov’s tester (thank you!!) and everything seems to be ok with my server stuff; however when I actually try to turn the feature on I always get this:

<NEPIRChecker: 0xd65178d00>: -[NEPIRChecker start:responseQueue:completionHandler:]_block_invoke - PIR status returned error <Error Domain=com.apple.CipherML Code=1100 "Unable to query status due to errors: failed to fetch token key" UserInfo={NSLocalizedDescription=Unable to query status due to errors: failed to fetch token key, NSUnderlyingError=0xd64d70810 {Error Domain=CipherML.AuthenticationError Code=7 "failed to fetch token key" UserInfo={NSLocalizedDescription=failed to fetch token key}}}>

Does this mean the server stuff was not certified?

I think I finally did it! I eventually gave up and switched to a different gateway: https://github.com/gruberb/ohttp-gateway

Once configured properly, everything started flowing, even from TestFlight (which I hope means that it will be the same from the App Store).

Feels kinda unreal that this is actually happening, I had lost hope. Thanks to everyone who helped out!

@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).

Feels kinda unreal that this is actually happening

Yay!


I am still getting this when pushing to Testflight:

NSExtensionPointIdentifier is associated with old-style Foundation extensions, whereas URL filters are based on new-style ExtensionKit extensions. I downloaded and built the latest version of the Filtering traffic by URL sample. Consider this:

% grep NSExtensionPointIdentifier -r SimpleURLFilter.app
% 

and this:

% plutil -p SimpleURLFilter.app/Extensions/SimpleURLFilterExtension.appex/Info.plist 
{
  …
  "EXAppExtensionAttributes" => {
    "EXExtensionPointIdentifier" => "com.apple.networkextension.url-filter-control"
  }
  …
}

Share and Enjoy

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

Of course the new beta would break the whole thing immediately 😅

Now all I get is

<NEPIRChecker: 0x6a7057180>: -[NEPIRChecker start:responseQueue:completionHandler:] - failed to register with PIR for Group site.kaylees.Wipr2 usecase site.kaylees.Wipr2.url.filtering

even with no errors on the server side.

My kingdom for a flag to ignore the PIR server completely and just “fail closed” on the bloom filter. Why do we even need to register with the server in order to enable a “fail closed” filter? I see that pirSkipRegistration flag in the logs, can we have it please? 😬

Or like a normal API with a JSON file like Content Blockers and regex and bundle ID filtering, but I guess that’s asking too much 😬

Of course the new beta would break the whole thing immediately

So lemme see if I understand this problem:

  • Your app on TestFlight works on iOS 26.3.
  • But fails with that error an iOS 26.4b3.

Is that right?

Share and Enjoy

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

That’s what was happening last night 😅

Currently (on the latest beta), I always get that error when trying to activate the TestFlight build. However, some testers have reported being able to activate 🤷‍♀️

But (still on the latest beta) versions installed from Xcode eventually activate. They flip many times between “busy” and “error” before tho, but that’s not new. It takes like a minute for the NEURLFilterManager.Status to eventually go to running. Once it does, everything works.

I don’t see any new errors on the server side, always the same two that were already common two days ago when everything was working, so I don’t think these are related, but here goes anyway:

Gateway:

2026-03-03T13:01:21.886520Z ERROR ThreadId(02) http_request{request_id=508c3c86-e2e2-440b-901e-0041f5928152 method=POST uri=/gateway user_agent=unknown}: ohttp_gateway::handlers::ohttp: Failed to decapsulate OHTTP request: a problem occurred with HPKE: Failed to open ciphertext

PIR:

2026-03-03T12:50:16+0000 error id=8836ee4457e3aa7dce6037645e7783cc [PIRService] HTTPError: Bad Request, Evaluation key not found

All I see on the server side when trying to activate is a few GETs to /.well-known/private-token-issuer-directory which appear to succeed.

I’ve restarted everything on the server but no change.

Any guidance in how to debug this would be extremely appreciated!

Still banging my head on this 😬

Thanks to the author of the gateway software I’m using we figured out those errors, and everything seems good on that front.

Still getting a lot of Bad Request, Evaluation key not found errors during queries. The sample project documentation says these should happen when the server is restarted bc old keys are cached, but they happen all the time. Still, this is only on the /queries endpoint, which is not involved in setup (afaik).

The client is still at times throwing this on TestFlight builds:

<NEPIRChecker: 0xbc2c4ae00>: -[NEPIRChecker start:responseQueue:completionHandler:] - failed to register with PIR for Group site.kaylees.Wipr2 usecase site.kaylees.Wipr2.url.filtering

The thing is, all other endpoints always work with no issues: /.well-known/private-token-issuer-directory, /token-key-for-user-token, /issue, /config, and /key are always successful. As far as I can tell, this should be enough for registration.

What exactly does the failed to register with PIR error mean?

What exactly does the failed to register with PIR error mean?

It’s hard to say without more information.

That log entry is recorded by NE when it fails to register with some underlying infrastructure. That registration mechanism follows standard Objective-C error conventions, that is, it has a method result and if that indicates an error, by returning NO, there’s an ‘out’ error parameter. NE checks the method result and sees the failure but it doesn’t record the error.

It’s possible that the error is being logged by the underlying code. Do you see any correlated log entries with a subsystem of com.apple.cipherml.

Share and Enjoy

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

Yes actually! This one

7214 error 19:24:29.268275+0100 framework configureUseCaseGroup(withName:useCaseGroup:) threw an error: CipherML.CipherMLError.unsupportedNetworkURL(url: https://pir.kaylees.site/)

or later

configureGroupWithName:useCaseGroup:error: Request complete error:Error Domain=com.apple.CipherML Code=1400 "Unable to configure use-case group: unsupported network URL: https://pir.kaylees.site/" UserInfo={NSLocalizedDescription=Unable to configure use-case group: unsupported network URL: https://pir.kaylees.site/, NSUnderlyingError=0x736c3de60 {Error Domain=CipherML.CipherMLError Code=12 "unsupported network URL: https://pir.kaylees.site/" UserInfo={NSLocalizedDescription=unsupported network URL: https://pir.kaylees.site/}}}

“unsupported”?

As far as I can tell, the device makes no attempt to contact the server.

This only happen with TestFlight builds on the latest beta. Every other combination seems to work fine.

I would try to debug this but I think it’s private API, and it’s pretty hard if I have to release a new TestFlight build every time 😅

Omg it was the / at the end. I’m gonna send this to the testers and see if that’s it.

Getting a basic URL Filter to work
 
 
Q