fix: prevent asset conflicts between React and Grid.js versions

Add coexistence checks to all enqueue methods to prevent loading
both React and Grid.js assets simultaneously.

Changes:
- ReactAdmin.php: Only enqueue React assets when ?react=1
- Init.php: Skip Grid.js when React active on admin pages
- Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0
- Customer.php, Product.php, License.php: Add coexistence checks

Now the toggle between Classic and React versions works correctly.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
dwindown
2026-04-18 17:02:14 +07:00
parent bd9cdac02e
commit e8fbfb14c1
74973 changed files with 6658406 additions and 71 deletions

View File

@@ -0,0 +1,2 @@
export declare const URLS: string[];
//# sourceMappingURL=angular.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"angular.d.ts","sourceRoot":"","sources":["../../allowlist_bypasses/angular.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,IAAI,EAAE,MAAM,EA0CxB,CAAC"}

View File

@@ -0,0 +1,47 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.URLS = void 0;
exports.URLS = [
'//gstatic.com/fsn/angular_js-bundle1.js',
'//www.gstatic.com/fsn/angular_js-bundle1.js',
'//www.googleadservices.com/pageadimg/imgad',
'//yandex.st/angularjs/1.2.16/angular-cookies.min.js',
'//yastatic.net/angularjs/1.2.23/angular.min.js',
'//yuedust.yuedu.126.net/js/components/angular/angular.js',
'//art.jobs.netease.com/script/angular.js',
'//csu-c45.kxcdn.com/angular/angular.js',
'//elysiumwebsite.s3.amazonaws.com/uploads/blog-media/rockstar/angular.min.js',
'//inno.blob.core.windows.net/new/libs/AngularJS/1.2.1/angular.min.js',
'//gift-talk.kakao.com/public/javascripts/angular.min.js',
'//ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular-route.min.js',
'//master-sumok.ru/vendors/angular/angular-cookies.js',
'//ayicommon-a.akamaihd.net/static/vendor/angular-1.4.2.min.js',
'//pangxiehaitao.com/framework/angular-1.3.9/angular-animate.min.js',
'//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.16/angular.min.js',
'//96fe3ee995e96e922b6b-d10c35bd0a0de2c718b252bc575fdb73.ssl.cf1.rackcdn.com/angular.js',
'//oss.maxcdn.com/angularjs/1.2.20/angular.min.js',
'//reports.zemanta.com/smedia/common/angularjs/1.2.11/angular.js',
'//cdn.shopify.com/s/files/1/0225/6463/t/1/assets/angular-animate.min.js',
'//parademanagement.com.s3-website-ap-southeast-1.amazonaws.com/js/angular.min.js',
'//cdn.jsdelivr.net/angularjs/1.1.2/angular.min.js',
'//eb2883ede55c53e09fd5-9c145fb03d93709ea57875d307e2d82e.ssl.cf3.rackcdn.com/components/angular-resource.min.js',
'//andors-trail.googlecode.com/git/AndorsTrailEdit/lib/angular.min.js',
'//cdn.walkme.com/General/EnvironmentTests/angular/angular.min.js',
'//laundrymail.com/angular/angular.js',
'//s3-eu-west-1.amazonaws.com/staticancpa/js/angular-cookies.min.js',
'//collade.demo.stswp.com/js/vendor/angular.min.js',
'//mrfishie.github.io/sailor/bower_components/angular/angular.min.js',
'//askgithub.com/static/js/angular.min.js',
'//services.amazon.com/solution-providers/assets/vendor/angular-cookies.min.js',
'//raw.githubusercontent.com/angular/code.angularjs.org/master/1.0.7/angular-resource.js',
'//prb-resume.appspot.com/bower_components/angular-animate/angular-animate.js',
'//dl.dropboxusercontent.com/u/30877786/angular.min.js',
'//static.tumblr.com/x5qdx0r/nPOnngtff/angular-resource.min_1_.js',
'//storage.googleapis.com/assets-prod.urbansitter.net/us-sym/assets/vendor/angular-sanitize/angular-sanitize.min.js',
'//twitter.github.io/labella.js/bower_components/angular/angular.min.js',
'//cdn2-casinoroom.global.ssl.fastly.net/js/lib/angular-animate.min.js',
'//www.adobe.com/devnet-apps/flashshowcase/lib/angular/angular.1.1.5.min.js',
'//eternal-sunset.herokuapp.com/bower_components/angular/angular.js',
'//cdn.bootcss.com/angular.js/1.2.0/angular.min.js'
];
//# sourceMappingURL=angular.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"angular.js","sourceRoot":"","sources":["../../allowlist_bypasses/angular.ts"],"names":[],"mappings":";;;AA0Ba,QAAA,IAAI,GAAa;IAC5B,yCAAyC;IACzC,6CAA6C;IAC7C,4CAA4C;IAC5C,qDAAqD;IACrD,gDAAgD;IAChD,0DAA0D;IAC1D,0CAA0C;IAC1C,wCAAwC;IACxC,8EAA8E;IAC9E,sEAAsE;IACtE,yDAAyD;IACzD,yEAAyE;IACzE,sDAAsD;IACtD,+DAA+D;IAC/D,oEAAoE;IACpE,mEAAmE;IACnE,wFAAwF;IACxF,kDAAkD;IAClD,iEAAiE;IACjE,yEAAyE;IACzE,kFAAkF;IAClF,mDAAmD;IACnD,gHAAgH;IAChH,sEAAsE;IACtE,kEAAkE;IAClE,sCAAsC;IACtC,oEAAoE;IACpE,mDAAmD;IACnD,qEAAqE;IACrE,0CAA0C;IAC1C,+EAA+E;IAC/E,yFAAyF;IACzF,8EAA8E;IAC9E,uDAAuD;IACvD,kEAAkE;IAClE,oHAAoH;IACpH,wEAAwE;IACxE,uEAAuE;IACvE,4EAA4E;IAC5E,oEAAoE;IACpE,mDAAmD;CACpD,CAAC"}

View File

@@ -0,0 +1,2 @@
export declare const URLS: string[];
//# sourceMappingURL=flash.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"flash.d.ts","sourceRoot":"","sources":["../../allowlist_bypasses/flash.ts"],"names":[],"mappings":"AA0BA,eAAO,MAAM,IAAI,EAAE,MAAM,EAGxB,CAAC"}

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.URLS = void 0;
exports.URLS = [
'//vk.com/swf/video.swf',
'//ajax.googleapis.com/ajax/libs/yui/2.8.0r4/build/charts/assets/charts.swf'
];
//# sourceMappingURL=flash.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"flash.js","sourceRoot":"","sources":["../../allowlist_bypasses/flash.ts"],"names":[],"mappings":";;;AA0Ba,QAAA,IAAI,GAAa;IAC5B,wBAAwB;IACxB,4EAA4E;CAC7E,CAAC"}

View File

@@ -0,0 +1,3 @@
export declare const NEEDS_EVAL: string[];
export declare const URLS: string[];
//# sourceMappingURL=jsonp.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"jsonp.d.ts","sourceRoot":"","sources":["../../allowlist_bypasses/jsonp.ts"],"names":[],"mappings":"AA6BA,eAAO,MAAM,UAAU,EAAE,MAAM,EAK9B,CAAC;AAUF,eAAO,MAAM,IAAI,EAAE,MAAM,EA6HxB,CAAC"}

View File

@@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.URLS = exports.NEEDS_EVAL = void 0;
exports.NEEDS_EVAL = [
'googletagmanager.com', 'www.googletagmanager.com',
'www.googleadservices.com', 'google-analytics.com',
'ssl.google-analytics.com', 'www.google-analytics.com'
];
exports.URLS = [
'//bebezoo.1688.com/fragment/index.htm',
'//www.google-analytics.com/gtm/js',
'//googleads.g.doubleclick.net/pagead/conversion/1036918760/wcm',
'//www.googleadservices.com/pagead/conversion/1070110417/wcm',
'//www.google.com/tools/feedback/escalation-options',
'//pin.aliyun.com/check_audio',
'//offer.alibaba.com/market/CID100002954/5/fetchKeyword.do',
'//ccrprod.alipay.com/ccr/arriveTime.json',
'//group.aliexpress.com/ajaxAcquireGroupbuyProduct.do',
'//detector.alicdn.com/2.7.3/index.php',
'//suggest.taobao.com/sug',
'//translate.google.com/translate_a/l',
'//count.tbcdn.cn//counter3',
'//wb.amap.com/channel.php',
'//translate.googleapis.com/translate_a/l',
'//afpeng.alimama.com/ex',
'//accounts.google.com/o/oauth2/revoke',
'//pagead2.googlesyndication.com/relatedsearch',
'//yandex.ru/soft/browsers/check',
'//api.facebook.com/restserver.php',
'//mts0.googleapis.com/maps/vt',
'//syndication.twitter.com/widgets/timelines/765840589183213568',
'//www.youtube.com/profile_style',
'//googletagmanager.com/gtm/js',
'//mc.yandex.ru/watch/24306916/1',
'//share.yandex.net/counter/gpp/',
'//ok.go.mail.ru/lady_on_lady_recipes_r.json',
'//d1f69o4buvlrj5.cloudfront.net/__efa_15_1_ornpba.xekq.arg/optout_check',
'//www.googletagmanager.com/gtm/js',
'//api.vk.com/method/wall.get',
'//www.sharethis.com/get-publisher-info.php',
'//google.ru/maps/vt',
'//pro.netrox.sc/oapi/h_checksite.ashx',
'//vimeo.com/api/oembed.json/',
'//de.blog.newrelic.com/wp-admin/admin-ajax.php',
'//ajax.googleapis.com/ajax/services/search/news',
'//ssl.google-analytics.com/gtm/js',
'//pubsub.pubnub.com/subscribe/demo/hello_world/',
'//pass.yandex.ua/services',
'//id.rambler.ru/script/topline_info.js',
'//m.addthis.com/live/red_lojson/100eng.json',
'//passport.ngs.ru/ajax/check',
'//catalog.api.2gis.ru/ads/search',
'//gum.criteo.com/sync',
'//maps.google.com/maps/vt',
'//ynuf.alipay.com/service/um.json',
'//securepubads.g.doubleclick.net/gampad/ads',
'//c.tiles.mapbox.com/v3/texastribune.tx-congress-cvap/6/15/26.grid.json',
'//rexchange.begun.ru/banners',
'//an.yandex.ru/page/147484',
'//links.services.disqus.com/api/ping',
'//api.map.baidu.com/',
'//tj.gongchang.com/api/keywordrecomm/',
'//data.gongchang.com/livegrail/',
'//ulogin.ru/token.php',
'//beta.gismeteo.ru/api/informer/layout.js/120x240-3/ru/',
'//maps.googleapis.com/maps/api/js/GeoPhotoService.GetMetadata',
'//a.config.skype.com/config/v1/Skype/908_1.33.0.111/SkypePersonalization',
'//maps.beeline.ru/w',
'//target.ukr.net/',
'//www.meteoprog.ua/data/weather/informer/Poltava.js',
'//cdn.syndication.twimg.com/widgets/timelines/599200054310604802',
'//wslocker.ru/client/user.chk.php',
'//community.adobe.com/CommunityPod/getJSON',
'//maps.google.lv/maps/vt',
'//dev.virtualearth.net/REST/V1/Imagery/Metadata/AerialWithLabels/26.318581',
'//awaps.yandex.ru/10/8938/02400400.',
'//a248.e.akamai.net/h5.hulu.com/h5.mp4',
'//nominatim.openstreetmap.org/',
'//plugins.mozilla.org/en-us/plugins_list.json',
'//h.cackle.me/widget/32153/bootstrap',
'//graph.facebook.com/1/',
'//fellowes.ugc.bazaarvoice.com/data/reviews.json',
'//widgets.pinterest.com/v3/pidgets/boards/ciciwin/hedgehog-squirrel-crafts/pins/',
'//www.linkedin.com/countserv/count/share',
'//se.wikipedia.org/w/api.php',
'//cse.google.com/api/007627024705277327428/cse/r3vs7b0fcli/queries/js',
'//relap.io/api/v2/similar_pages_jsonp.js',
'//c1n3.hypercomments.com/stream/subscribe',
'//maps.google.de/maps/vt',
'//books.google.com/books',
'//connect.mail.ru/share_count',
'//tr.indeed.com/m/newjobs',
'//www-onepick-opensocial.googleusercontent.com/gadgets/proxy',
'//www.panoramio.com/map/get_panoramas.php',
'//client.siteheart.com/streamcli/client',
'//www.facebook.com/restserver.php',
'//autocomplete.travelpayouts.com/avia',
'//www.googleapis.com/freebase/v1/topic/m/0344_',
'//mts1.googleapis.com/mapslt/ft',
'//api.twitter.com/1/statuses/oembed.json',
'//fast.wistia.com/embed/medias/o75jtw7654.json',
'//partner.googleadservices.com/gampad/ads',
'//pass.yandex.ru/services',
'//gupiao.baidu.com/stocks/stockbets',
'//widget.admitad.com/widget/init',
'//api.instagram.com/v1/tags/partykungen23328/media/recent',
'//video.media.yql.yahoo.com/v1/video/sapi/streams/063fb76c-6c70-38c5-9bbc-04b7c384de2b',
'//ib.adnxs.com/jpt',
'//pass.yandex.com/services',
'//www.google.de/maps/vt',
'//clients1.google.com/complete/search',
'//api.userlike.com/api/chat/slot/proactive/',
'//www.youku.com/index_cookielist/s/jsonp',
'//mt1.googleapis.com/mapslt/ft',
'//api.mixpanel.com/track/',
'//wpd.b.qq.com/cgi/get_sign.php',
'//pipes.yahooapis.com/pipes/pipe.run',
'//gdata.youtube.com/feeds/api/videos/WsJIHN1kNWc',
'//9.chart.apis.google.com/chart',
'//cdn.syndication.twitter.com/moments/709229296800440320',
'//api.flickr.com/services/feeds/photos_friends.gne',
'//cbks0.googleapis.com/cbk',
'//www.blogger.com/feeds/5578653387562324002/posts/summary/4427562025302749269',
'//query.yahooapis.com/v1/public/yql',
'//kecngantang.blogspot.com/feeds/posts/default/-/Komik',
'//www.travelpayouts.com/widgets/50f53ce9ada1b54bcc000031.json',
'//i.cackle.me/widget/32586/bootstrap',
'//translate.yandex.net/api/v1.5/tr.json/detect',
'//a.tiles.mapbox.com/v3/zentralmedia.map-n2raeauc.jsonp',
'//maps.google.ru/maps/vt',
'//c1n2.hypercomments.com/stream/subscribe',
'//rec.ydf.yandex.ru/cookie',
'//cdn.jsdelivr.net'
];
//# sourceMappingURL=jsonp.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"jsonp.js","sourceRoot":"","sources":["../../allowlist_bypasses/jsonp.ts"],"names":[],"mappings":";;;AA6Ba,QAAA,UAAU,GAAa;IAClC,sBAAsB,EAAE,0BAA0B;IAElD,0BAA0B,EAAE,sBAAsB;IAClD,0BAA0B,EAAE,0BAA0B;CACvD,CAAC;AAUW,QAAA,IAAI,GAAa;IAC5B,uCAAuC;IACvC,mCAAmC;IACnC,gEAAgE;IAChE,6DAA6D;IAC7D,oDAAoD;IACpD,8BAA8B;IAC9B,2DAA2D;IAC3D,0CAA0C;IAC1C,sDAAsD;IACtD,uCAAuC;IACvC,0BAA0B;IAC1B,sCAAsC;IACtC,4BAA4B;IAC5B,2BAA2B;IAC3B,0CAA0C;IAC1C,yBAAyB;IACzB,uCAAuC;IACvC,+CAA+C;IAC/C,iCAAiC;IACjC,mCAAmC;IACnC,+BAA+B;IAC/B,gEAAgE;IAChE,iCAAiC;IACjC,+BAA+B;IAC/B,iCAAiC;IACjC,iCAAiC;IACjC,6CAA6C;IAC7C,yEAAyE;IACzE,mCAAmC;IACnC,8BAA8B;IAC9B,4CAA4C;IAC5C,qBAAqB;IACrB,uCAAuC;IACvC,8BAA8B;IAC9B,gDAAgD;IAChD,iDAAiD;IACjD,mCAAmC;IACnC,iDAAiD;IACjD,2BAA2B;IAC3B,wCAAwC;IACxC,6CAA6C;IAC7C,8BAA8B;IAC9B,kCAAkC;IAClC,uBAAuB;IACvB,2BAA2B;IAC3B,mCAAmC;IACnC,6CAA6C;IAC7C,yEAAyE;IACzE,8BAA8B;IAC9B,4BAA4B;IAC5B,sCAAsC;IACtC,sBAAsB;IACtB,uCAAuC;IACvC,iCAAiC;IACjC,uBAAuB;IACvB,yDAAyD;IACzD,+DAA+D;IAC/D,0EAA0E;IAC1E,qBAAqB;IACrB,mBAAmB;IACnB,qDAAqD;IACrD,kEAAkE;IAClE,mCAAmC;IACnC,4CAA4C;IAC5C,0BAA0B;IAC1B,4EAA4E;IAC5E,qCAAqC;IACrC,wCAAwC;IACxC,gCAAgC;IAChC,+CAA+C;IAC/C,sCAAsC;IACtC,yBAAyB;IACzB,kDAAkD;IAClD,kFAAkF;IAClF,0CAA0C;IAC1C,8BAA8B;IAC9B,uEAAuE;IACvE,0CAA0C;IAC1C,2CAA2C;IAC3C,0BAA0B;IAC1B,0BAA0B;IAC1B,+BAA+B;IAC/B,2BAA2B;IAC3B,8DAA8D;IAC9D,2CAA2C;IAC3C,yCAAyC;IACzC,mCAAmC;IACnC,uCAAuC;IACvC,gDAAgD;IAChD,iCAAiC;IACjC,0CAA0C;IAC1C,gDAAgD;IAChD,2CAA2C;IAC3C,2BAA2B;IAC3B,qCAAqC;IACrC,kCAAkC;IAClC,2DAA2D;IAC3D,wFAAwF;IACxF,oBAAoB;IACpB,4BAA4B;IAC5B,yBAAyB;IACzB,uCAAuC;IACvC,6CAA6C;IAC7C,0CAA0C;IAC1C,gCAAgC;IAChC,2BAA2B;IAC3B,iCAAiC;IACjC,sCAAsC;IACtC,kDAAkD;IAClD,iCAAiC;IACjC,0DAA0D;IAC1D,oDAAoD;IACpD,4BAA4B;IAC5B,+EAA+E;IAC/E,qCAAqC;IACrC,wDAAwD;IACxD,+DAA+D;IAC/D,sCAAsC;IACtC,gDAAgD;IAChD,yDAAyD;IACzD,0BAA0B;IAC1B,2CAA2C;IAC3C,4BAA4B;IAC5B,oBAAoB;CACrB,CAAC"}

