Next.js website for Rocky Mountain Vending company featuring: - Product catalog with Stripe integration - Service areas and parts pages - Admin dashboard with Clerk authentication - SEO optimized pages with JSON-LD structured data Co-authored-by: Cursor <cursoragent@cursor.com>
235 lines
No EOL
10 KiB
Text
235 lines
No EOL
10 KiB
Text
"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(directives = {}) {
|
|
this.directives = {};
|
|
for (const [directive, directiveValues] of Object.entries(directives)) {
|
|
if (directiveValues) {
|
|
this.directives[directive] = [...directiveValues];
|
|
}
|
|
}
|
|
}
|
|
clone() {
|
|
return new Csp(this.directives);
|
|
}
|
|
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();
|
|
[Directive.SCRIPT_SRC, Directive.SCRIPT_SRC_ATTR, Directive.SCRIPT_SRC_ELEM]
|
|
.forEach(directiveToNormalize => {
|
|
const directive = effectiveCsp.getEffectiveDirective(directiveToNormalize);
|
|
const values = this.directives[directive] || [];
|
|
const effectiveCspValues = effectiveCsp.directives[directive];
|
|
if (effectiveCspValues &&
|
|
(effectiveCsp.policyHasScriptNonces(directive) ||
|
|
effectiveCsp.policyHasScriptHashes(directive))) {
|
|
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(directive)) {
|
|
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];
|
|
delete effectiveCsp.directives[Directive.SCRIPT_SRC_ATTR];
|
|
delete effectiveCsp.directives[Directive.SCRIPT_SRC_ELEM];
|
|
delete effectiveCsp.directives[Directive.STYLE_SRC_ATTR];
|
|
delete effectiveCsp.directives[Directive.STYLE_SRC_ELEM];
|
|
}
|
|
return effectiveCsp;
|
|
}
|
|
getEffectiveDirective(directive) {
|
|
if (directive in this.directives) {
|
|
return directive;
|
|
}
|
|
if ((directive === Directive.SCRIPT_SRC_ATTR ||
|
|
directive === Directive.SCRIPT_SRC_ELEM) &&
|
|
Directive.SCRIPT_SRC in this.directives) {
|
|
return Directive.SCRIPT_SRC;
|
|
}
|
|
if ((directive === Directive.STYLE_SRC_ATTR ||
|
|
directive === Directive.STYLE_SRC_ELEM) &&
|
|
Directive.STYLE_SRC in this.directives) {
|
|
return Directive.STYLE_SRC;
|
|
}
|
|
if (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(directive) {
|
|
const directiveName = this.getEffectiveDirective(directive || Directive.SCRIPT_SRC);
|
|
const values = this.directives[directiveName] || [];
|
|
return values.some((val) => isNonce(val));
|
|
}
|
|
policyHasScriptHashes(directive) {
|
|
const directiveName = this.getEffectiveDirective(directive || Directive.SCRIPT_SRC);
|
|
const values = this.directives[directiveName] || [];
|
|
return values.some((val) => isHash(val));
|
|
}
|
|
policyHasStrictDynamic(directive) {
|
|
const directiveName = this.getEffectiveDirective(directive || 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["INLINE_SPECULATION_RULES"] = "'inline-speculation-rules'";
|
|
})(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 |