Implement actual policy
This commit is contained in:
@@ -91,7 +91,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
|
||||
var allowJavaScript = tab.javaScriptEnabled
|
||||
if !allowJavaScript, let host = navigationAction.request.url?.host {
|
||||
// Check origin policy
|
||||
allowJavaScript = policyManager.allowedOriginsForScriptResources().contains(host)
|
||||
allowJavaScript = policyManager.scriptPolicy(forOrigin: host).allowsEmbeddedJavaScript()
|
||||
}
|
||||
|
||||
preferences.allowsContentJavaScript = allowJavaScript
|
||||
|
||||
@@ -84,9 +84,11 @@
|
||||
_processPool = [[WKProcessPool alloc] _initWithConfiguration:poolConfiguration];
|
||||
|
||||
// Initialize allowed origins now
|
||||
NSDictionary<NSString *, NSNumber *> *policies = [_policyDataSource scriptPolicyTypeByOrigin];
|
||||
NSArray<NSString *> *allowedOrigins = [[_policyDataSource allowedOriginsForScriptResources] allObjects];
|
||||
[_processPool _setObject:allowedOrigins forBundleParameter:SBRGetAllowedOriginsKey()];
|
||||
[_processPool _setObject:@(_allowAllScripts) forBundleParameter:SBRGetAllScriptsAllowedKey()];
|
||||
[_processPool _setObject:policies forBundleParameter:SBRGetPolicyTypeByOriginKey()];
|
||||
|
||||
webViewConfiguration.processPool = _processPool;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ NS_SWIFT_NAME(ScriptPolicy)
|
||||
|
||||
- (instancetype)initWithSecurityOrigin:(NSString *)origin policyType:(SBRScriptOriginPolicyType)policyType;
|
||||
|
||||
/// Returns YES if policy type allows embedded (<script>) JavaScript for the given origin.
|
||||
- (BOOL)allowsEmbeddedJavaScript;
|
||||
|
||||
/// Returns YES if policy allows loading external JavaScript resource with the security origin `resourceOrigin`.
|
||||
- (BOOL)allowsExternalJavaScriptResourceOrigin:(NSString *)resourceOrigin;
|
||||
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
@end
|
||||
|
||||
|
||||
@@ -12,6 +12,32 @@
|
||||
|
||||
@implementation SBRScriptPolicy
|
||||
|
||||
+ (NSSet<NSString *> *)_commonCDNOrigins {
|
||||
static dispatch_once_t onceToken;
|
||||
static NSSet<NSString *> *whitelist = nil;
|
||||
dispatch_once(&onceToken, ^{
|
||||
whitelist = [NSSet setWithArray:@[
|
||||
// JSDelivr: Used by bootstrap
|
||||
@"cdn.jsdelivr.net",
|
||||
|
||||
// SourceForge
|
||||
@"fsdn.net",
|
||||
|
||||
// Open Source CDNs
|
||||
@"cdnjs.com",
|
||||
@"osscdn.com",
|
||||
|
||||
// JQuery
|
||||
@"code.jquery.com",
|
||||
|
||||
// Bootstrap
|
||||
@"bootstrapcdn.com",
|
||||
]];
|
||||
});
|
||||
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
+ (NSString *)titleForPolicyType:(SBRScriptOriginPolicyType)policyType
|
||||
{
|
||||
switch (policyType) {
|
||||
@@ -118,4 +144,62 @@
|
||||
[coder encodeObject:[NSNumber numberWithInteger:_policyType] forKey:@"policyType"];
|
||||
}
|
||||
|
||||
- (BOOL)allowsEmbeddedJavaScript
|
||||
{
|
||||
return _policyType > SBRScriptOriginPolicyTypeAlpha;
|
||||
}
|
||||
|
||||
- (BOOL)allowsExternalJavaScriptResourceOrigin:(NSString *)resourceOrigin
|
||||
{
|
||||
switch (_policyType) {
|
||||
case SBRScriptOriginPolicyTypeAlpha:
|
||||
// No scripts allowed whatsoever.
|
||||
return NO;
|
||||
case SBRScriptOriginPolicyTypeBravo:
|
||||
// Only allows on-page scripts, no external scripts whatsoever.
|
||||
return NO;
|
||||
case SBRScriptOriginPolicyTypeCharlie:
|
||||
// Only allow scripts from the exact same origin as the host.
|
||||
return [_origin isEqualToString:resourceOrigin];
|
||||
case SBRScriptOriginPolicyTypeDelta: {
|
||||
// Allow scripts from common CDNs, or CDNs that *appear* to belong to the host.
|
||||
if ([[[self class] _commonCDNOrigins] containsObject:resourceOrigin]) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
BOOL looksLikeCDN = NO;
|
||||
NSArray<NSString *> *hostOriginComponents = [_origin componentsSeparatedByString:@"."];
|
||||
if ([hostOriginComponents count] > 1) {
|
||||
// Assume our "family" name is just before the TLD.
|
||||
NSString *hostFamilyName = [hostOriginComponents objectAtIndex:(hostOriginComponents.count - 2)];
|
||||
looksLikeCDN = [resourceOrigin containsString:hostFamilyName];
|
||||
|
||||
if (!looksLikeCDN) {
|
||||
NSArray<NSString *> *resourceOriginComponents = [resourceOrigin componentsSeparatedByString:@"."];
|
||||
if ([resourceOriginComponents count] > 1) {
|
||||
NSString *resourceFamilyName = [resourceOriginComponents objectAtIndex:(resourceOriginComponents.count - 2)];
|
||||
|
||||
// Check and see if the subdomain is "cdn", but also make sure we're not accidentally allowing an ad network CDN.
|
||||
looksLikeCDN = [[resourceOriginComponents firstObject] isEqualToString:@"cdn"];
|
||||
|
||||
BOOL looksLikeAdNetwork = (
|
||||
[resourceFamilyName hasSuffix:@"ad"] ||
|
||||
[resourceFamilyName hasSuffix:@"ads"] ||
|
||||
[resourceFamilyName containsString:@"analy"] // "analy-tics"
|
||||
);
|
||||
looksLikeCDN = looksLikeCDN && !looksLikeAdNetwork;
|
||||
|
||||
NSLog(@"SBRProcessPlugin: [%@] CDN:%@ AD:%@", resourceOriginComponents, looksLikeCDN ? @"YES" : @"NO", looksLikeAdNetwork ? @"YES" : @"NO");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return looksLikeCDN;
|
||||
}
|
||||
case SBRScriptOriginPolicyTypeEcho:
|
||||
// Anything goes.
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user