4
node_modules/csp_evaluator/dist/checks/checker.d.ts generated vendored Normal file
View File

@@ -0,0 +1,4 @@
import { Csp } from '../csp';
import { Finding } from '../finding';
export declare type CheckerFunction = (csp: Csp) => Finding[];
//# sourceMappingURL=checker.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"checker.d.ts","sourceRoot":"","sources":["../../checks/checker.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,GAAG,EAAC,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AAMnC,oBAAY,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,EAAE,CAAC"}

3
node_modules/csp_evaluator/dist/checks/checker.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=checker.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"checker.js","sourceRoot":"","sources":["../../checks/checker.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,6 @@
import { Csp } from '../csp';
import { Finding } from '../finding';
export declare function checkUnknownDirective(parsedCsp: Csp): Finding[];
export declare function checkMissingSemicolon(parsedCsp: Csp): Finding[];
export declare function checkInvalidKeyword(parsedCsp: Csp): Finding[];
//# sourceMappingURL=parser_checks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_checks.d.ts","sourceRoot":"","sources":["../../checks/parser_checks.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAC,GAAG,EAAU,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAC,OAAO,EAAiB,MAAM,YAAY,CAAC;AAWnD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAsB/D;AAYD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAsB/D;AAWD,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAoD7D"}

View File

@@ -0,0 +1,96 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkInvalidKeyword = exports.checkMissingSemicolon = exports.checkUnknownDirective = void 0;
const csp = __importStar(require("../csp"));
const csp_1 = require("../csp");
const finding_1 = require("../finding");
function checkUnknownDirective(parsedCsp) {
const findings = [];
for (const directive of Object.keys(parsedCsp.directives)) {
if (csp.isDirective(directive)) {
continue;
}
if (directive.endsWith(':')) {
findings.push(new finding_1.Finding(finding_1.Type.UNKNOWN_DIRECTIVE, 'CSP directives don\'t end with a colon.', finding_1.Severity.SYNTAX, directive));
}
else {
findings.push(new finding_1.Finding(finding_1.Type.UNKNOWN_DIRECTIVE, 'Directive "' + directive + '" is not a known CSP directive.', finding_1.Severity.SYNTAX, directive));
}
}
return findings;
}
exports.checkUnknownDirective = checkUnknownDirective;
function checkMissingSemicolon(parsedCsp) {
const findings = [];
for (const [directive, directiveValues] of Object.entries(parsedCsp.directives)) {
if (directiveValues === undefined) {
continue;
}
for (const value of directiveValues) {
if (csp.isDirective(value)) {
findings.push(new finding_1.Finding(finding_1.Type.MISSING_SEMICOLON, 'Did you forget the semicolon? ' +
'"' + value + '" seems to be a directive, not a value.', finding_1.Severity.SYNTAX, directive, value));
}
}
}
return findings;
}
exports.checkMissingSemicolon = checkMissingSemicolon;
function checkInvalidKeyword(parsedCsp) {
const findings = [];
const keywordsNoTicks = Object.values(csp_1.Keyword).map((k) => k.replace(/'/g, ''));
for (const [directive, directiveValues] of Object.entries(parsedCsp.directives)) {
if (directiveValues === undefined) {
continue;
}
for (const value of directiveValues) {
if (keywordsNoTicks.some((k) => k === value) ||
value.startsWith('nonce-') ||
value.match(/^(sha256|sha384|sha512)-/)) {
findings.push(new finding_1.Finding(finding_1.Type.INVALID_KEYWORD, 'Did you forget to surround "' + value + '" with single-ticks?', finding_1.Severity.SYNTAX, directive, value));
continue;
}
if (!value.startsWith('\'')) {
continue;
}
if (directive === csp.Directive.REQUIRE_TRUSTED_TYPES_FOR) {
if (value === csp.TrustedTypesSink.SCRIPT) {
continue;
}
}
else if (directive === csp.Directive.TRUSTED_TYPES) {
if (value === '\'allow-duplicates\'' || value === '\'none\'') {
continue;
}
}
else {
if (csp.isKeyword(value) || csp.isHash(value) || csp.isNonce(value)) {
continue;
}
}
findings.push(new finding_1.Finding(finding_1.Type.INVALID_KEYWORD, value + ' seems to be an invalid CSP keyword.', finding_1.Severity.SYNTAX, directive, value));
}
}
return findings;
}
exports.checkInvalidKeyword = checkInvalidKeyword;
//# sourceMappingURL=parser_checks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_checks.js","sourceRoot":"","sources":["../../checks/parser_checks.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBA,4CAA8B;AAC9B,gCAAoC;AAEpC,wCAAmD;AAWnD,SAAgB,qBAAqB,CAAC,SAAc;IAClD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE;QACzD,IAAI,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE;YAE9B,SAAS;SACV;QAED,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;YAC3B,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CACrB,cAAI,CAAC,iBAAiB,EAAE,yCAAyC,EACjE,kBAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;SAClC;aAAM;YACL,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CACrB,cAAI,CAAC,iBAAiB,EACtB,aAAa,GAAG,SAAS,GAAG,iCAAiC,EAC7D,kBAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;SAClC;KACF;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAtBD,sDAsBC;AAYD,SAAgB,qBAAqB,CAAC,SAAc;IAClD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAE/B,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAChD,SAAS,CAAC,UAAU,CAAC,EAAE;QAC9B,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,SAAS;SACV;QACD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE;YAGnC,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE;gBAC1B,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CACrB,cAAI,CAAC,iBAAiB,EACtB,gCAAgC;oBAC5B,GAAG,GAAG,KAAK,GAAG,yCAAyC,EAC3D,kBAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;aACzC;SACF;KACF;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAtBD,sDAsBC;AAWD,SAAgB,mBAAmB,CAAC,SAAc;IAChD,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,eAAe,GACjB,MAAM,CAAC,MAAM,CAAC,aAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAE3D,KAAK,MAAM,CAAC,SAAS,EAAE,eAAe,CAAC,IAAI,MAAM,CAAC,OAAO,CAChD,SAAS,CAAC,UAAU,CAAC,EAAE;QAC9B,IAAI,eAAe,KAAK,SAAS,EAAE;YACjC,SAAS;SACV;QACD,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE;YAEnC,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC;gBACxC,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC;gBAC1B,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE;gBAC3C,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CACrB,cAAI,CAAC,eAAe,EACpB,8BAA8B,GAAG,KAAK,GAAG,sBAAsB,EAC/D,kBAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;gBACxC,SAAS;aACV;YAID,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;gBAC3B,SAAS;aACV;YAED,IAAI,SAAS,KAAK,GAAG,CAAC,SAAS,CAAC,yBAAyB,EAAE;gBAEzD,IAAI,KAAK,KAAK,GAAG,CAAC,gBAAgB,CAAC,MAAM,EAAE;oBACzC,SAAS;iBACV;aACF;iBAAM,IAAI,SAAS,KAAK,GAAG,CAAC,SAAS,CAAC,aAAa,EAAE;gBAEpD,IAAI,KAAK,KAAK,sBAAsB,IAAI,KAAK,KAAK,UAAU,EAAE;oBAC5D,SAAS;iBACV;aACF;iBAAM;gBAEL,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;oBACnE,SAAS;iBACV;aACF;YAED,QAAQ,CAAC,IAAI,CAAC,IAAI,iBAAO,CACrB,cAAI,CAAC,eAAe,EAAE,KAAK,GAAG,sCAAsC,EACpE,kBAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;SACzC;KACF;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AApDD,kDAoDC"}

View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=parser_checks_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_checks_test.d.ts","sourceRoot":"","sources":["../../checks/parser_checks_test.ts"],"names":[],"mappings":"AAmBA,OAAO,SAAS,CAAC"}

View File

@@ -0,0 +1,71 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const finding_1 = require("../finding");
const parser_1 = require("../parser");
const parserChecks = __importStar(require("./parser_checks"));
function checkCsp(test, checkFunction) {
const parsedCsp = (new parser_1.CspParser(test)).csp;
return checkFunction(parsedCsp);
}
describe('Test parser checks', () => {
it('CheckUnknownDirective', () => {
const test = 'foobar-src http:';
const violations = checkCsp(test, parserChecks.checkUnknownDirective);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0].directive).toBe('foobar-src');
});
it('CheckMissingSemicolon', () => {
const test = 'default-src foo.bar script-src \'none\'';
const violations = checkCsp(test, parserChecks.checkMissingSemicolon);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0].value).toBe('script-src');
});
it('CheckInvalidKeywordForgottenSingleTicks', () => {
const test = 'script-src strict-dynamic nonce-test sha256-asdf';
const violations = checkCsp(test, parserChecks.checkInvalidKeyword);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.SYNTAX)).toBeTrue();
expect(violations.every((v) => v.description.includes('single-ticks')))
.toBeTrue();
});
it('CheckInvalidKeywordUnknownKeyword', () => {
const test = 'script-src \'foo-bar\'';
const violations = checkCsp(test, parserChecks.checkInvalidKeyword);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0].value).toBe('\'foo-bar\'');
});
it('CheckInvalidKeywordAllowsRequireTrustedTypesForScript', () => {
const test = 'require-trusted-types-for \'script\'';
const violations = checkCsp(test, parserChecks.checkInvalidKeyword);
expect(violations.length).toBe(0);
});
it('CheckInvalidKeywordAllowsTrustedTypesAllowDuplicateKeyword', () => {
const test = 'trusted-types \'allow-duplicates\' policy1';
const violations = checkCsp(test, parserChecks.checkInvalidKeyword);
expect(violations.length).toBe(0);
});
});
//# sourceMappingURL=parser_checks_test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_checks_test.js","sourceRoot":"","sources":["../../checks/parser_checks_test.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,22 @@
import { Csp, Directive } from '../csp';
import { Finding } from '../finding';
export declare const DIRECTIVES_CAUSING_XSS: Directive[];
export declare const URL_SCHEMES_CAUSING_XSS: string[];
export declare function checkScriptUnsafeInline(effectiveCsp: Csp): Finding[];
export declare function checkScriptUnsafeEval(parsedCsp: Csp): Finding[];
export declare function checkPlainUrlSchemes(parsedCsp: Csp): Finding[];
export declare function checkWildcards(parsedCsp: Csp): Finding[];
export declare function checkMissingObjectSrcDirective(parsedCsp: Csp): Finding[];
export declare function checkMissingScriptSrcDirective(parsedCsp: Csp): Finding[];
export declare function checkMissingBaseUriDirective(parsedCsp: Csp): Finding[];
export declare function checkMultipleMissingBaseUriDirective(parsedCsps: Csp[]): Finding[];
export declare function checkMissingDirectives(parsedCsp: Csp): Finding[];
export declare function checkScriptAllowlistBypass(parsedCsp: Csp): Finding[];
export declare function checkFlashObjectAllowlistBypass(parsedCsp: Csp): Finding[];
export declare function looksLikeIpAddress(maybeIp: string): boolean;
export declare function checkIpSource(parsedCsp: Csp): Finding[];
export declare function checkDeprecatedDirective(parsedCsp: Csp): Finding[];
export declare function checkNonceLength(parsedCsp: Csp): Finding[];
export declare function checkSrcHttp(parsedCsp: Csp): Finding[];
export declare function checkHasConfiguredReporting(parsedCsp: Csp): Finding[];
//# sourceMappingURL=security_checks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"security_checks.d.ts","sourceRoot":"","sources":["../../checks/security_checks.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAC,GAAG,EAAE,SAAS,EAAU,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAC,OAAO,EAAiB,MAAM,YAAY,CAAC;AAQnD,eAAO,MAAM,sBAAsB,EAAE,SAAS,EACsB,CAAC;AAMrE,eAAO,MAAM,uBAAuB,EAAE,MAAM,EAAiC,CAAC;AAgB9E,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,GAAG,GAAG,OAAO,EAAE,CAepE;AAYD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAc/D;AAYD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAmB9D;AAYD,wBAAgB,cAAc,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAmBxD;AAMD,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAcxE;AAKD,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAQxE;AAMD,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAEtE;AAMD,wBAAgB,oCAAoC,CAAC,UAAU,EAAE,GAAG,EAAE,GAClE,OAAO,EAAE,CAkBZ;AAYD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAMhE;AAYD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAyEpE;AAYD,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAqCzE;AAOD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAc3D;AAWD,wBAAgB,aAAa,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CA8BvD;AAYD,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CA8BlE;AAYD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CA+B1D;AAYD,wBAAgB,YAAY,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAiBtD;AAKD,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAoBrE"}

View File

@@ -0,0 +1,304 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkHasConfiguredReporting = exports.checkSrcHttp = exports.checkNonceLength = exports.checkDeprecatedDirective = exports.checkIpSource = exports.looksLikeIpAddress = exports.checkFlashObjectAllowlistBypass = exports.checkScriptAllowlistBypass = exports.checkMissingDirectives = exports.checkMultipleMissingBaseUriDirective = exports.checkMissingBaseUriDirective = exports.checkMissingScriptSrcDirective = exports.checkMissingObjectSrcDirective = exports.checkWildcards = exports.checkPlainUrlSchemes = exports.checkScriptUnsafeEval = exports.checkScriptUnsafeInline = exports.URL_SCHEMES_CAUSING_XSS = exports.DIRECTIVES_CAUSING_XSS = void 0;
const angular = __importStar(require("../allowlist_bypasses/angular"));
const flash = __importStar(require("../allowlist_bypasses/flash"));
const jsonp = __importStar(require("../allowlist_bypasses/jsonp"));
const csp = __importStar(require("../csp"));
const csp_1 = require("../csp");
const finding_1 = require("../finding");
const utils = __importStar(require("../utils"));
exports.DIRECTIVES_CAUSING_XSS = [csp_1.Directive.SCRIPT_SRC, csp_1.Directive.OBJECT_SRC, csp_1.Directive.BASE_URI];
exports.URL_SCHEMES_CAUSING_XSS = ['data:', 'http:', 'https:'];
function checkScriptUnsafeInline(effectiveCsp) {
const directiveName = effectiveCsp.getEffectiveDirective(csp_1.Directive.SCRIPT_SRC);
const values = effectiveCsp.directives[directiveName] || [];
if (values.includes(csp_1.Keyword.UNSAFE_INLINE)) {
return [new finding_1.Finding(finding_1.Type.SCRIPT_UNSAFE_INLINE, `'unsafe-inline' allows the execution of unsafe in-page scripts ` +
'and event handlers.', finding_1.Severity.HIGH, directiveName, csp_1.Keyword.UNSAFE_INLINE)];
}
return [];
}
exports.checkScriptUnsafeInline = checkScriptUnsafeInline;
function checkScriptUnsafeEval(parsedCsp) {
const directiveName = parsedCsp.getEffectiveDirective(csp_1.Directive.SCRIPT_SRC);
const values = parsedCsp.directives[directiveName] || [];
if (values.includes(csp_1.Keyword.UNSAFE_EVAL)) {
return [new finding_1.Finding(finding_1.Type.SCRIPT_UNSAFE_EVAL, `'unsafe-eval' allows the execution of code injected into DOM APIs ` +
'such as eval().', finding_1.Severity.MEDIUM_MAYBE, directiveName, csp_1.Keyword.UNSAFE_EVAL)];
}
return [];
}
exports.checkScriptUnsafeEval = checkScriptUnsafeEval;
function checkPlainUrlSchemes(parsedCsp) {
const violations = [];
const directivesToCheck = parsedCsp.getEffectiveDirectives(exports.DIRECTIVES_CAUSING_XSS);
for (const directive of directivesToCheck) {
const values = parsedCsp.directives[directive] || [];
for (const value of values) {
if (exports.URL_SCHEMES_CAUSING_XSS.includes(value)) {
violations.push(new finding_1.Finding(finding_1.Type.PLAIN_URL_SCHEMES, value + ' URI in ' + directive + ' allows the execution of ' +
'unsafe scripts.', finding_1.Severity.HIGH, directive, value));
}
}
}
return violations;
}
exports.checkPlainUrlSchemes = checkPlainUrlSchemes;
function checkWildcards(parsedCsp) {
const violations = [];
const directivesToCheck = parsedCsp.getEffectiveDirectives(exports.DIRECTIVES_CAUSING_XSS);
for (const directive of directivesToCheck) {
const values = parsedCsp.directives[directive] || [];
for (const value of values) {
const url = utils.getSchemeFreeUrl(value);
if (url === '*') {
violations.push(new finding_1.Finding(finding_1.Type.PLAIN_WILDCARD, directive + ` should not allow '*' as source`, finding_1.Severity.HIGH, directive, value));
continue;
}
}
}
return violations;
}
exports.checkWildcards = checkWildcards;
function checkMissingObjectSrcDirective(parsedCsp) {
let objectRestrictions = [];
if (csp_1.Directive.OBJECT_SRC in parsedCsp.directives) {
objectRestrictions = parsedCsp.directives[csp_1.Directive.OBJECT_SRC];
}
else if (csp_1.Directive.DEFAULT_SRC in parsedCsp.directives) {
objectRestrictions = parsedCsp.directives[csp_1.Directive.DEFAULT_SRC];
}
if (objectRestrictions !== undefined && objectRestrictions.length >= 1) {
return [];
}
return [new finding_1.Finding(finding_1.Type.MISSING_DIRECTIVES, `Missing object-src allows the injection of plugins which can execute JavaScript. Can you set it to 'none'?`, finding_1.Severity.HIGH, csp_1.Directive.OBJECT_SRC)];
}
exports.checkMissingObjectSrcDirective = checkMissingObjectSrcDirective;
function checkMissingScriptSrcDirective(parsedCsp) {
if (csp_1.Directive.SCRIPT_SRC in parsedCsp.directives ||
csp_1.Directive.DEFAULT_SRC in parsedCsp.directives) {
return [];
}
return [new finding_1.Finding(finding_1.Type.MISSING_DIRECTIVES, 'script-src directive is missing.', finding_1.Severity.HIGH, csp_1.Directive.SCRIPT_SRC)];
}
exports.checkMissingScriptSrcDirective = checkMissingScriptSrcDirective;
function checkMissingBaseUriDirective(parsedCsp) {
return checkMultipleMissingBaseUriDirective([parsedCsp]);
}
exports.checkMissingBaseUriDirective = checkMissingBaseUriDirective;
function checkMultipleMissingBaseUriDirective(parsedCsps) {
const needsBaseUri = (csp) => (csp.policyHasScriptNonces() ||
(csp.policyHasScriptHashes() && csp.policyHasStrictDynamic()));
const hasBaseUri = (csp) => csp_1.Directive.BASE_URI in csp.directives;
if (parsedCsps.some(needsBaseUri) && !parsedCsps.some(hasBaseUri)) {
const description = 'Missing base-uri allows the injection of base tags. ' +
'They can be used to set the base URL for all relative (script) ' +
'URLs to an attacker controlled domain. ' +
`Can you set it to 'none' or 'self'?`;
return [new finding_1.Finding(finding_1.Type.MISSING_DIRECTIVES, description, finding_1.Severity.HIGH, csp_1.Directive.BASE_URI)];
}
return [];
}
exports.checkMultipleMissingBaseUriDirective = checkMultipleMissingBaseUriDirective;
function checkMissingDirectives(parsedCsp) {
return [
...checkMissingObjectSrcDirective(parsedCsp),
...checkMissingScriptSrcDirective(parsedCsp),
...checkMissingBaseUriDirective(parsedCsp),
];
}
exports.checkMissingDirectives = checkMissingDirectives;
function checkScriptAllowlistBypass(parsedCsp) {
const violations = [];
const effectiveScriptSrcDirective = parsedCsp.getEffectiveDirective(csp_1.Directive.SCRIPT_SRC);
const scriptSrcValues = parsedCsp.directives[effectiveScriptSrcDirective] || [];
if (scriptSrcValues.includes(csp_1.Keyword.NONE)) {
return violations;
}
for (const value of scriptSrcValues) {
if (value === csp_1.Keyword.SELF) {
violations.push(new finding_1.Finding(finding_1.Type.SCRIPT_ALLOWLIST_BYPASS, `'self' can be problematic if you host JSONP, AngularJS or user ` +
'uploaded files.', finding_1.Severity.MEDIUM_MAYBE, effectiveScriptSrcDirective, value));
continue;
}
if (value.startsWith('\'')) {
continue;
}
if (csp.isUrlScheme(value) || value.indexOf('.') === -1) {
continue;
}
const url = '//' + utils.getSchemeFreeUrl(value);
const angularBypass = utils.matchWildcardUrls(url, angular.URLS);
let jsonpBypass = utils.matchWildcardUrls(url, jsonp.URLS);
if (jsonpBypass) {
const evalRequired = jsonp.NEEDS_EVAL.includes(jsonpBypass.hostname);
const evalPresent = scriptSrcValues.includes(csp_1.Keyword.UNSAFE_EVAL);
if (evalRequired && !evalPresent) {
jsonpBypass = null;
}
}
if (jsonpBypass || angularBypass) {
let bypassDomain = '';
let bypassTxt = '';
if (jsonpBypass) {
bypassDomain = jsonpBypass.hostname;
bypassTxt = ' JSONP endpoints';
}
if (angularBypass) {
bypassDomain = angularBypass.hostname;
bypassTxt += (bypassTxt.trim() === '') ? '' : ' and';
bypassTxt += ' Angular libraries';
}
violations.push(new finding_1.Finding(finding_1.Type.SCRIPT_ALLOWLIST_BYPASS, bypassDomain + ' is known to host' + bypassTxt +
' which allow to bypass this CSP.', finding_1.Severity.HIGH, effectiveScriptSrcDirective, value));
}
else {
violations.push(new finding_1.Finding(finding_1.Type.SCRIPT_ALLOWLIST_BYPASS, `No bypass found; make sure that this URL doesn't serve JSONP ` +
'replies or Angular libraries.', finding_1.Severity.MEDIUM_MAYBE, effectiveScriptSrcDirective, value));
}
}
return violations;
}
exports.checkScriptAllowlistBypass = checkScriptAllowlistBypass;
function checkFlashObjectAllowlistBypass(parsedCsp) {
const violations = [];
const effectiveObjectSrcDirective = parsedCsp.getEffectiveDirective(csp_1.Directive.OBJECT_SRC);
const objectSrcValues = parsedCsp.directives[effectiveObjectSrcDirective] || [];
const pluginTypes = parsedCsp.directives[csp_1.Directive.PLUGIN_TYPES];
if (pluginTypes && !pluginTypes.includes('application/x-shockwave-flash')) {
return [];
}
for (const value of objectSrcValues) {
if (value === csp_1.Keyword.NONE) {
return [];
}
const url = '//' + utils.getSchemeFreeUrl(value);
const flashBypass = utils.matchWildcardUrls(url, flash.URLS);
if (flashBypass) {
violations.push(new finding_1.Finding(finding_1.Type.OBJECT_ALLOWLIST_BYPASS, flashBypass.hostname +
' is known to host Flash files which allow to bypass this CSP.', finding_1.Severity.HIGH, effectiveObjectSrcDirective, value));
}
else if (effectiveObjectSrcDirective === csp_1.Directive.OBJECT_SRC) {
violations.push(new finding_1.Finding(finding_1.Type.OBJECT_ALLOWLIST_BYPASS, `Can you restrict object-src to 'none' only?`, finding_1.Severity.MEDIUM_MAYBE, effectiveObjectSrcDirective, value));
}
}
return violations;
}
exports.checkFlashObjectAllowlistBypass = checkFlashObjectAllowlistBypass;
function looksLikeIpAddress(maybeIp) {
if (maybeIp.startsWith('[') && maybeIp.endsWith(']')) {
return true;
}
if (/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/.test(maybeIp)) {
return true;
}
return false;
}
exports.looksLikeIpAddress = looksLikeIpAddress;
function checkIpSource(parsedCsp) {
const violations = [];
const checkIp = (directive, directiveValues) => {
for (const value of directiveValues) {
const host = utils.getHostname(value);
if (looksLikeIpAddress(host)) {
if (host === '127.0.0.1') {
violations.push(new finding_1.Finding(finding_1.Type.IP_SOURCE, directive + ' directive allows localhost as source. ' +
'Please make sure to remove this in production environments.', finding_1.Severity.INFO, directive, value));
}
else {
violations.push(new finding_1.Finding(finding_1.Type.IP_SOURCE, directive + ' directive has an IP-Address as source: ' + host +
' (will be ignored by browsers!). ', finding_1.Severity.INFO, directive, value));
}
}
}
};
utils.applyCheckFunktionToDirectives(parsedCsp, checkIp);
return violations;
}
exports.checkIpSource = checkIpSource;
function checkDeprecatedDirective(parsedCsp) {
const violations = [];
if (csp_1.Directive.REFLECTED_XSS in parsedCsp.directives) {
violations.push(new finding_1.Finding(finding_1.Type.DEPRECATED_DIRECTIVE, 'reflected-xss is deprecated since CSP2. ' +
'Please, use the X-XSS-Protection header instead.', finding_1.Severity.INFO, csp_1.Directive.REFLECTED_XSS));
}
if (csp_1.Directive.REFERRER in parsedCsp.directives) {
violations.push(new finding_1.Finding(finding_1.Type.DEPRECATED_DIRECTIVE, 'referrer is deprecated since CSP2. ' +
'Please, use the Referrer-Policy header instead.', finding_1.Severity.INFO, csp_1.Directive.REFERRER));
}
if (csp_1.Directive.DISOWN_OPENER in parsedCsp.directives) {
violations.push(new finding_1.Finding(finding_1.Type.DEPRECATED_DIRECTIVE, 'disown-opener is deprecated since CSP3. ' +
'Please, use the Cross Origin Opener Policy header instead.', finding_1.Severity.INFO, csp_1.Directive.DISOWN_OPENER));
}
return violations;
}
exports.checkDeprecatedDirective = checkDeprecatedDirective;
function checkNonceLength(parsedCsp) {
const noncePattern = new RegExp('^\'nonce-(.+)\'$');
const violations = [];
utils.applyCheckFunktionToDirectives(parsedCsp, (directive, directiveValues) => {
for (const value of directiveValues) {
const match = value.match(noncePattern);
if (!match) {
continue;
}
const nonceValue = match[1];
if (nonceValue.length < 8) {
violations.push(new finding_1.Finding(finding_1.Type.NONCE_LENGTH, 'Nonces should be at least 8 characters long.', finding_1.Severity.MEDIUM, directive, value));
}
if (!csp.isNonce(value, true)) {
violations.push(new finding_1.Finding(finding_1.Type.NONCE_CHARSET, 'Nonces should only use the base64 charset.', finding_1.Severity.INFO, directive, value));
}
}
});
return violations;
}
exports.checkNonceLength = checkNonceLength;
function checkSrcHttp(parsedCsp) {
const violations = [];
utils.applyCheckFunktionToDirectives(parsedCsp, (directive, directiveValues) => {
for (const value of directiveValues) {
const description = directive === csp_1.Directive.REPORT_URI ?
'Use HTTPS to send violation reports securely.' :
'Allow only resources downloaded over HTTPS.';
if (value.startsWith('http://')) {
violations.push(new finding_1.Finding(finding_1.Type.SRC_HTTP, description, finding_1.Severity.MEDIUM, directive, value));
}
}
});
return violations;
}
exports.checkSrcHttp = checkSrcHttp;
function checkHasConfiguredReporting(parsedCsp) {
const reportUriValues = parsedCsp.directives[csp_1.Directive.REPORT_URI] || [];
if (reportUriValues.length > 0) {
return [];
}
const reportToValues = parsedCsp.directives[csp_1.Directive.REPORT_TO] || [];
if (reportToValues.length > 0) {
return [new finding_1.Finding(finding_1.Type.REPORT_TO_ONLY, `This CSP policy only provides a reporting destination via the 'report-to' directive. This directive is only supported in Chromium-based browsers so it is recommended to also use a 'report-uri' directive.`, finding_1.Severity.INFO, csp_1.Directive.REPORT_TO)];
}
return [new finding_1.Finding(finding_1.Type.REPORTING_DESTINATION_MISSING, 'This CSP policy does not configure a reporting destination. This makes it difficult to maintain the CSP policy over time and monitor for any breakages.', finding_1.Severity.INFO, csp_1.Directive.REPORT_URI)];
}
exports.checkHasConfiguredReporting = checkHasConfiguredReporting;
//# sourceMappingURL=security_checks.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=security_checks_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"security_checks_test.d.ts","sourceRoot":"","sources":["../../checks/security_checks_test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,329 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const csp_1 = require("../csp");
const finding_1 = require("../finding");
const parser_1 = require("../parser");
const securityChecks = __importStar(require("./security_checks"));
function checkCsp(test, checkFunction) {
const parsedCsp = (new parser_1.CspParser(test)).csp;
return checkFunction(parsedCsp);
}
describe('Test security checks', () => {
it('CheckScriptUnsafeInlineInScriptSrc', () => {
const test = 'default-src https:; script-src \'unsafe-inline\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckScriptUnsafeInlineInDefaultSrc', () => {
const test = 'default-src \'unsafe-inline\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(1);
});
it('CheckScriptUnsafeInlineInDefaultSrcAndNotInScriptSrc', () => {
const test = 'default-src \'unsafe-inline\'; script-src https:';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(0);
});
it('CheckScriptUnsafeInlineWithNonce', () => {
const test = 'script-src \'unsafe-inline\' \'nonce-foobar\'';
const parsedCsp = (new parser_1.CspParser(test)).csp;
let effectiveCsp = parsedCsp.getEffectiveCsp(csp_1.Version.CSP1);
let violations = securityChecks.checkScriptUnsafeInline(effectiveCsp);
expect(violations.length).toBe(1);
effectiveCsp = parsedCsp.getEffectiveCsp(csp_1.Version.CSP3);
violations = securityChecks.checkScriptUnsafeInline(effectiveCsp);
expect(violations.length).toBe(0);
});
it('CheckScriptUnsafeEvalInScriptSrc', () => {
const test = 'default-src https:; script-src \'unsafe-eval\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeEval);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
});
it('CheckScriptUnsafeEvalInDefaultSrc', () => {
const test = 'default-src \'unsafe-eval\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeEval);
expect(violations.length).toBe(1);
});
it('CheckPlainUrlSchemesInScriptSrc', () => {
const test = 'script-src data: http: https: sthInvalid:';
const violations = checkCsp(test, securityChecks.checkPlainUrlSchemes);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckPlainUrlSchemesInObjectSrc', () => {
const test = 'object-src data: http: https: sthInvalid:';
const violations = checkCsp(test, securityChecks.checkPlainUrlSchemes);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckPlainUrlSchemesInBaseUri', () => {
const test = 'base-uri data: http: https: sthInvalid:';
const violations = checkCsp(test, securityChecks.checkPlainUrlSchemes);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckPlainUrlSchemesMixed', () => {
const test = 'default-src https:; object-src data: sthInvalid:';
const violations = checkCsp(test, securityChecks.checkPlainUrlSchemes);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
expect(violations[0].directive).toBe(csp_1.Directive.DEFAULT_SRC);
expect(violations[1].directive).toBe(csp_1.Directive.OBJECT_SRC);
});
it('CheckPlainUrlSchemesDangerousDirectivesOK', () => {
const test = 'default-src https:; object-src \'none\'; script-src \'none\'; ' +
'base-uri \'none\'';
const violations = checkCsp(test, securityChecks.checkPlainUrlSchemes);
expect(violations.length).toBe(0);
});
it('CheckWildcardsInScriptSrc', () => {
const test = 'script-src * http://* //*';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckWildcardsInObjectSrc', () => {
const test = 'object-src * http://* //*';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckWildcardsInBaseUri', () => {
const test = 'base-uri * http://* //*';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
});
it('CheckWildcardsSchemesMixed', () => {
const test = 'default-src *; object-src * ignore.me.com';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === finding_1.Severity.HIGH)).toBeTrue();
expect(violations[0].directive).toBe(csp_1.Directive.DEFAULT_SRC);
expect(violations[1].directive).toBe(csp_1.Directive.OBJECT_SRC);
});
it('CheckWildcardsDangerousDirectivesOK', () => {
const test = 'default-src *; object-src *.foo.bar; script-src \'none\'; ' +
'base-uri \'none\'';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(0);
});
it('CheckMissingDirectivesMissingObjectSrc', () => {
const test = 'script-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckMissingDirectivesMissingScriptSrc', () => {
const test = 'object-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckMissingDirectivesObjectSrcSelf', () => {
const test = 'object-src \'self\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckMissingDirectivesMissingBaseUriInNonceCsp', () => {
const test = 'script-src \'nonce-123\'; object-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckMissingDirectivesMissingBaseUriInHashWStrictDynamicCsp', () => {
const test = 'script-src \'sha256-123456\' \'strict-dynamic\'; object-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('CheckMissingDirectivesMissingBaseUriInHashCsp', () => {
const test = 'script-src \'sha256-123456\'; object-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(0);
});
it('CheckMissingDirectivesScriptAndObjectSrcSet', () => {
const test = 'script-src \'none\'; object-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(0);
});
it('CheckMissingDirectivesDefaultSrcSet', () => {
const test = 'default-src https:;';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(0);
});
it('CheckMissingDirectivesDefaultSrcSetToNone', () => {
const test = 'default-src \'none\';';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(0);
});
it('checkScriptAllowlistBypassJSONPBypass', () => {
const test = 'script-src *.google.com';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].description.includes('www.google.com is known to host JSONP endpoints which'))
.toBeTrue();
});
it('checkScriptAllowlistBypassWithNoneAndJSONPBypass', () => {
const test = 'script-src *.google.com \'none\'';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(0);
});
it('checkScriptAllowlistBypassJSONPBypassEvalRequired', () => {
const test = 'script-src https://googletagmanager.com \'unsafe-eval\'';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('checkScriptAllowlistBypassJSONPBypassEvalRequiredNotPresent', () => {
const test = 'script-src https://googletagmanager.com';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
});
it('checkScriptAllowlistBypassAngularBypass', () => {
const test = 'script-src gstatic.com';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].description.includes('gstatic.com is known to host Angular libraries which'))
.toBeTrue();
});
it('checkScriptAllowlistBypassNoBypassWarningOnly', () => {
const test = 'script-src foo.bar';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
});
it('checkScriptAllowlistBypassNoBypassSelfWarningOnly', () => {
const test = 'script-src \'self\'';
const violations = checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
});
it('checkFlashObjectAllowlistBypassFlashBypass', () => {
const test = 'object-src https://*.googleapis.com';
const violations = checkCsp(test, securityChecks.checkFlashObjectAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
});
it('checkFlashObjectAllowlistBypassNoFlashBypass', () => {
const test = 'object-src https://foo.bar';
const violations = checkCsp(test, securityChecks.checkFlashObjectAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
});
it('checkFlashObjectAllowlistBypassSelfAllowed', () => {
const test = 'object-src \'self\'';
const violations = checkCsp(test, securityChecks.checkFlashObjectAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM_MAYBE);
expect(violations[0].description)
.toBe('Can you restrict object-src to \'none\' only?');
});
it('CheckIpSource', () => {
const test = 'script-src 8.8.8.8; font-src //127.0.0.1 https://[::1] not.an.ip';
const violations = checkCsp(test, securityChecks.checkIpSource);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === finding_1.Severity.INFO)).toBeTrue();
});
it('LooksLikeIpAddressIPv4', () => {
expect(securityChecks.looksLikeIpAddress('8.8.8.8')).toBeTrue();
});
it('LooksLikeIpAddressIPv6', () => {
expect(securityChecks.looksLikeIpAddress('[::1]')).toBeTrue();
});
it('CheckDeprecatedDirectiveReportUriWithReportTo', () => {
const test = 'report-uri foo.bar/csp;report-to abc';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(0);
});
it('CheckDeprecatedDirectiveWithoutReportUriButWithReportTo', () => {
const test = 'report-to abc';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(0);
});
it('CheckDeprecatedDirectiveReflectedXss', () => {
const test = 'reflected-xss block';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
});
it('CheckDeprecatedDirectiveReferrer', () => {
const test = 'referrer origin';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
});
it('CheckNonceLengthWithLongNonce', () => {
const test = 'script-src \'nonce-veryLongRandomNonce\'';
const violations = checkCsp(test, securityChecks.checkNonceLength);
expect(violations.length).toBe(0);
});
it('CheckNonceLengthWithShortNonce', () => {
const test = 'script-src \'nonce-short\'';
const violations = checkCsp(test, securityChecks.checkNonceLength);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.MEDIUM);
});
it('CheckNonceLengthInvalidCharset', () => {
const test = 'script-src \'nonce-***notBase64***\'';
const violations = checkCsp(test, securityChecks.checkNonceLength);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
});
it('CheckSrcHttp', () => {
const test = 'script-src http://foo.bar https://test.com; report-uri http://test.com';
const violations = checkCsp(test, securityChecks.checkSrcHttp);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === finding_1.Severity.MEDIUM)).toBeTrue();
});
it('CheckHasConfiguredReporting_whenNoReporting', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'';
const violations = checkCsp(test, securityChecks.checkHasConfiguredReporting);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
expect(violations[0].directive).toBe('report-uri');
});
it('CheckHasConfiguredReporting_whenOnlyReportTo', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; report-to name';
const violations = checkCsp(test, securityChecks.checkHasConfiguredReporting);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
expect(violations[0].directive).toBe('report-to');
});
it('CheckHasConfiguredReporting_whenOnlyReportUri', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; report-uri url';
const violations = checkCsp(test, securityChecks.checkHasConfiguredReporting);
expect(violations.length).toBe(0);
});
it('CheckHasConfiguredReporting_whenReportUriAndReportTo', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; report-uri url; report-to name';
const violations = checkCsp(test, securityChecks.checkHasConfiguredReporting);
expect(violations.length).toBe(0);
});
});
//# sourceMappingURL=security_checks_test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import { Csp } from '../csp';
import { Finding } from '../finding';
export declare function checkStrictDynamic(parsedCsp: Csp): Finding[];
export declare function checkStrictDynamicNotStandalone(parsedCsp: Csp): Finding[];
export declare function checkUnsafeInlineFallback(parsedCsp: Csp): Finding[];
export declare function checkAllowlistFallback(parsedCsp: Csp): Finding[];
export declare function checkRequiresTrustedTypesForScripts(parsedCsp: Csp): Finding[];
//# sourceMappingURL=strictcsp_checks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"strictcsp_checks.d.ts","sourceRoot":"","sources":["../../checks/strictcsp_checks.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAC,GAAG,EAAU,MAAM,QAAQ,CAAC;AAEpC,OAAO,EAAC,OAAO,EAAiB,MAAM,YAAY,CAAC;AAWnD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAiB5D;AAWD,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAezE;AAaD,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAmBnE;AAcD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAqBhE;AAWD,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,EAAE,CAe7E"}

View File

@@ -0,0 +1,87 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkRequiresTrustedTypesForScripts = exports.checkAllowlistFallback = exports.checkUnsafeInlineFallback = exports.checkStrictDynamicNotStandalone = exports.checkStrictDynamic = void 0;
const csp = __importStar(require("../csp"));
const csp_1 = require("../csp");
const finding_1 = require("../finding");
function checkStrictDynamic(parsedCsp) {
const directiveName = parsedCsp.getEffectiveDirective(csp.Directive.SCRIPT_SRC);
const values = parsedCsp.directives[directiveName] || [];
const schemeOrHostPresent = values.some((v) => !v.startsWith('\''));
if (schemeOrHostPresent && !values.includes(csp_1.Keyword.STRICT_DYNAMIC)) {
return [new finding_1.Finding(finding_1.Type.STRICT_DYNAMIC, 'Host allowlists can frequently be bypassed. Consider using ' +
'\'strict-dynamic\' in combination with CSP nonces or hashes.', finding_1.Severity.STRICT_CSP, directiveName)];
}
return [];
}
exports.checkStrictDynamic = checkStrictDynamic;
function checkStrictDynamicNotStandalone(parsedCsp) {
const directiveName = parsedCsp.getEffectiveDirective(csp.Directive.SCRIPT_SRC);
const values = parsedCsp.directives[directiveName] || [];
if (values.includes(csp_1.Keyword.STRICT_DYNAMIC) &&
(!parsedCsp.policyHasScriptNonces() &&
!parsedCsp.policyHasScriptHashes())) {
return [new finding_1.Finding(finding_1.Type.STRICT_DYNAMIC_NOT_STANDALONE, '\'strict-dynamic\' without a CSP nonce/hash will block all scripts.', finding_1.Severity.INFO, directiveName)];
}
return [];
}
exports.checkStrictDynamicNotStandalone = checkStrictDynamicNotStandalone;
function checkUnsafeInlineFallback(parsedCsp) {
if (!parsedCsp.policyHasScriptNonces() &&
!parsedCsp.policyHasScriptHashes()) {
return [];
}
const directiveName = parsedCsp.getEffectiveDirective(csp.Directive.SCRIPT_SRC);
const values = parsedCsp.directives[directiveName] || [];
if (!values.includes(csp_1.Keyword.UNSAFE_INLINE)) {
return [new finding_1.Finding(finding_1.Type.UNSAFE_INLINE_FALLBACK, 'Consider adding \'unsafe-inline\' (ignored by browsers supporting ' +
'nonces/hashes) to be backward compatible with older browsers.', finding_1.Severity.STRICT_CSP, directiveName)];
}
return [];
}
exports.checkUnsafeInlineFallback = checkUnsafeInlineFallback;
function checkAllowlistFallback(parsedCsp) {
const directiveName = parsedCsp.getEffectiveDirective(csp.Directive.SCRIPT_SRC);
const values = parsedCsp.directives[directiveName] || [];
if (!values.includes(csp_1.Keyword.STRICT_DYNAMIC)) {
return [];
}
if (!values.some((v) => ['http:', 'https:', '*'].includes(v) || v.includes('.'))) {
return [new finding_1.Finding(finding_1.Type.ALLOWLIST_FALLBACK, 'Consider adding https: and http: url schemes (ignored by browsers ' +
'supporting \'strict-dynamic\') to be backward compatible with older ' +
'browsers.', finding_1.Severity.STRICT_CSP, directiveName)];
}
return [];
}
exports.checkAllowlistFallback = checkAllowlistFallback;
function checkRequiresTrustedTypesForScripts(parsedCsp) {
const directiveName = parsedCsp.getEffectiveDirective(csp.Directive.REQUIRE_TRUSTED_TYPES_FOR);
const values = parsedCsp.directives[directiveName] || [];
if (!values.includes(csp.TrustedTypesSink.SCRIPT)) {
return [new finding_1.Finding(finding_1.Type.REQUIRE_TRUSTED_TYPES_FOR_SCRIPTS, 'Consider requiring Trusted Types for scripts to lock down DOM XSS ' +
'injection sinks. You can do this by adding ' +
'"require-trusted-types-for \'script\'" to your policy.', finding_1.Severity.INFO, csp.Directive.REQUIRE_TRUSTED_TYPES_FOR)];
}
return [];
}
exports.checkRequiresTrustedTypesForScripts = checkRequiresTrustedTypesForScripts;
//# sourceMappingURL=strictcsp_checks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"strictcsp_checks.js","sourceRoot":"","sources":["../../checks/strictcsp_checks.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=strictcsp_checks_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"strictcsp_checks_test.d.ts","sourceRoot":"","sources":["../../checks/strictcsp_checks_test.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,79 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const finding_1 = require("../finding");
const parser_1 = require("../parser");
const strictcspChecks = __importStar(require("./strictcsp_checks"));
function checkCsp(test, checkFunction) {
const parsedCsp = (new parser_1.CspParser(test)).csp;
return checkFunction(parsedCsp);
}
describe('Test strictcsp checks', () => {
it('CheckStrictDynamic', () => {
const test = 'script-src foo.bar';
const violations = checkCsp(test, strictcspChecks.checkStrictDynamic);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
});
it('CheckStrictDynamicNotStandalone', () => {
const test = 'script-src \'strict-dynamic\'';
const violations = checkCsp(test, strictcspChecks.checkStrictDynamicNotStandalone);
expect(violations[0].severity).toBe(finding_1.Severity.INFO);
});
it('CheckStrictDynamicNotStandaloneDoesntFireIfNoncePresent', () => {
const test = 'script-src \'strict-dynamic\' \'nonce-foobar\'';
const violations = checkCsp(test, strictcspChecks.checkStrictDynamicNotStandalone);
expect(violations.length).toBe(0);
});
it('CheckUnsafeInlineFallback', () => {
const test = 'script-src \'nonce-test\'';
const violations = checkCsp(test, strictcspChecks.checkUnsafeInlineFallback);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
});
it('CheckUnsafeInlineFallbackDoesntFireIfFallbackPresent', () => {
const test = 'script-src \'nonce-test\' \'unsafe-inline\'';
const violations = checkCsp(test, strictcspChecks.checkUnsafeInlineFallback);
expect(violations.length).toBe(0);
});
it('checkAllowlistFallback', () => {
const test = 'script-src \'nonce-test\' \'strict-dynamic\'';
const violations = checkCsp(test, strictcspChecks.checkAllowlistFallback);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
});
it('checkAllowlistFallbackDoesntFireIfSchemeFallbackPresent', () => {
const test = 'script-src \'nonce-test\' \'strict-dynamic\' https:';
const violations = checkCsp(test, strictcspChecks.checkAllowlistFallback);
expect(violations.length).toBe(0);
});
it('checkAllowlistFallbackDoesntFireIfURLFallbackPresent', () => {
const test = 'script-src \'nonce-test\' \'strict-dynamic\' foo.bar';
const violations = checkCsp(test, strictcspChecks.checkAllowlistFallback);
expect(violations.length).toBe(0);
});
it('checkAllowlistFallbackDoesntFireInAbsenceOfStrictDynamic', () => {
const test = 'script-src \'nonce-test\'';
const violations = checkCsp(test, strictcspChecks.checkAllowlistFallback);
expect(violations.length).toBe(0);
});
});
//# sourceMappingURL=strictcsp_checks_test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"strictcsp_checks_test.js","sourceRoot":"","sources":["../../checks/strictcsp_checks_test.ts"],"names":[],"mappings":"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"}

84
node_modules/csp_evaluator/dist/csp.d.ts generated vendored Normal file
View File

@@ -0,0 +1,84 @@
import { Finding } from './finding';
export declare class Csp {
directives: Record<string, string[] | undefined>;
clone(): Csp;
convertToString(): string;
getEffectiveCsp(cspVersion: Version, optFindings?: Finding[]): Csp;
getEffectiveDirective(directive: string): string;
getEffectiveDirectives(directives: string[]): string[];
policyHasScriptNonces(): boolean;
policyHasScriptHashes(): boolean;
policyHasStrictDynamic(): boolean;
}
export declare enum Keyword {
SELF = "'self'",
NONE = "'none'",
UNSAFE_INLINE = "'unsafe-inline'",
UNSAFE_EVAL = "'unsafe-eval'",
WASM_EVAL = "'wasm-eval'",
WASM_UNSAFE_EVAL = "'wasm-unsafe-eval'",
STRICT_DYNAMIC = "'strict-dynamic'",
UNSAFE_HASHED_ATTRIBUTES = "'unsafe-hashed-attributes'",
UNSAFE_HASHES = "'unsafe-hashes'",
REPORT_SAMPLE = "'report-sample'",
BLOCK = "'block'",
ALLOW = "'allow'"
}
export declare enum TrustedTypesSink {
SCRIPT = "'script'"
}
export declare enum Directive {
CHILD_SRC = "child-src",
CONNECT_SRC = "connect-src",
DEFAULT_SRC = "default-src",
FONT_SRC = "font-src",
FRAME_SRC = "frame-src",
IMG_SRC = "img-src",
MEDIA_SRC = "media-src",
OBJECT_SRC = "object-src",
SCRIPT_SRC = "script-src",
SCRIPT_SRC_ATTR = "script-src-attr",
SCRIPT_SRC_ELEM = "script-src-elem",
STYLE_SRC = "style-src",
STYLE_SRC_ATTR = "style-src-attr",
STYLE_SRC_ELEM = "style-src-elem",
PREFETCH_SRC = "prefetch-src",
MANIFEST_SRC = "manifest-src",
WORKER_SRC = "worker-src",
BASE_URI = "base-uri",
PLUGIN_TYPES = "plugin-types",
SANDBOX = "sandbox",
DISOWN_OPENER = "disown-opener",
FORM_ACTION = "form-action",
FRAME_ANCESTORS = "frame-ancestors",
NAVIGATE_TO = "navigate-to",
REPORT_TO = "report-to",
REPORT_URI = "report-uri",
BLOCK_ALL_MIXED_CONTENT = "block-all-mixed-content",
UPGRADE_INSECURE_REQUESTS = "upgrade-insecure-requests",
REFLECTED_XSS = "reflected-xss",
REFERRER = "referrer",
REQUIRE_SRI_FOR = "require-sri-for",
TRUSTED_TYPES = "trusted-types",
REQUIRE_TRUSTED_TYPES_FOR = "require-trusted-types-for",
WEBRTC = "webrtc"
}
export declare const FETCH_DIRECTIVES: Directive[];
export declare enum Version {
CSP1 = 1,
CSP2 = 2,
CSP3 = 3
}
export declare function isDirective(directive: string): boolean;
export declare function isKeyword(keyword: string): boolean;
export declare function isUrlScheme(urlScheme: string): boolean;
export declare const STRICT_NONCE_PATTERN: RegExp;
export declare const NONCE_PATTERN: RegExp;
export declare function isNonce(nonce: string, strictCheck?: boolean): boolean;
export declare const STRICT_HASH_PATTERN: RegExp;
export declare const HASH_PATTERN: RegExp;
export declare function isHash(hash: string, strictCheck?: boolean): boolean;
export declare class CspError extends Error {
constructor(message?: string);
}
//# sourceMappingURL=csp.d.ts.map

1
node_modules/csp_evaluator/dist/csp.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"csp.d.ts","sourceRoot":"","sources":["../csp.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAC,OAAO,EAAiB,MAAM,WAAW,CAAC;AAQlD,qBAAa,GAAG;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,GAAC,SAAS,CAAC,CAAM;IAMpD,KAAK,IAAI,GAAG;IAeZ,eAAe,IAAI,MAAM;IA0BzB,eAAe,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG;IAwElE,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAgBhD,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAUtD,qBAAqB,IAAI,OAAO;IAUhC,qBAAqB,IAAI,OAAO;IAUhC,sBAAsB,IAAI,OAAO;CAKlC;AAMD,oBAAY,OAAO;IACjB,IAAI,WAAa;IACjB,IAAI,WAAa;IACjB,aAAa,oBAAsB;IACnC,WAAW,kBAAoB;IAC/B,SAAS,gBAAkB;IAC3B,gBAAgB,uBAAyB;IACzC,cAAc,qBAAuB;IACrC,wBAAwB,+BAAiC;IACzD,aAAa,oBAAsB;IACnC,aAAa,oBAAsB;IACnC,KAAK,YAAc;IACnB,KAAK,YAAc;CACpB;AAMD,oBAAY,gBAAgB;IAC1B,MAAM,aAAe;CACtB;AAUD,oBAAY,SAAS;IAEnB,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,WAAW,gBAAgB;IAC3B,QAAQ,aAAa;IACrB,SAAS,cAAc;IACvB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,UAAU,eAAe;IACzB,UAAU,eAAe;IACzB,eAAe,oBAAoB;IACnC,eAAe,oBAAoB;IACnC,SAAS,cAAc;IACvB,cAAc,mBAAmB;IACjC,cAAc,mBAAmB;IACjC,YAAY,iBAAiB;IAE7B,YAAY,iBAAiB;IAC7B,UAAU,eAAe;IAGzB,QAAQ,aAAa;IACrB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;IACnB,aAAa,kBAAkB;IAG/B,WAAW,gBAAgB;IAC3B,eAAe,oBAAoB;IACnC,WAAW,gBAAgB;IAG3B,SAAS,cAAc;IACvB,UAAU,eAAe;IAGzB,uBAAuB,4BAA4B;IACnD,yBAAyB,8BAA8B;IACvD,aAAa,kBAAkB;IAC/B,QAAQ,aAAa;IACrB,eAAe,oBAAoB;IACnC,aAAa,kBAAkB;IAE/B,yBAAyB,8BAA8B;IACvD,MAAM,WAAW;CAClB;AAQD,eAAO,MAAM,gBAAgB,EAAE,SAAS,EAOvC,CAAC;AAKF,oBAAY,OAAO;IACjB,IAAI,IAAI;IACR,IAAI,IAAA;IACJ,IAAI,IAAA;CACL;AAQD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEtD;AAQD,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAElD;AAUD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGtD;AAMD,eAAO,MAAM,oBAAoB,QACqB,CAAC;AAIvD,eAAO,MAAM,aAAa,QAAiC,CAAC;AAU5D,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAGrE;AAMD,eAAO,MAAM,mBAAmB,QACqC,CAAC;AAItE,eAAO,MAAM,YAAY,QAAkD,CAAC;AAU5E,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,OAAO,CAGnE;AAMD,qBAAa,QAAS,SAAQ,KAAK;gBAIrB,OAAO,CAAC,EAAE,MAAM;CAG7B"}

216
node_modules/csp_evaluator/dist/csp.js generated vendored Normal file
View File

@@ -0,0 +1,216 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CspError = exports.isHash = exports.HASH_PATTERN = exports.STRICT_HASH_PATTERN = exports.isNonce = exports.NONCE_PATTERN = exports.STRICT_NONCE_PATTERN = exports.isUrlScheme = exports.isKeyword = exports.isDirective = exports.Version = exports.FETCH_DIRECTIVES = exports.Directive = exports.TrustedTypesSink = exports.Keyword = exports.Csp = void 0;
const finding_1 = require("./finding");
class Csp {
constructor() {
this.directives = {};
}
clone() {
const clone = new Csp();
for (const [directive, directiveValues] of Object.entries(this.directives)) {
if (directiveValues) {
clone.directives[directive] = [...directiveValues];
}
}
return clone;
}
convertToString() {
let cspString = '';
for (const [directive, directiveValues] of Object.entries(this.directives)) {
cspString += directive;
if (directiveValues !== undefined) {
for (let value, i = 0; (value = directiveValues[i]); i++) {
cspString += ' ';
cspString += value;
}
}
cspString += '; ';
}
return cspString;
}
getEffectiveCsp(cspVersion, optFindings) {
const findings = optFindings || [];
const effectiveCsp = this.clone();
const directive = effectiveCsp.getEffectiveDirective(Directive.SCRIPT_SRC);
const values = this.directives[directive] || [];
const effectiveCspValues = effectiveCsp.directives[directive];
if (effectiveCspValues &&
(effectiveCsp.policyHasScriptNonces() ||
effectiveCsp.policyHasScriptHashes())) {
if (cspVersion >= Version.CSP2) {
if (values.includes(Keyword.UNSAFE_INLINE)) {
arrayRemove(effectiveCspValues, Keyword.UNSAFE_INLINE);
findings.push(new finding_1.Finding(finding_1.Type.IGNORED, 'unsafe-inline is ignored if a nonce or a hash is present. ' +
'(CSP2 and above)', finding_1.Severity.NONE, directive, Keyword.UNSAFE_INLINE));
}
}
else {
for (const value of values) {
if (value.startsWith('\'nonce-') || value.startsWith('\'sha')) {
arrayRemove(effectiveCspValues, value);
}
}
}
}
if (effectiveCspValues && this.policyHasStrictDynamic()) {
if (cspVersion >= Version.CSP3) {
for (const value of values) {
if (!value.startsWith('\'') || value === Keyword.SELF ||
value === Keyword.UNSAFE_INLINE) {
arrayRemove(effectiveCspValues, value);
findings.push(new finding_1.Finding(finding_1.Type.IGNORED, 'Because of strict-dynamic this entry is ignored in CSP3 and above', finding_1.Severity.NONE, directive, value));
}
}
}
else {
arrayRemove(effectiveCspValues, Keyword.STRICT_DYNAMIC);
}
}
if (cspVersion < Version.CSP3) {
delete effectiveCsp.directives[Directive.REPORT_TO];
delete effectiveCsp.directives[Directive.WORKER_SRC];
delete effectiveCsp.directives[Directive.MANIFEST_SRC];
delete effectiveCsp.directives[Directive.TRUSTED_TYPES];
delete effectiveCsp.directives[Directive.REQUIRE_TRUSTED_TYPES_FOR];
}
return effectiveCsp;
}
getEffectiveDirective(directive) {
if (!(directive in this.directives) &&
exports.FETCH_DIRECTIVES.includes(directive)) {
return Directive.DEFAULT_SRC;
}
return directive;
}
getEffectiveDirectives(directives) {
const effectiveDirectives = new Set(directives.map((val) => this.getEffectiveDirective(val)));
return [...effectiveDirectives];
}
policyHasScriptNonces() {
const directiveName = this.getEffectiveDirective(Directive.SCRIPT_SRC);
const values = this.directives[directiveName] || [];
return values.some((val) => isNonce(val));
}
policyHasScriptHashes() {
const directiveName = this.getEffectiveDirective(Directive.SCRIPT_SRC);
const values = this.directives[directiveName] || [];
return values.some((val) => isHash(val));
}
policyHasStrictDynamic() {
const directiveName = this.getEffectiveDirective(Directive.SCRIPT_SRC);
const values = this.directives[directiveName] || [];
return values.includes(Keyword.STRICT_DYNAMIC);
}
}
exports.Csp = Csp;
var Keyword;
(function (Keyword) {
Keyword["SELF"] = "'self'";
Keyword["NONE"] = "'none'";
Keyword["UNSAFE_INLINE"] = "'unsafe-inline'";
Keyword["UNSAFE_EVAL"] = "'unsafe-eval'";
Keyword["WASM_EVAL"] = "'wasm-eval'";
Keyword["WASM_UNSAFE_EVAL"] = "'wasm-unsafe-eval'";
Keyword["STRICT_DYNAMIC"] = "'strict-dynamic'";
Keyword["UNSAFE_HASHED_ATTRIBUTES"] = "'unsafe-hashed-attributes'";
Keyword["UNSAFE_HASHES"] = "'unsafe-hashes'";
Keyword["REPORT_SAMPLE"] = "'report-sample'";
Keyword["BLOCK"] = "'block'";
Keyword["ALLOW"] = "'allow'";
})(Keyword = exports.Keyword || (exports.Keyword = {}));
var TrustedTypesSink;
(function (TrustedTypesSink) {
TrustedTypesSink["SCRIPT"] = "'script'";
})(TrustedTypesSink = exports.TrustedTypesSink || (exports.TrustedTypesSink = {}));
var Directive;
(function (Directive) {
Directive["CHILD_SRC"] = "child-src";
Directive["CONNECT_SRC"] = "connect-src";
Directive["DEFAULT_SRC"] = "default-src";
Directive["FONT_SRC"] = "font-src";
Directive["FRAME_SRC"] = "frame-src";
Directive["IMG_SRC"] = "img-src";
Directive["MEDIA_SRC"] = "media-src";
Directive["OBJECT_SRC"] = "object-src";
Directive["SCRIPT_SRC"] = "script-src";
Directive["SCRIPT_SRC_ATTR"] = "script-src-attr";
Directive["SCRIPT_SRC_ELEM"] = "script-src-elem";
Directive["STYLE_SRC"] = "style-src";
Directive["STYLE_SRC_ATTR"] = "style-src-attr";
Directive["STYLE_SRC_ELEM"] = "style-src-elem";
Directive["PREFETCH_SRC"] = "prefetch-src";
Directive["MANIFEST_SRC"] = "manifest-src";
Directive["WORKER_SRC"] = "worker-src";
Directive["BASE_URI"] = "base-uri";
Directive["PLUGIN_TYPES"] = "plugin-types";
Directive["SANDBOX"] = "sandbox";
Directive["DISOWN_OPENER"] = "disown-opener";
Directive["FORM_ACTION"] = "form-action";
Directive["FRAME_ANCESTORS"] = "frame-ancestors";
Directive["NAVIGATE_TO"] = "navigate-to";
Directive["REPORT_TO"] = "report-to";
Directive["REPORT_URI"] = "report-uri";
Directive["BLOCK_ALL_MIXED_CONTENT"] = "block-all-mixed-content";
Directive["UPGRADE_INSECURE_REQUESTS"] = "upgrade-insecure-requests";
Directive["REFLECTED_XSS"] = "reflected-xss";
Directive["REFERRER"] = "referrer";
Directive["REQUIRE_SRI_FOR"] = "require-sri-for";
Directive["TRUSTED_TYPES"] = "trusted-types";
Directive["REQUIRE_TRUSTED_TYPES_FOR"] = "require-trusted-types-for";
Directive["WEBRTC"] = "webrtc";
})(Directive = exports.Directive || (exports.Directive = {}));
exports.FETCH_DIRECTIVES = [
Directive.CHILD_SRC, Directive.CONNECT_SRC, Directive.DEFAULT_SRC,
Directive.FONT_SRC, Directive.FRAME_SRC, Directive.IMG_SRC,
Directive.MANIFEST_SRC, Directive.MEDIA_SRC, Directive.OBJECT_SRC,
Directive.SCRIPT_SRC, Directive.SCRIPT_SRC_ATTR, Directive.SCRIPT_SRC_ELEM,
Directive.STYLE_SRC, Directive.STYLE_SRC_ATTR, Directive.STYLE_SRC_ELEM,
Directive.WORKER_SRC
];
var Version;
(function (Version) {
Version[Version["CSP1"] = 1] = "CSP1";
Version[Version["CSP2"] = 2] = "CSP2";
Version[Version["CSP3"] = 3] = "CSP3";
})(Version = exports.Version || (exports.Version = {}));
function isDirective(directive) {
return Object.values(Directive).includes(directive);
}
exports.isDirective = isDirective;
function isKeyword(keyword) {
return Object.values(Keyword).includes(keyword);
}
exports.isKeyword = isKeyword;
function isUrlScheme(urlScheme) {
const pattern = new RegExp('^[a-zA-Z][+a-zA-Z0-9.-]*:$');
return pattern.test(urlScheme);
}
exports.isUrlScheme = isUrlScheme;
exports.STRICT_NONCE_PATTERN = new RegExp('^\'nonce-[a-zA-Z0-9+/_-]+[=]{0,2}\'$');
exports.NONCE_PATTERN = new RegExp('^\'nonce-(.+)\'$');
function isNonce(nonce, strictCheck) {
const pattern = strictCheck ? exports.STRICT_NONCE_PATTERN : exports.NONCE_PATTERN;
return pattern.test(nonce);
}
exports.isNonce = isNonce;
exports.STRICT_HASH_PATTERN = new RegExp('^\'(sha256|sha384|sha512)-[a-zA-Z0-9+/]+[=]{0,2}\'$');
exports.HASH_PATTERN = new RegExp('^\'(sha256|sha384|sha512)-(.+)\'$');
function isHash(hash, strictCheck) {
const pattern = strictCheck ? exports.STRICT_HASH_PATTERN : exports.HASH_PATTERN;
return pattern.test(hash);
}
exports.isHash = isHash;
class CspError extends Error {
constructor(message) {
super(message);
}
}
exports.CspError = CspError;
function arrayRemove(arr, item) {
if (arr.includes(item)) {
const idx = arr.findIndex(elem => item === elem);
arr.splice(idx, 1);
}
}
//# sourceMappingURL=csp.js.map

1
node_modules/csp_evaluator/dist/csp.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

2
node_modules/csp_evaluator/dist/csp_test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=csp_test.d.ts.map

1
node_modules/csp_evaluator/dist/csp_test.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"csp_test.d.ts","sourceRoot":"","sources":["../csp_test.ts"],"names":[],"mappings":"AAmBA,OAAO,SAAS,CAAC"}

149
node_modules/csp_evaluator/dist/csp_test.js generated vendored Normal file
View File

@@ -0,0 +1,149 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const csp_1 = require("./csp");
const parser_1 = require("./parser");
describe('Test Csp', () => {
it('ConvertToString', () => {
const testCsp = 'default-src \'none\'; ' +
'script-src \'nonce-unsafefoobar\' \'unsafe-eval\' \'unsafe-inline\' ' +
'https://example.com/foo.js foo.bar; ' +
'img-src \'self\' https: data: blob:; ';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.convertToString()).toBe(testCsp);
});
it('GetEffectiveCspVersion1', () => {
const testCsp = 'default-src \'unsafe-inline\' \'strict-dynamic\' \'nonce-123\' ' +
'\'sha256-foobar\' \'self\'; report-to foo.bar; worker-src *; manifest-src *';
const parsed = (new parser_1.CspParser(testCsp)).csp;
const effectiveCsp = parsed.getEffectiveCsp(csp_1.Version.CSP1);
expect(effectiveCsp.directives[csp_1.Directive.DEFAULT_SRC]).toEqual([
'\'unsafe-inline\'', '\'self\''
]);
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.REPORT_TO)).toBeFalse();
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.WORKER_SRC)).toBeFalse();
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.MANIFEST_SRC)).toBeFalse();
});
it('GetEffectiveCspVersion2', () => {
const testCsp = 'default-src \'unsafe-inline\' \'strict-dynamic\' \'nonce-123\' ' +
'\'sha256-foobar\' \'self\'; report-to foo.bar; worker-src *; manifest-src *';
const parsed = (new parser_1.CspParser(testCsp)).csp;
const effectiveCsp = parsed.getEffectiveCsp(csp_1.Version.CSP2);
expect(effectiveCsp.directives[csp_1.Directive.DEFAULT_SRC]).toEqual([
'\'nonce-123\'', '\'sha256-foobar\'', '\'self\''
]);
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.REPORT_TO)).toBeFalse();
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.WORKER_SRC)).toBeFalse();
expect(effectiveCsp.hasOwnProperty(csp_1.Directive.MANIFEST_SRC)).toBeFalse();
});
it('GetEffectiveCspVersion3', () => {
const testCsp = 'default-src \'unsafe-inline\' \'strict-dynamic\' \'nonce-123\' ' +
'\'sha256-foobar\' \'self\'; report-to foo.bar; worker-src *; manifest-src *';
const parsed = (new parser_1.CspParser(testCsp)).csp;
const effectiveCsp = parsed.getEffectiveCsp(csp_1.Version.CSP3);
expect(effectiveCsp.directives[csp_1.Directive.DEFAULT_SRC]).toEqual([
'\'strict-dynamic\'', '\'nonce-123\'', '\'sha256-foobar\''
]);
expect(effectiveCsp.directives[csp_1.Directive.REPORT_TO]).toEqual(['foo.bar']);
expect(effectiveCsp.directives[csp_1.Directive.WORKER_SRC]).toEqual(['*']);
expect(effectiveCsp.directives[csp_1.Directive.MANIFEST_SRC]).toEqual(['*']);
});
it('GetEffectiveDirective', () => {
const testCsp = 'default-src https:; script-src foo.bar';
const parsed = (new parser_1.CspParser(testCsp)).csp;
const script = parsed.getEffectiveDirective(csp_1.Directive.SCRIPT_SRC);
expect(script).toBe(csp_1.Directive.SCRIPT_SRC);
const style = parsed.getEffectiveDirective(csp_1.Directive.STYLE_SRC);
expect(style).toBe(csp_1.Directive.DEFAULT_SRC);
});
it('GetEffectiveDirectives', () => {
const testCsp = 'default-src https:; script-src foo.bar';
const parsed = (new parser_1.CspParser(testCsp)).csp;
const directives = parsed.getEffectiveDirectives([csp_1.Directive.SCRIPT_SRC, csp_1.Directive.STYLE_SRC]);
expect(directives).toEqual([csp_1.Directive.SCRIPT_SRC, csp_1.Directive.DEFAULT_SRC]);
});
it('PolicyHasScriptNoncesScriptSrcWithNonce', () => {
const testCsp = 'default-src https:; script-src \'nonce-test123\'';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasScriptNonces()).toBeTrue();
});
it('PolicyHasScriptNoncesNoNonce', () => {
const testCsp = 'default-src https: \'nonce-ignored\'; script-src nonce-invalid';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasScriptNonces()).toBeFalse();
});
it('PolicyHasScriptHashesScriptSrcWithHash', () => {
const testCsp = 'default-src https:; script-src \'sha256-asdfASDF\'';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasScriptHashes()).toBeTrue();
});
it('PolicyHasScriptHashesNoHash', () => {
const testCsp = 'default-src https: \'nonce-ignored\'; script-src sha256-invalid';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasScriptHashes()).toBeFalse();
});
it('PolicyHasStrictDynamicScriptSrcWithStrictDynamic', () => {
const testCsp = 'default-src https:; script-src \'strict-dynamic\'';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasStrictDynamic()).toBeTrue();
});
it('PolicyHasStrictDynamicDefaultSrcWithStrictDynamic', () => {
const testCsp = 'default-src https \'strict-dynamic\'';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasStrictDynamic()).toBeTrue();
});
it('PolicyHasStrictDynamicNoStrictDynamic', () => {
const testCsp = 'default-src \'strict-dynamic\'; script-src foo.bar';
const parsed = (new parser_1.CspParser(testCsp)).csp;
expect(parsed.policyHasStrictDynamic()).toBeFalse();
});
it('IsDirective', () => {
const directives = Object.keys(csp_1.Directive).map((name) => csp_1.Directive[name]);
expect(directives.every(csp_1.isDirective)).toBeTrue();
expect(csp_1.isDirective('invalid-src')).toBeFalse();
});
it('IsKeyword', () => {
const keywords = Object.keys(csp_1.Keyword).map((name) => (csp_1.Keyword[name]));
expect(keywords.every(csp_1.isKeyword)).toBeTrue();
expect(csp_1.isKeyword('invalid')).toBeFalse();
});
it('IsUrlScheme', () => {
expect(csp_1.isUrlScheme('http:')).toBeTrue();
expect(csp_1.isUrlScheme('https:')).toBeTrue();
expect(csp_1.isUrlScheme('data:')).toBeTrue();
expect(csp_1.isUrlScheme('blob:')).toBeTrue();
expect(csp_1.isUrlScheme('b+l.o-b:')).toBeTrue();
expect(csp_1.isUrlScheme('filesystem:')).toBeTrue();
expect(csp_1.isUrlScheme('invalid')).toBeFalse();
expect(csp_1.isUrlScheme('ht_tp:')).toBeFalse();
});
it('IsNonce', () => {
expect(csp_1.isNonce('\'nonce-asdfASDF=\'')).toBeTrue();
expect(csp_1.isNonce('\'sha256-asdfASDF=\'')).toBeFalse();
expect(csp_1.isNonce('\'asdfASDF=\'')).toBeFalse();
expect(csp_1.isNonce('example.com')).toBeFalse();
});
it('IsStrictNonce', () => {
expect(csp_1.isNonce('\'nonce-asdfASDF=\'', true)).toBeTrue();
expect(csp_1.isNonce('\'nonce-as+df/A0234SDF==\'', true)).toBeTrue();
expect(csp_1.isNonce('\'nonce-as_dfASDF=\'', true)).toBeTrue();
expect(csp_1.isNonce('\'nonce-asdfASDF===\'', true)).toBeFalse();
expect(csp_1.isNonce('\'sha256-asdfASDF=\'', true)).toBeFalse();
});
it('IsHash', () => {
expect(csp_1.isHash('\'sha256-asdfASDF=\'')).toBeTrue();
expect(csp_1.isHash('\'sha777-asdfASDF=\'')).toBeFalse();
expect(csp_1.isHash('\'asdfASDF=\'')).toBeFalse();
expect(csp_1.isHash('example.com')).toBeFalse();
});
it('IsStrictHash', () => {
expect(csp_1.isHash('\'sha256-asdfASDF=\'', true)).toBeTrue();
expect(csp_1.isHash('\'sha256-as+d/f/ASD0+4F==\'', true)).toBeTrue();
expect(csp_1.isHash('\'sha256-asdfASDF===\'', true)).toBeFalse();
expect(csp_1.isHash('\'sha256-asd_fASDF=\'', true)).toBeFalse();
expect(csp_1.isHash('\'sha777-asdfASDF=\'', true)).toBeFalse();
expect(csp_1.isHash('\'asdfASDF=\'', true)).toBeFalse();
expect(csp_1.isHash('example.com', true)).toBeFalse();
});
});
//# sourceMappingURL=csp_test.js.map

1
node_modules/csp_evaluator/dist/csp_test.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

13
node_modules/csp_evaluator/dist/evaluator.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
import { CheckerFunction } from './checks/checker';
import { Csp, Version } from './csp';
import { Finding } from './finding';
export declare class CspEvaluator {
version: Version;
csp: Csp;
findings: Finding[];
constructor(parsedCsp: Csp, cspVersion?: Version);
evaluate(parsedCspChecks?: CheckerFunction[], effectiveCspChecks?: CheckerFunction[]): Finding[];
}
export declare const DEFAULT_CHECKS: CheckerFunction[];
export declare const STRICTCSP_CHECKS: CheckerFunction[];
//# sourceMappingURL=evaluator.d.ts.map

1
node_modules/csp_evaluator/dist/evaluator.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"evaluator.d.ts","sourceRoot":"","sources":["../evaluator.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAKjD,OAAO,EAAC,GAAG,EAAE,OAAO,EAAC,MAAM,OAAO,CAAC;AACnC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AASlC,qBAAa,YAAY;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;IAMT,QAAQ,EAAE,OAAO,EAAE,CAAM;gBAKb,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,OAAO;IAqBhD,QAAQ,CACJ,eAAe,CAAC,EAAE,eAAe,EAAE,EACnC,kBAAkB,CAAC,EAAE,eAAe,EAAE,GAAG,OAAO,EAAE;CAwBvD;AAMD,eAAO,MAAM,cAAc,EAAE,eAAe,EAS3C,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAM7C,CAAC"}

66
node_modules/csp_evaluator/dist/evaluator.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.STRICTCSP_CHECKS = exports.DEFAULT_CHECKS = exports.CspEvaluator = void 0;
const parserChecks = __importStar(require("./checks/parser_checks"));
const securityChecks = __importStar(require("./checks/security_checks"));
const strictcspChecks = __importStar(require("./checks/strictcsp_checks"));
const csp = __importStar(require("./csp"));
class CspEvaluator {
constructor(parsedCsp, cspVersion) {
this.findings = [];
this.version = cspVersion || csp.Version.CSP3;
this.csp = parsedCsp;
}
evaluate(parsedCspChecks, effectiveCspChecks) {
this.findings = [];
const checks = effectiveCspChecks || exports.DEFAULT_CHECKS;
const effectiveCsp = this.csp.getEffectiveCsp(this.version, this.findings);
if (parsedCspChecks) {
for (const check of parsedCspChecks) {
this.findings = this.findings.concat(check(this.csp));
}
}
for (const check of checks) {
this.findings = this.findings.concat(check(effectiveCsp));
}
return this.findings;
}
}
exports.CspEvaluator = CspEvaluator;
exports.DEFAULT_CHECKS = [
securityChecks.checkScriptUnsafeInline, securityChecks.checkScriptUnsafeEval,
securityChecks.checkPlainUrlSchemes, securityChecks.checkWildcards,
securityChecks.checkMissingDirectives,
securityChecks.checkScriptAllowlistBypass,
securityChecks.checkFlashObjectAllowlistBypass, securityChecks.checkIpSource,
securityChecks.checkNonceLength, securityChecks.checkSrcHttp,
securityChecks.checkDeprecatedDirective, parserChecks.checkUnknownDirective,
parserChecks.checkMissingSemicolon, parserChecks.checkInvalidKeyword
];
exports.STRICTCSP_CHECKS = [
strictcspChecks.checkStrictDynamic,
strictcspChecks.checkStrictDynamicNotStandalone,
strictcspChecks.checkUnsafeInlineFallback,
strictcspChecks.checkAllowlistFallback,
strictcspChecks.checkRequiresTrustedTypesForScripts
];
//# sourceMappingURL=evaluator.js.map

1
node_modules/csp_evaluator/dist/evaluator.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../evaluator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmBA,qEAAuD;AACvD,yEAA2D;AAC3D,2EAA6D;AAC7D,2CAA6B;AAW7B,MAAa,YAAY;IAavB,YAAY,SAAc,EAAE,UAAoB;QALhD,aAAQ,GAAc,EAAE,CAAC;QASvB,IAAI,CAAC,OAAO,GAAG,UAAU,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;QAK9C,IAAI,CAAC,GAAG,GAAG,SAAS,CAAC;IACvB,CAAC;IAWD,QAAQ,CACJ,eAAmC,EACnC,kBAAsC;QACxC,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,kBAAkB,IAAI,sBAAc,CAAC;QAMpD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAG3E,IAAI,eAAe,EAAE;YACnB,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE;gBACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;aACvD;SACF;QAGD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;SAC3D;QAED,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF;AA5DD,oCA4DC;AAMY,QAAA,cAAc,GAAsB;IAC/C,cAAc,CAAC,uBAAuB,EAAE,cAAc,CAAC,qBAAqB;IAC5E,cAAc,CAAC,oBAAoB,EAAE,cAAc,CAAC,cAAc;IAClE,cAAc,CAAC,sBAAsB;IACrC,cAAc,CAAC,0BAA0B;IACzC,cAAc,CAAC,+BAA+B,EAAE,cAAc,CAAC,aAAa;IAC5E,cAAc,CAAC,gBAAgB,EAAE,cAAc,CAAC,YAAY;IAC5D,cAAc,CAAC,wBAAwB,EAAE,YAAY,CAAC,qBAAqB;IAC3E,YAAY,CAAC,qBAAqB,EAAE,YAAY,CAAC,mBAAmB;CACrE,CAAC;AAMW,QAAA,gBAAgB,GAAsB;IACjD,eAAe,CAAC,kBAAkB;IAClC,eAAe,CAAC,+BAA+B;IAC/C,eAAe,CAAC,yBAAyB;IACzC,eAAe,CAAC,sBAAsB;IACtC,eAAe,CAAC,mCAAmC;CACpD,CAAC"}

2
node_modules/csp_evaluator/dist/evaluator_test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=evaluator_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"evaluator_test.d.ts","sourceRoot":"","sources":["../evaluator_test.ts"],"names":[],"mappings":"AAmBA,OAAO,SAAS,CAAC"}

25
node_modules/csp_evaluator/dist/evaluator_test.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const csp_1 = require("./csp");
const evaluator_1 = require("./evaluator");
const finding_1 = require("./finding");
describe('Test evaluator', () => {
it('CspEvaluator', () => {
const fakeCsp = new csp_1.Csp();
const evaluator = new evaluator_1.CspEvaluator(fakeCsp);
expect(evaluator.csp).toBe(fakeCsp);
});
it('Evaluate', () => {
const fakeCsp = new (csp_1.Csp)();
const fakeFinding = new (finding_1.Finding)(finding_1.Type.UNKNOWN_DIRECTIVE, 'Fake description', finding_1.Severity.MEDIUM, 'fake-directive', 'fake-directive-value');
const fakeVerifier = (parsedCsp) => {
return [fakeFinding];
};
const evaluator = new (evaluator_1.CspEvaluator)(fakeCsp);
const findings = evaluator.evaluate([fakeVerifier, fakeVerifier], [fakeVerifier]);
const expectedFindings = [fakeFinding, fakeFinding, fakeFinding];
expect(findings).toEqual(expectedFindings);
});
});
//# sourceMappingURL=evaluator_test.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"evaluator_test.js","sourceRoot":"","sources":["../evaluator_test.ts"],"names":[],"mappings":";;AAmBA,mBAAiB;AAEjB,+BAA0B;AAC1B,2CAAyC;AACzC,uCAAkD;AAElD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;QACtB,MAAM,OAAO,GAAG,IAAI,SAAG,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,IAAI,wBAAY,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAO,CAAC,CAC7B,cAAI,CAAC,iBAAiB,EAAE,kBAAkB,EAAE,kBAAQ,CAAC,MAAM,EAC3D,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,CAAC,SAAc,EAAE,EAAE;YACtC,OAAO,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,wBAAY,CAAC,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,QAAQ,GACV,SAAS,CAAC,QAAQ,CAAC,CAAC,YAAY,EAAE,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;QAErE,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QACjE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

47
node_modules/csp_evaluator/dist/finding.d.ts generated vendored Normal file
View File

@@ -0,0 +1,47 @@
export declare class Finding {
type: Type;
description: string;
severity: Severity;
directive: string;
value?: string | undefined;
constructor(type: Type, description: string, severity: Severity, directive: string, value?: string | undefined);
static getHighestSeverity(findings: Finding[]): Severity;
equals(obj: unknown): boolean;
}
export declare enum Severity {
HIGH = 10,
SYNTAX = 20,
MEDIUM = 30,
HIGH_MAYBE = 40,
STRICT_CSP = 45,
MEDIUM_MAYBE = 50,
INFO = 60,
NONE = 100
}
export declare enum Type {
MISSING_SEMICOLON = 100,
UNKNOWN_DIRECTIVE = 101,
INVALID_KEYWORD = 102,
NONCE_CHARSET = 106,
MISSING_DIRECTIVES = 300,
SCRIPT_UNSAFE_INLINE = 301,
SCRIPT_UNSAFE_EVAL = 302,
PLAIN_URL_SCHEMES = 303,
PLAIN_WILDCARD = 304,
SCRIPT_ALLOWLIST_BYPASS = 305,
OBJECT_ALLOWLIST_BYPASS = 306,
NONCE_LENGTH = 307,
IP_SOURCE = 308,
DEPRECATED_DIRECTIVE = 309,
SRC_HTTP = 310,
STRICT_DYNAMIC = 400,
STRICT_DYNAMIC_NOT_STANDALONE = 401,
NONCE_HASH = 402,
UNSAFE_INLINE_FALLBACK = 403,
ALLOWLIST_FALLBACK = 404,
IGNORED = 405,
REQUIRE_TRUSTED_TYPES_FOR_SCRIPTS = 500,
REPORTING_DESTINATION_MISSING = 600,
REPORT_TO_ONLY = 601
}
//# sourceMappingURL=finding.d.ts.map

1
node_modules/csp_evaluator/dist/finding.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../finding.ts"],"names":[],"mappings":"AAyBA,qBAAa,OAAO;IASP,IAAI,EAAE,IAAI;IAAS,WAAW,EAAE,MAAM;IAAS,QAAQ,EAAE,QAAQ;IACjE,SAAS,EAAE,MAAM;IAAS,KAAK,CAAC;gBADhC,IAAI,EAAE,IAAI,EAAS,WAAW,EAAE,MAAM,EAAS,QAAQ,EAAE,QAAQ,EACjE,SAAS,EAAE,MAAM,EAAS,KAAK,CAAC,oBAAQ;IAOnD,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ;IAUxD,MAAM,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO;CAQ9B;AAMD,oBAAY,QAAQ;IAClB,IAAI,KAAK;IACT,MAAM,KAAK;IACX,MAAM,KAAK;IACX,UAAU,KAAK;IACf,UAAU,KAAK;IACf,YAAY,KAAK;IACjB,IAAI,KAAK;IACT,IAAI,MAAM;CACX;AAMD,oBAAY,IAAI;IAEd,iBAAiB,MAAM;IACvB,iBAAiB,MAAA;IACjB,eAAe,MAAA;IACf,aAAa,MAAM;IAGnB,kBAAkB,MAAM;IACxB,oBAAoB,MAAA;IACpB,kBAAkB,MAAA;IAClB,iBAAiB,MAAA;IACjB,cAAc,MAAA;IACd,uBAAuB,MAAA;IACvB,uBAAuB,MAAA;IACvB,YAAY,MAAA;IACZ,SAAS,MAAA;IACT,oBAAoB,MAAA;IACpB,QAAQ,MAAA;IAGR,cAAc,MAAM;IACpB,6BAA6B,MAAA;IAC7B,UAAU,MAAA;IACV,sBAAsB,MAAA;IACtB,kBAAkB,MAAA;IAClB,OAAO,MAAA;IAGP,iCAAiC,MAAM;IAGvC,6BAA6B,MAAM;IACnC,cAAc,MAAA;CACf"}

68
node_modules/csp_evaluator/dist/finding.js generated vendored Normal file
View File

@@ -0,0 +1,68 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Type = exports.Severity = exports.Finding = void 0;
class Finding {
constructor(type, description, severity, directive, value) {
this.type = type;
this.description = description;
this.severity = severity;
this.directive = directive;
this.value = value;
}
static getHighestSeverity(findings) {
if (findings.length === 0) {
return Severity.NONE;
}
const severities = findings.map((finding) => finding.severity);
const min = (prev, cur) => prev < cur ? prev : cur;
return severities.reduce(min, Severity.NONE);
}
equals(obj) {
if (!(obj instanceof Finding)) {
return false;
}
return obj.type === this.type && obj.description === this.description &&
obj.severity === this.severity && obj.directive === this.directive &&
obj.value === this.value;
}
}
exports.Finding = Finding;
var Severity;
(function (Severity) {
Severity[Severity["HIGH"] = 10] = "HIGH";
Severity[Severity["SYNTAX"] = 20] = "SYNTAX";
Severity[Severity["MEDIUM"] = 30] = "MEDIUM";
Severity[Severity["HIGH_MAYBE"] = 40] = "HIGH_MAYBE";
Severity[Severity["STRICT_CSP"] = 45] = "STRICT_CSP";
Severity[Severity["MEDIUM_MAYBE"] = 50] = "MEDIUM_MAYBE";
Severity[Severity["INFO"] = 60] = "INFO";
Severity[Severity["NONE"] = 100] = "NONE";
})(Severity = exports.Severity || (exports.Severity = {}));
var Type;
(function (Type) {
Type[Type["MISSING_SEMICOLON"] = 100] = "MISSING_SEMICOLON";
Type[Type["UNKNOWN_DIRECTIVE"] = 101] = "UNKNOWN_DIRECTIVE";
Type[Type["INVALID_KEYWORD"] = 102] = "INVALID_KEYWORD";
Type[Type["NONCE_CHARSET"] = 106] = "NONCE_CHARSET";
Type[Type["MISSING_DIRECTIVES"] = 300] = "MISSING_DIRECTIVES";
Type[Type["SCRIPT_UNSAFE_INLINE"] = 301] = "SCRIPT_UNSAFE_INLINE";
Type[Type["SCRIPT_UNSAFE_EVAL"] = 302] = "SCRIPT_UNSAFE_EVAL";
Type[Type["PLAIN_URL_SCHEMES"] = 303] = "PLAIN_URL_SCHEMES";
Type[Type["PLAIN_WILDCARD"] = 304] = "PLAIN_WILDCARD";
Type[Type["SCRIPT_ALLOWLIST_BYPASS"] = 305] = "SCRIPT_ALLOWLIST_BYPASS";
Type[Type["OBJECT_ALLOWLIST_BYPASS"] = 306] = "OBJECT_ALLOWLIST_BYPASS";
Type[Type["NONCE_LENGTH"] = 307] = "NONCE_LENGTH";
Type[Type["IP_SOURCE"] = 308] = "IP_SOURCE";
Type[Type["DEPRECATED_DIRECTIVE"] = 309] = "DEPRECATED_DIRECTIVE";
Type[Type["SRC_HTTP"] = 310] = "SRC_HTTP";
Type[Type["STRICT_DYNAMIC"] = 400] = "STRICT_DYNAMIC";
Type[Type["STRICT_DYNAMIC_NOT_STANDALONE"] = 401] = "STRICT_DYNAMIC_NOT_STANDALONE";
Type[Type["NONCE_HASH"] = 402] = "NONCE_HASH";
Type[Type["UNSAFE_INLINE_FALLBACK"] = 403] = "UNSAFE_INLINE_FALLBACK";
Type[Type["ALLOWLIST_FALLBACK"] = 404] = "ALLOWLIST_FALLBACK";
Type[Type["IGNORED"] = 405] = "IGNORED";
Type[Type["REQUIRE_TRUSTED_TYPES_FOR_SCRIPTS"] = 500] = "REQUIRE_TRUSTED_TYPES_FOR_SCRIPTS";
Type[Type["REPORTING_DESTINATION_MISSING"] = 600] = "REPORTING_DESTINATION_MISSING";
Type[Type["REPORT_TO_ONLY"] = 601] = "REPORT_TO_ONLY";
})(Type = exports.Type || (exports.Type = {}));
//# sourceMappingURL=finding.js.map

1
node_modules/csp_evaluator/dist/finding.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"finding.js","sourceRoot":"","sources":["../finding.ts"],"names":[],"mappings":";;;AAyBA,MAAa,OAAO;IAQlB,YACW,IAAU,EAAS,WAAmB,EAAS,QAAkB,EACjE,SAAiB,EAAS,KAAc;QADxC,SAAI,GAAJ,IAAI,CAAM;QAAS,gBAAW,GAAX,WAAW,CAAQ;QAAS,aAAQ,GAAR,QAAQ,CAAU;QACjE,cAAS,GAAT,SAAS,CAAQ;QAAS,UAAK,GAAL,KAAK,CAAS;IAAG,CAAC;IAOvD,MAAM,CAAC,kBAAkB,CAAC,QAAmB;QAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;YACzB,OAAO,QAAQ,CAAC,IAAI,CAAC;SACtB;QAED,MAAM,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,CAAC,IAAc,EAAE,GAAa,EAAE,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;QACvE,OAAO,UAAU,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,CAAC,GAAY;QACjB,IAAI,CAAC,CAAC,GAAG,YAAY,OAAO,CAAC,EAAE;YAC7B,OAAO,KAAK,CAAC;SACd;QACD,OAAO,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;YACjE,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;YAClE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC;IAC/B,CAAC;CACF;AAnCD,0BAmCC;AAMD,IAAY,QASX;AATD,WAAY,QAAQ;IAClB,wCAAS,CAAA;IACT,4CAAW,CAAA;IACX,4CAAW,CAAA;IACX,oDAAe,CAAA;IACf,oDAAe,CAAA;IACf,wDAAiB,CAAA;IACjB,wCAAS,CAAA;IACT,yCAAU,CAAA;AACZ,CAAC,EATW,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QASnB;AAMD,IAAY,IAkCX;AAlCD,WAAY,IAAI;IAEd,2DAAuB,CAAA;IACvB,2DAAiB,CAAA;IACjB,uDAAe,CAAA;IACf,mDAAmB,CAAA;IAGnB,6DAAwB,CAAA;IACxB,iEAAoB,CAAA;IACpB,6DAAkB,CAAA;IAClB,2DAAiB,CAAA;IACjB,qDAAc,CAAA;IACd,uEAAuB,CAAA;IACvB,uEAAuB,CAAA;IACvB,iDAAY,CAAA;IACZ,2CAAS,CAAA;IACT,iEAAoB,CAAA;IACpB,yCAAQ,CAAA;IAGR,qDAAoB,CAAA;IACpB,mFAA6B,CAAA;IAC7B,6CAAU,CAAA;IACV,qEAAsB,CAAA;IACtB,6DAAkB,CAAA;IAClB,uCAAO,CAAA;IAGP,2FAAuC,CAAA;IAGvC,mFAAmC,CAAA;IACnC,qDAAc,CAAA;AAChB,CAAC,EAlCW,IAAI,GAAJ,YAAI,KAAJ,YAAI,QAkCf"}

2
node_modules/csp_evaluator/dist/finding_test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=finding_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"finding_test.d.ts","sourceRoot":"","sources":["../finding_test.ts"],"names":[],"mappings":"AAmBA,OAAO,SAAS,CAAC"}

36
node_modules/csp_evaluator/dist/finding_test.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const csp_1 = require("./csp");
const finding_1 = require("./finding");
describe('Test finding', () => {
it('Finding', () => {
const type = finding_1.Type.MISSING_SEMICOLON;
const description = 'description';
const severity = finding_1.Severity.HIGH;
const directive = csp_1.Directive.SCRIPT_SRC;
const value = csp_1.Keyword.NONE;
const finding = new finding_1.Finding(type, description, severity, directive, value);
expect(finding.type).toBe(type);
expect(finding.description).toBe(description);
expect(finding.severity).toBe(severity);
expect(finding.directive).toBe(directive);
expect(finding.value).toBe(value);
});
it('GetHighestSeverity', () => {
const finding1 = new finding_1.Finding(finding_1.Type.MISSING_SEMICOLON, 'description', finding_1.Severity.HIGH, csp_1.Directive.SCRIPT_SRC);
const finding2 = new finding_1.Finding(finding_1.Type.MISSING_SEMICOLON, 'description', finding_1.Severity.MEDIUM, csp_1.Directive.SCRIPT_SRC);
const finding3 = new finding_1.Finding(finding_1.Type.MISSING_SEMICOLON, 'description', finding_1.Severity.INFO, csp_1.Directive.SCRIPT_SRC);
expect(finding_1.Finding.getHighestSeverity([
finding1, finding3, finding2, finding1
])).toBe(finding_1.Severity.HIGH);
expect(finding_1.Finding.getHighestSeverity([
finding3, finding2
])).toBe(finding_1.Severity.MEDIUM);
expect(finding_1.Finding.getHighestSeverity([
finding3, finding3
])).toBe(finding_1.Severity.INFO);
expect(finding_1.Finding.getHighestSeverity([])).toBe(finding_1.Severity.NONE);
});
});
//# sourceMappingURL=finding_test.js.map

1
node_modules/csp_evaluator/dist/finding_test.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"finding_test.js","sourceRoot":"","sources":["../finding_test.ts"],"names":[],"mappings":";;AAmBA,mBAAiB;AAEjB,+BAAyC;AACzC,uCAAkD;AAGlD,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;QACjB,MAAM,IAAI,GAAG,cAAI,CAAC,iBAAiB,CAAC;QACpC,MAAM,WAAW,GAAG,aAAa,CAAC;QAClC,MAAM,QAAQ,GAAG,kBAAQ,CAAC,IAAI,CAAC;QAC/B,MAAM,SAAS,GAAG,eAAS,CAAC,UAAU,CAAC;QACvC,MAAM,KAAK,GAAG,aAAO,CAAC,IAAI,CAAC;QAE3B,MAAM,OAAO,GAAG,IAAI,iBAAO,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;QAE3E,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,QAAQ,GAAG,IAAI,iBAAO,CACxB,cAAI,CAAC,iBAAiB,EAAE,aAAa,EAAE,kBAAQ,CAAC,IAAI,EACpD,eAAS,CAAC,UAAU,CAAC,CAAC;QAC1B,MAAM,QAAQ,GAAG,IAAI,iBAAO,CACxB,cAAI,CAAC,iBAAiB,EAAE,aAAa,EAAE,kBAAQ,CAAC,MAAM,EACtD,eAAS,CAAC,UAAU,CAAC,CAAC;QAC1B,MAAM,QAAQ,GAAG,IAAI,iBAAO,CACxB,cAAI,CAAC,iBAAiB,EAAE,aAAa,EAAE,kBAAQ,CAAC,IAAI,EACpD,eAAS,CAAC,UAAU,CAAC,CAAC;QAE1B,MAAM,CAAC,iBAAO,CAAC,kBAAkB,CAAC;YAChC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ;SACvC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,iBAAO,CAAC,kBAAkB,CAAC;YAChC,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAQ,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,iBAAO,CAAC,kBAAkB,CAAC;YAChC,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAQ,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,iBAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAQ,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

View File

@@ -0,0 +1,6 @@
import { Csp } from '../csp';
import { Finding } from '../finding';
export declare function evaluateForFailure(parsedCsps: Csp[]): Finding[];
export declare function evaluateForWarnings(parsedCsps: Csp[]): Finding[];
export declare function evaluateForSyntaxErrors(parsedCsps: Csp[]): Finding[][];
//# sourceMappingURL=lighthouse_checks.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"lighthouse_checks.d.ts","sourceRoot":"","sources":["../../lighthouse/lighthouse_checks.ts"],"names":[],"mappings":"AASA,OAAO,EAAC,GAAG,EAAqB,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAC;AA2EnC,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAsB/D;AAOD,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAShE;AAOD,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,EAAE,CAYtE"}

View File

@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.evaluateForSyntaxErrors = exports.evaluateForWarnings = exports.evaluateForFailure = void 0;
const parser_checks_1 = require("../checks/parser_checks");
const security_checks_1 = require("../checks/security_checks");
const strictcsp_checks_1 = require("../checks/strictcsp_checks");
const csp_1 = require("../csp");
function arrayContains(arr, elem) {
return arr.some(e => e.equals(elem));
}
function setIntersection(sets) {
const intersection = [];
if (sets.length === 0) {
return intersection;
}
const firstSet = sets[0];
for (const elem of firstSet) {
if (sets.every(set => arrayContains(set, elem))) {
intersection.push(elem);
}
}
return intersection;
}
function setUnion(sets) {
const union = [];
for (const set of sets) {
for (const elem of set) {
if (!arrayContains(union, elem)) {
union.push(elem);
}
}
}
return union;
}
function atLeastOnePasses(parsedCsps, checker) {
const findings = [];
for (const parsedCsp of parsedCsps) {
findings.push(checker(parsedCsp));
}
return setIntersection(findings);
}
function atLeastOneFails(parsedCsps, checker) {
const findings = [];
for (const parsedCsp of parsedCsps) {
findings.push(checker(parsedCsp));
}
return setUnion(findings);
}
function evaluateForFailure(parsedCsps) {
const targetsXssFindings = [
...atLeastOnePasses(parsedCsps, security_checks_1.checkMissingScriptSrcDirective),
...atLeastOnePasses(parsedCsps, security_checks_1.checkMissingObjectSrcDirective),
...security_checks_1.checkMultipleMissingBaseUriDirective(parsedCsps),
];
const effectiveCsps = parsedCsps.map(csp => csp.getEffectiveCsp(csp_1.Version.CSP3));
const effectiveCspsWithScript = effectiveCsps.filter(csp => {
const directiveName = csp.getEffectiveDirective(csp_1.Directive.SCRIPT_SRC);
return csp.directives[directiveName];
});
const robust = [
...atLeastOnePasses(effectiveCspsWithScript, strictcsp_checks_1.checkStrictDynamic),
...atLeastOnePasses(effectiveCspsWithScript, security_checks_1.checkScriptUnsafeInline),
...atLeastOnePasses(effectiveCsps, security_checks_1.checkWildcards),
...atLeastOnePasses(effectiveCsps, security_checks_1.checkPlainUrlSchemes),
];
return [...targetsXssFindings, ...robust];
}
exports.evaluateForFailure = evaluateForFailure;
function evaluateForWarnings(parsedCsps) {
return [
...atLeastOneFails(parsedCsps, strictcsp_checks_1.checkUnsafeInlineFallback),
...atLeastOneFails(parsedCsps, strictcsp_checks_1.checkAllowlistFallback)
];
}
exports.evaluateForWarnings = evaluateForWarnings;
function evaluateForSyntaxErrors(parsedCsps) {
const allFindings = [];
for (const csp of parsedCsps) {
const findings = [
...security_checks_1.checkNonceLength(csp), ...parser_checks_1.checkUnknownDirective(csp),
...security_checks_1.checkDeprecatedDirective(csp), ...parser_checks_1.checkMissingSemicolon(csp),
...parser_checks_1.checkInvalidKeyword(csp)
];
allFindings.push(findings);
}
return allFindings;
}
exports.evaluateForSyntaxErrors = evaluateForSyntaxErrors;
//# sourceMappingURL=lighthouse_checks.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"lighthouse_checks.js","sourceRoot":"","sources":["../../lighthouse/lighthouse_checks.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=lighthouse_checks_test.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"lighthouse_checks_test.d.ts","sourceRoot":"","sources":["../../lighthouse/lighthouse_checks_test.ts"],"names":[],"mappings":"AAIC,OAAO,SAAS,CAAC"}

View File

@@ -0,0 +1,403 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const finding_1 = require("../finding");
const parser_1 = require("../parser");
const lighthouseChecks = __importStar(require("./lighthouse_checks"));
function parsePolicies(policies) {
return policies.map(p => (new parser_1.CspParser(p)).csp);
}
describe('Test evaluateForFailure', () => {
it('robust nonce-based policy', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; object-src \'none\'; base-uri \'none\'';
const violations = lighthouseChecks.evaluateForFailure(parsePolicies([test]));
expect(violations.length).toBe(0);
});
it('robust hash-based policy', () => {
const test = 'script-src \'sha256-aaaaaaaaaa\'; object-src \'none\'';
const violations = lighthouseChecks.evaluateForFailure(parsePolicies([test]));
expect(violations.length).toBe(0);
});
it('policy not attempt', () => {
const test = 'block-all-mixed-content';
const violations = lighthouseChecks.evaluateForFailure(parsePolicies([test]));
expect(violations.length).toBe(2);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description).toBe('script-src directive is missing.');
expect(violations[1].severity).toBe(finding_1.Severity.HIGH);
expect(violations[1].directive).toBe('object-src');
expect(violations[1].description)
.toBe(`Missing object-src allows the injection of plugins which can execute JavaScript. Can you set it to 'none'?`);
});
it('policy not robust', () => {
const test = 'script-src *.google.com; object-src \'none\'';
const violations = lighthouseChecks.evaluateForFailure(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe(`Host allowlists can frequently be bypassed. Consider using 'strict-dynamic' in combination with CSP nonces or hashes.`);
});
it('robust policy and not robust policy', () => {
const policies = [
'script-src *.google.com; object-src \'none\'',
'script-src \'nonce-aaaaaaaaaa\'; base-uri \'none\''
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('split across many policies', () => {
const policies = [
'object-src \'none\'', 'script-src \'nonce-aaaaaaaaaa\'',
'base-uri \'none\''
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('split across many policies with default-src', () => {
const policies = ['default-src \'none\'', 'base-uri \'none\''];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('split across many policies some mixed useless policies', () => {
const policies = [
'object-src \'none\'', 'script-src \'nonce-aaaaaaaaaa\'',
'base-uri \'none\'', 'block-all-mixed-content'
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('split across many policies with allowlist', () => {
const policies = [
'object-src \'none\'', 'script-src \'nonce-aaaaaaaaaa\'',
'base-uri \'none\'', 'script-src *'
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('not robust and not attempt', () => {
const policies = ['block-all-mixed-content', 'script-src *.google.com'];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(2);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('object-src');
expect(violations[0].description)
.toBe(`Missing object-src allows the injection of plugins which can execute JavaScript. Can you set it to 'none'?`);
expect(violations[1].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[1].directive).toBe('script-src');
expect(violations[1].description)
.toBe(`Host allowlists can frequently be bypassed. Consider using \'strict-dynamic\' in combination with CSP nonces or hashes.`);
});
it('robust check only CSPs with script-src', () => {
const policies = ['script-src https://example.com', 'object-src \'none\''];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe(`Host allowlists can frequently be bypassed. Consider using \'strict-dynamic\' in combination with CSP nonces or hashes.`);
});
it('two not attempt', () => {
const policies = ['block-all-mixed-content', 'block-all-mixed-content'];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(2);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description).toBe('script-src directive is missing.');
expect(violations[1].severity).toBe(finding_1.Severity.HIGH);
expect(violations[1].directive).toBe('object-src');
expect(violations[1].description)
.toBe(`Missing object-src allows the injection of plugins which can execute JavaScript. Can you set it to 'none'?`);
});
it('two not attempt somewhat', () => {
const policies = [
'block-all-mixed-content; object-src \'none\'',
'block-all-mixed-content',
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description).toBe('script-src directive is missing.');
});
it('base-uri split across many policies', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaaa\'; object-src \'none\'',
'base-uri \'none\'',
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('base-uri not set', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaaa\'; object-src \'none\'',
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('base-uri');
expect(violations[0].description)
.toBe(`Missing base-uri allows the injection of base tags. They can be used to set the base URL for all relative (script) URLs to an attacker controlled domain. Can you set it to 'none' or 'self'?`);
});
it('base-uri not set in either policy', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaaa\'; object-src \'none\'',
'block-all-mixed-content'
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('base-uri');
});
it('check wildcards', () => {
const policies = ['script-src \'none\'; object-src *'];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('object-src');
expect(violations[0].description)
.toBe(`object-src should not allow '*' as source`);
});
it('check wildcards on multiple', () => {
const policies = ['script-src \'none\'; object-src *', 'object-src \'none\''];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('check plain url schemes', () => {
const policies = [
`script-src 'strict-dynamic' 'nonce-random123' 'unsafe-inline' https:; base-uri 'none'; object-src https:`
];
const violations = lighthouseChecks.evaluateForFailure(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.HIGH);
expect(violations[0].directive).toBe('object-src');
expect(violations[0].description)
.toBe(`https: URI in object-src allows the execution of unsafe scripts.`);
});
});
describe('Test evaluateForWarnings', () => {
it('perfect', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(0);
});
it('perfect except some failures', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url; object-src \'none\'',
'block-all-mixed-content'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('a perfect policy and a policy that does not target', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url; base-uri \'none\'; object-src \'none\'',
'block-all-mixed-content'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('perfect policy split into two', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url; base-uri \'none\'; ',
'block-all-mixed-content; object-src \'none\''
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('perfect policy split into three', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url; base-uri \'none\'; ',
'block-all-mixed-content', 'object-src \'none\''
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('no reporting and malformed', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; unknown-directive';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe('Consider adding \'unsafe-inline\' (ignored by browsers supporting nonces/hashes) to be backward compatible with older browsers.');
});
it('missing unsafe-inline fallback', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\'; report-uri url';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe('Consider adding \'unsafe-inline\' (ignored by browsers supporting nonces/hashes) to be backward compatible with older browsers.');
});
it('missing allowlist fallback', () => {
const test = 'script-src \'nonce-aaaaaaaaaa\' \'strict-dynamic\' \'unsafe-inline\'; report-uri url';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe('Consider adding https: and http: url schemes (ignored by browsers supporting \'strict-dynamic\') to be backward compatible with older browsers.');
});
it('missing semicolon', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'unsafe-inline\'; report-uri url object-src \'self\'';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(0);
});
it('invalid keyword', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'invalid\' \'unsafe-inline\'; report-uri url';
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies([test]));
expect(violations.length).toBe(0);
});
it('perfect policy and invalid policy', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:; report-uri url; base-uri \'none\'; object-src \'none\'',
'unknown'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('reporting on the wrong policy', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:',
'block-all-mixed-content; report-uri url'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(0);
});
it('missing unsafe-inline fallback split over two policies', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\'',
'block-all-mixed-content; report-uri url'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe('Consider adding \'unsafe-inline\' (ignored by browsers supporting nonces/hashes) to be backward compatible with older browsers.');
});
it('strict-dynamic with no fallback in any policy', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'strict-dynamic\'',
'block-all-mixed-content; report-uri url'
];
const violations = lighthouseChecks.evaluateForWarnings(parsePolicies(policies));
expect(violations.length).toBe(2);
expect(violations[0].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[0].directive).toBe('script-src');
expect(violations[0].description)
.toBe('Consider adding \'unsafe-inline\' (ignored by browsers supporting nonces/hashes) to be backward compatible with older browsers.');
expect(violations[1].severity).toBe(finding_1.Severity.STRICT_CSP);
expect(violations[1].directive).toBe('script-src');
expect(violations[1].description)
.toBe('Consider adding https: and http: url schemes (ignored by browsers supporting \'strict-dynamic\') to be backward compatible with older browsers.');
});
});
describe('Test evaluateForSyntaxErrors', () => {
it('whenPerfectPolicies', () => {
const policies = [
'script-src \'nonce-aaaaaaaaaa\' \'unsafe-inline\' http: https:',
'block-all-mixed-content; report-uri url'
];
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies(policies));
expect(violations.length).toBe(2);
expect(violations[0].length).toBe(0);
expect(violations[1].length).toBe(0);
});
it('whenShortNonce', () => {
const test = 'script-src \'nonce-a\' \'unsafe-inline\'; report-uri url';
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.MEDIUM);
expect(violations[0][0].directive).toBe('script-src');
expect(violations[0][0].description)
.toBe('Nonces should be at least 8 characters long.');
});
it('whenUnknownDirective', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'unsafe-inline\'; report-uri url; unknown';
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0][0].directive).toBe('unknown');
expect(violations[0][0].description)
.toBe('Directive "unknown" is not a known CSP directive.');
});
it('whenDeprecatedDirective', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'unsafe-inline\'; report-uri url; reflected-xss foo';
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.INFO);
expect(violations[0][0].directive).toBe('reflected-xss');
expect(violations[0][0].description)
.toBe('reflected-xss is deprecated since CSP2. Please, use the X-XSS-Protection header instead.');
});
it('whenMissingSemicolon', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'unsafe-inline\'; report-uri url object-src \'none\'';
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0][0].directive).toBe('report-uri');
expect(violations[0][0].description)
.toBe('Did you forget the semicolon? "object-src" seems to be a directive, not a value.');
});
it('whenInvalidKeyword', () => {
const test = 'script-src \'nonce-aaaaaaaaa\' \'unsafe-inline\'; object-src \'invalid\'';
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies([test]));
expect(violations.length).toBe(1);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0][0].directive).toBe('object-src');
expect(violations[0][0].description)
.toBe('\'invalid\' seems to be an invalid CSP keyword.');
});
it('manyPolicies', () => {
const policies = [
'object-src \'invalid\'', 'script-src \'none\'',
'script-src \'nonce-short\' default-src \'none\''
];
const violations = lighthouseChecks.evaluateForSyntaxErrors(parsePolicies(policies));
expect(violations.length).toBe(3);
expect(violations[0].length).toBe(1);
expect(violations[0][0].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[0][0].directive).toBe('object-src');
expect(violations[0][0].description)
.toBe('\'invalid\' seems to be an invalid CSP keyword.');
expect(violations[1].length).toBe(0);
expect(violations[2].length).toBe(2);
expect(violations[2][0].severity).toBe(finding_1.Severity.MEDIUM);
expect(violations[2][0].directive).toBe('script-src');
expect(violations[2][0].description)
.toBe('Nonces should be at least 8 characters long.');
expect(violations[2][1].severity).toBe(finding_1.Severity.SYNTAX);
expect(violations[2][1].directive).toBe('script-src');
expect(violations[2][1].description)
.toBe('Did you forget the semicolon? "default-src" seems to be a directive, not a value.');
});
});
//# sourceMappingURL=lighthouse_checks_test.js.map

File diff suppressed because one or more lines are too long

12
node_modules/csp_evaluator/dist/parser.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
import * as csp from './csp';
export declare class CspParser {
csp: csp.Csp;
constructor(unparsedCsp: string);
parse(unparsedCsp: string): csp.Csp;
}
declare function normalizeDirectiveValue(directiveValue: string): string;
export declare const TEST_ONLY: {
normalizeDirectiveValue: typeof normalizeDirectiveValue;
};
export {};
//# sourceMappingURL=parser.d.ts.map

1
node_modules/csp_evaluator/dist/parser.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../parser.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAQ7B,qBAAa,SAAS;IACpB,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC;gBAID,WAAW,EAAE,MAAM;IAa/B,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG,CAAC,GAAG;CAsCpC;AAQD,iBAAS,uBAAuB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED,eAAO,MAAM,SAAS;;CAA4B,CAAC"}

65
node_modules/csp_evaluator/dist/parser.js generated vendored Normal file
View File

@@ -0,0 +1,65 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.TEST_ONLY = exports.CspParser = void 0;
const csp = __importStar(require("./csp"));
class CspParser {
constructor(unparsedCsp) {
this.csp = new csp.Csp();
this.parse(unparsedCsp);
}
parse(unparsedCsp) {
this.csp = new csp.Csp();
const directiveTokens = unparsedCsp.split(';');
for (let i = 0; i < directiveTokens.length; i++) {
const directiveToken = directiveTokens[i].trim();
const directiveParts = directiveToken.match(/\S+/g);
if (Array.isArray(directiveParts)) {
const directiveName = directiveParts[0].toLowerCase();
if (directiveName in this.csp.directives) {
continue;
}
if (!csp.isDirective(directiveName)) {
}
const directiveValues = [];
for (let directiveValue, j = 1; (directiveValue = directiveParts[j]); j++) {
directiveValue = normalizeDirectiveValue(directiveValue);
if (!directiveValues.includes(directiveValue)) {
directiveValues.push(directiveValue);
}
}
this.csp.directives[directiveName] = directiveValues;
}
}
return this.csp;
}
}
exports.CspParser = CspParser;
function normalizeDirectiveValue(directiveValue) {
directiveValue = directiveValue.trim();
const directiveValueLower = directiveValue.toLowerCase();
if (csp.isKeyword(directiveValueLower) || csp.isUrlScheme(directiveValue)) {
return directiveValueLower;
}
return directiveValue;
}
exports.TEST_ONLY = { normalizeDirectiveValue };
//# sourceMappingURL=parser.js.map

1
node_modules/csp_evaluator/dist/parser.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../parser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAkBA,2CAA6B;AAQ7B,MAAa,SAAS;IAKpB,YAAY,WAAmB;QAI7B,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;QAEzB,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IAMD,KAAK,CAAC,WAAmB;QAEvB,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;QAGzB,MAAM,eAAe,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC/C,MAAM,cAAc,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAGjD,MAAM,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE;gBACjC,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;gBAKtD,IAAI,aAAa,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE;oBACxC,SAAS;iBACV;gBAED,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE;iBACpC;gBAED,MAAM,eAAe,GAAa,EAAE,CAAC;gBACrC,KAAK,IAAI,cAAc,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,EAC/D,CAAC,EAAE,EAAE;oBACR,cAAc,GAAG,uBAAuB,CAAC,cAAc,CAAC,CAAC;oBACzD,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE;wBAC7C,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;qBACtC;iBACF;gBACD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,eAAe,CAAC;aACtD;SACF;QAED,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;CACF;AAxDD,8BAwDC;AAQD,SAAS,uBAAuB,CAAC,cAAsB;IACrD,cAAc,GAAG,cAAc,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,mBAAmB,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IACzD,IAAI,GAAG,CAAC,SAAS,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE;QACzE,OAAO,mBAAmB,CAAC;KAC5B;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAEY,QAAA,SAAS,GAAG,EAAC,uBAAuB,EAAC,CAAC"}

2
node_modules/csp_evaluator/dist/parser_test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=parser_test.d.ts.map

1
node_modules/csp_evaluator/dist/parser_test.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_test.d.ts","sourceRoot":"","sources":["../parser_test.ts"],"names":[],"mappings":"AAmBA,OAAO,SAAS,CAAC"}

89
node_modules/csp_evaluator/dist/parser_test.js generated vendored Normal file
View File

@@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const parser_1 = require("./parser");
describe('Test parser', () => {
it('CspParser', () => {
const validCsp = 'default-src \'none\';' +
'script-src \'nonce-unsafefoobar\' \'unsafe-eval\' \'unsafe-inline\' \n' +
'https://example.com/foo.js foo.bar; ' +
'object-src \'none\';' +
'img-src \'self\' https: data: blob:;' +
'style-src \'self\' \'unsafe-inline\' \'sha256-1DCfk1NYWuHMfoobarfoobar=\';' +
'font-src *;' +
'child-src *.example.com:9090;' +
'upgrade-insecure-requests;\n' +
'report-uri /csp/test';
const parser = new (parser_1.CspParser)(validCsp);
const parsedCsp = parser.csp;
const directives = Object.keys(parsedCsp.directives);
const expectedDirectives = [
'default-src', 'script-src', 'object-src', 'img-src', 'style-src',
'font-src', 'child-src', 'upgrade-insecure-requests', 'report-uri'
];
expect(expectedDirectives)
.toEqual(jasmine.arrayWithExactContents(directives));
expect(['\'none\''])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['default-src']));
expect([
'\'nonce-unsafefoobar\'', '\'unsafe-eval\'', '\'unsafe-inline\'',
'https://example.com/foo.js', 'foo.bar'
])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['script-src']));
expect(['\'none\''])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['object-src']));
expect(['\'self\'', 'https:', 'data:', 'blob:'])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['img-src']));
expect([
'\'self\'', '\'unsafe-inline\'', '\'sha256-1DCfk1NYWuHMfoobarfoobar=\''
])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['style-src']));
expect(['*']).toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['font-src']));
expect(['*.example.com:9090'])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['child-src']));
expect([]).toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['upgrade-insecure-requests']));
expect(['/csp/test'])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['report-uri']));
});
it('CspParserDuplicateDirectives', () => {
const validCsp = 'default-src \'none\';' +
'default-src foo.bar;' +
'object-src \'none\';' +
'OBJECT-src foo.bar;';
const parser = new (parser_1.CspParser)(validCsp);
const parsedCsp = parser.csp;
const directives = Object.keys(parsedCsp.directives);
const expectedDirectives = ['default-src', 'object-src'];
expect(expectedDirectives)
.toEqual(jasmine.arrayWithExactContents(directives));
expect(['\'none\''])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['default-src']));
expect(['\'none\''])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['object-src']));
});
it('CspParserMixedCaseKeywords', () => {
const validCsp = 'DEFAULT-src \'NONE\';' +
'img-src \'sElf\' HTTPS: Example.com/CaseSensitive;';
const parser = new (parser_1.CspParser)(validCsp);
const parsedCsp = parser.csp;
const directives = Object.keys(parsedCsp.directives);
const expectedDirectives = ['default-src', 'img-src'];
expect(expectedDirectives)
.toEqual(jasmine.arrayWithExactContents(directives));
expect(['\'none\''])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['default-src']));
expect(['\'self\'', 'https:', 'Example.com/CaseSensitive'])
.toEqual(jasmine.arrayWithExactContents(parsedCsp.directives['img-src']));
});
it('NormalizeDirectiveValue', () => {
expect(parser_1.TEST_ONLY.normalizeDirectiveValue('\'nOnE\'')).toBe('\'none\'');
expect(parser_1.TEST_ONLY.normalizeDirectiveValue('\'nonce-aBcD\''))
.toBe('\'nonce-aBcD\'');
expect(parser_1.TEST_ONLY.normalizeDirectiveValue('\'hash-XyZ==\''))
.toBe('\'hash-XyZ==\'');
expect(parser_1.TEST_ONLY.normalizeDirectiveValue('HTTPS:')).toBe('https:');
expect(parser_1.TEST_ONLY.normalizeDirectiveValue('example.com/TEST'))
.toBe('example.com/TEST');
});
});
//# sourceMappingURL=parser_test.js.map

1
node_modules/csp_evaluator/dist/parser_test.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"parser_test.js","sourceRoot":"","sources":["../parser_test.ts"],"names":[],"mappings":";;AAmBA,mBAAiB;AAEjB,qCAA8C;AAG9C,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;QACnB,MAAM,QAAQ,GACV,uBAAuB;YACvB,0EAA0E;YAC1E,2CAA2C;YAC3C,sBAAsB;YACtB,sCAAsC;YACtC,4EAA4E;YAC5E,aAAa;YACb,+BAA+B;YAC/B,8BAA8B;YAC9B,sBAAsB,CAAC;QAE3B,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAS,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;QAG7B,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,kBAAkB,GAAG;YACzB,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW;YACjE,UAAU,EAAE,WAAW,EAAE,2BAA2B,EAAE,YAAY;SACnE,CAAC;QACF,MAAM,CAAC,kBAAkB,CAAC;aACrB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAGzD,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;aACf,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,aAAa,CAAa,CAAC,CAAC,CAAC;QAE1D,MAAM,CAAC;YACL,wBAAwB,EAAE,iBAAiB,EAAE,mBAAmB;YAChE,4BAA4B,EAAE,SAAS;SACxC,CAAC;aACG,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAa,CAAC,CAAC,CAAC;QAEzD,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;aACf,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAa,CAAC,CAAC,CAAC;QAEzD,MAAM,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;aAC3C,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAa,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC;YACL,UAAU,EAAE,mBAAmB,EAAE,sCAAsC;SACxE,CAAC;aACG,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAa,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAChD,SAAS,CAAC,UAAU,CAAC,UAAU,CAAa,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC;aACzB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAa,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAC7C,SAAS,CAAC,UAAU,CAAC,2BAA2B,CAAa,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,CAAC,WAAW,CAAC,CAAC;aAChB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAa,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,QAAQ,GAAG,uBAAuB;YACpC,sBAAsB;YACtB,sBAAsB;YACtB,qBAAqB,CAAC;QAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAS,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;QAG7B,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,kBAAkB,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QACzD,MAAM,CAAC,kBAAkB,CAAC;aACrB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAGzD,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;aACf,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,aAAa,CAAa,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;aACf,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,YAAY,CAAa,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACpC,MAAM,QAAQ,GAAG,uBAAuB;YAEpC,oDAAoD,CAAC;QAEzD,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAS,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC;QAG7B,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACrD,MAAM,kBAAkB,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;QACtD,MAAM,CAAC,kBAAkB,CAAC;aACrB,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC;QAGzD,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;aACf,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,aAAa,CAAa,CAAC,CAAC,CAAC;QAC1D,MAAM,CAAC,CAAC,UAAU,EAAE,QAAQ,EAAE,2BAA2B,CAAC,CAAC;aACtD,OAAO,CAAC,OAAO,CAAC,sBAAsB,CACnC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAa,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CAAC,kBAAS,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvE,MAAM,CAAC,kBAAS,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;aACtD,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5B,MAAM,CAAC,kBAAS,CAAC,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;aACtD,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC5B,MAAM,CAAC,kBAAS,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,MAAM,CAAC,kBAAS,CAAC,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;aACxD,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}

6
node_modules/csp_evaluator/dist/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,6 @@
import * as csp from './csp';
export declare function getSchemeFreeUrl(url: string): string;
export declare function getHostname(url: string): string;
export declare function matchWildcardUrls(cspUrlString: string, listOfUrlStrings: string[]): URL | null;
export declare function applyCheckFunktionToDirectives(parsedCsp: csp.Csp, check: (directive: string, directiveValues: string[]) => void): void;
//# sourceMappingURL=utils.d.ts.map

1
node_modules/csp_evaluator/dist/utils.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAQ7B,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpD;AAMD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAkB/C;AAgBD,wBAAgB,iBAAiB,CAC7B,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,GAAG,GAAC,IAAI,CAmD9D;AASD,wBAAgB,8BAA8B,CAC1C,SAAS,EAAE,GAAG,CAAC,GAAG,EAClB,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,KAAK,IAAI,QAUhE"}

74
node_modules/csp_evaluator/dist/utils.js generated vendored Normal file
View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyCheckFunktionToDirectives = exports.matchWildcardUrls = exports.getHostname = exports.getSchemeFreeUrl = void 0;
function getSchemeFreeUrl(url) {
url = url.replace(/^\w[+\w.-]*:\/\//i, '');
url = url.replace(/^\/\//, '');
return url;
}
exports.getSchemeFreeUrl = getSchemeFreeUrl;
function getHostname(url) {
const hostname = new URL('https://' +
getSchemeFreeUrl(url)
.replace(':*', '')
.replace('*', 'wildcard_placeholder'))
.hostname.replace('wildcard_placeholder', '*');
const ipv6Regex = /^\[[\d:]+\]/;
if (getSchemeFreeUrl(url).match(ipv6Regex) && !hostname.match(ipv6Regex)) {
return '[' + hostname + ']';
}
return hostname;
}
exports.getHostname = getHostname;
function setScheme(u) {
if (u.startsWith('//')) {
return u.replace('//', 'https://');
}
return u;
}
function matchWildcardUrls(cspUrlString, listOfUrlStrings) {
const cspUrl = new URL(setScheme(cspUrlString
.replace(':*', '')
.replace('*', 'wildcard_placeholder')));
const listOfUrls = listOfUrlStrings.map(u => new URL(setScheme(u)));
const host = cspUrl.hostname.toLowerCase();
const hostHasWildcard = host.startsWith('wildcard_placeholder.');
const wildcardFreeHost = host.replace(/^\wildcard_placeholder/i, '');
const path = cspUrl.pathname;
const hasPath = path !== '/';
for (const url of listOfUrls) {
const domain = url.hostname;
if (!domain.endsWith(wildcardFreeHost)) {
continue;
}
if (!hostHasWildcard && host !== domain) {
continue;
}
if (hasPath) {
if (path.endsWith('/')) {
if (!url.pathname.startsWith(path)) {
continue;
}
}
else {
if (url.pathname !== path) {
continue;
}
}
}
return url;
}
return null;
}
exports.matchWildcardUrls = matchWildcardUrls;
function applyCheckFunktionToDirectives(parsedCsp, check) {
const directiveNames = Object.keys(parsedCsp.directives);
for (const directive of directiveNames) {
const directiveValues = parsedCsp.directives[directive];
if (directiveValues) {
check(directive, directiveValues);
}
}
}
exports.applyCheckFunktionToDirectives = applyCheckFunktionToDirectives;
//# sourceMappingURL=utils.js.map

1
node_modules/csp_evaluator/dist/utils.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../utils.ts"],"names":[],"mappings":"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"}

2
node_modules/csp_evaluator/dist/utils_test.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import 'jasmine';
//# sourceMappingURL=utils_test.d.ts.map

1
node_modules/csp_evaluator/dist/utils_test.d.ts.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"utils_test.d.ts","sourceRoot":"","sources":["../utils_test.ts"],"names":[],"mappings":"AAkBA,OAAO,SAAS,CAAC"}

105
node_modules/csp_evaluator/dist/utils_test.js generated vendored Normal file
View File

@@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("jasmine");
const utils_1 = require("./utils");
const TEST_BYPASSES = [
'https://googletagmanager.com/gtm/js', 'https://www.google.com/jsapi',
'https://ajax.googleapis.com/ajax/services/feed/load'
];
describe('Test Utils', () => {
it('GetSchemeFreeUrl', () => {
expect(utils_1.getSchemeFreeUrl('https://*')).toBe('*');
expect(utils_1.getSchemeFreeUrl('//*')).toBe('*');
expect(utils_1.getSchemeFreeUrl('*')).toBe('*');
expect(utils_1.getSchemeFreeUrl('test//*')).toBe('test//*');
});
it('MatchWildcardUrlsMatchWildcardFreeHost', () => {
const wildcardFreeHost = '//www.google.com';
const match = utils_1.matchWildcardUrls(wildcardFreeHost, TEST_BYPASSES);
expect(match.hostname).toBe('www.google.com');
});
it('MatchWildcardUrlsNoMatch', () => {
const wildcardFreeHost = '//www.foo.bar';
const match = utils_1.matchWildcardUrls(wildcardFreeHost, TEST_BYPASSES);
expect(match).toBeNull();
});
it('MatchWildcardUrlsMatchWildcardHost', () => {
const wildcardHost = '//*.google.com';
const match = utils_1.matchWildcardUrls(wildcardHost, TEST_BYPASSES);
expect(match.hostname).toBe('www.google.com');
});
it('MatchWildcardUrlsNoMatchWildcardHost', () => {
const wildcardHost = '//*.www.google.com';
const match = utils_1.matchWildcardUrls(wildcardHost, TEST_BYPASSES);
expect(match).toBeNull();
});
it('MatchWildcardUrlsMatchWildcardHostWithPath', () => {
const wildcardHostWithPath = '//*.google.com/jsapi';
const match = utils_1.matchWildcardUrls(wildcardHostWithPath, TEST_BYPASSES);
expect(match.hostname).toBe('www.google.com');
});
it('MatchWildcardUrlsNoMatchWildcardHostWithPath', () => {
const wildcardHostWithPath = '//*.google.com/wrongPath';
const match = utils_1.matchWildcardUrls(wildcardHostWithPath, TEST_BYPASSES);
expect(match).toBeNull();
});
it('MatchWildcardUrlsMatchHostWithPathWildcard', () => {
const hostWithPath = '//ajax.googleapis.com/ajax/';
const match = utils_1.matchWildcardUrls(hostWithPath, TEST_BYPASSES);
expect(match.hostname).toBe('ajax.googleapis.com');
});
it('MatchWildcardUrlsNoMatchHostWithoutPathWildcard', () => {
const hostWithPath = '//ajax.googleapis.com/ajax';
const match = utils_1.matchWildcardUrls(hostWithPath, TEST_BYPASSES);
expect(match).toBeNull();
});
it('GetHostname', () => {
expect(utils_1.getHostname('https://www.google.com')).toBe('www.google.com');
});
it('GetHostnamePort', () => {
expect(utils_1.getHostname('https://www.google.com:8080')).toBe('www.google.com');
});
it('GetHostnameWildcardPort', () => {
expect(utils_1.getHostname('https://www.google.com:*')).toBe('www.google.com');
});
it('GetHostnameNoProtocol', () => {
expect(utils_1.getHostname('www.google.com')).toBe('www.google.com');
});
it('GetHostnameDoubleSlashProtocol', () => {
expect(utils_1.getHostname('//www.google.com')).toBe('www.google.com');
});
it('GetHostnameWildcard', () => {
expect(utils_1.getHostname('//*.google.com')).toBe('*.google.com');
});
it('GetHostnameWithPath', () => {
expect(utils_1.getHostname('//*.google.com/any/path')).toBe('*.google.com');
});
it('GetHostnameJustWildcard', () => {
expect(utils_1.getHostname('*')).toBe('*');
});
it('GetHostnameWildcardWithProtocol', () => {
expect(utils_1.getHostname('https://*')).toBe('*');
});
it('GetHostnameNonsense', () => {
expect(utils_1.getHostname('unsafe-inline')).toBe('unsafe-inline');
});
it('GetHostnameIPv4', () => {
expect(utils_1.getHostname('1.2.3.4')).toBe('1.2.3.4');
});
it('GetHostnameIPv6', () => {
expect(utils_1.getHostname('[::1]')).toBe('[::1]');
});
it('GetHostnameIPv4WithFullProtocol', () => {
expect(utils_1.getHostname('https://1.2.3.4')).toBe('1.2.3.4');
});
it('GetHostnameIPv6WithFullProtocol', () => {
expect(utils_1.getHostname('http://[::1]')).toBe('[::1]');
});
it('GetHostnameIPv4WithPartialProtocol', () => {
expect(utils_1.getHostname('//1.2.3.4')).toBe('1.2.3.4');
});
it('GetHostnameIPv6WithPartialProtocol', () => {
expect(utils_1.getHostname('//[::1]')).toBe('[::1]');
});
});
//# sourceMappingURL=utils_test.js.map

1
node_modules/csp_evaluator/dist/utils_test.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"utils_test.js","sourceRoot":"","sources":["../utils_test.ts"],"names":[],"mappings":"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"}