Rocky_Mountain_Vending/.pnpm-store/v10/files/90/da7db00c3b8f00376b9cddf329c9d7ec01c7a13303032b5c49edbbdeae2d49243f012fee3e6e3925130206ba3c6079828f71bb69847429afcdc49b16daf880
DMleadgen 46d973904b
Initial commit: Rocky Mountain Vending website
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>
2026-02-12 16:22:15 -07:00

520 lines
19 KiB
Text

/**
* @license
* Copyright 2016 Google Inc. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @fileoverview Tests for CSP Evaluator Checks.
* @author lwe@google.com (Lukas Weichselbaum)
*/
import {Directive, Version} from '../csp';
import {Finding, Severity} from '../finding';
import {CspParser} from '../parser';
import {CheckerFunction} from './checker';
import * as securityChecks from './security_checks';
/**
* Helper function for running a check on a CSP string.
*
* @param test CSP string.
* @param checkFunction check.
*/
function checkCsp(test: string, checkFunction: CheckerFunction): Finding[] {
const parsedCsp = (new CspParser(test)).csp;
return checkFunction(parsedCsp);
}
describe('Test security checks', () => {
/** Tests for csp.securityChecks.checkScriptUnsafeInline */
it('CheckScriptUnsafeInlineInScriptSrc', () => {
const test =
'default-src https:; script-src \'unsafe-inline\'; script-src-elem \'unsafe-inline\';';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(2);
expect(violations[0].severity).toBe(Severity.HIGH);
});
it('CheckScriptUnsafeInlineInDefaultSrc', () => {
const test = 'default-src \'unsafe-inline\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(1);
});
it('CheckScriptUnsafeHashesInScriptSrc', () => {
const test =
'script-src \'unsafe-hashes\' \'sha256-1DCfk1NYWuHMfoobarfoobar=\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(Severity.MEDIUM_MAYBE);
});
it('CheckScriptUnsafeInlineInDefaultSrcAndNotInScriptSrc', () => {
const test =
'default-src \'unsafe-inline\'; script-src https:; script-src-attr https:; script-src-elem https:';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(0);
});
it('CheckScriptUnsafeInlineWithNonce', () => {
const test =
'script-src \'unsafe-inline\' \'nonce-foobar\'; script-src-elem \'unsafe-inline\' \'nonce-foobar\';';
const parsedCsp = (new CspParser(test)).csp;
let effectiveCsp = parsedCsp.getEffectiveCsp(Version.CSP1);
let violations = securityChecks.checkScriptUnsafeInline(effectiveCsp);
// script-src-elem and script-src-attr are ignored
expect(violations.length).toBe(1);
effectiveCsp = parsedCsp.getEffectiveCsp(Version.CSP3);
violations = securityChecks.checkScriptUnsafeInline(effectiveCsp);
expect(violations.length).toBe(0);
});
/** Tests for csp.securityChecks.checkScriptUnsafeEval */
it('CheckScriptUnsafeEvalInScriptSrc', () => {
const test =
'default-src https:; script-src \'unsafe-eval\'; script-src-attr \'unsafe-eval\'; script-src-elem \'unsafe-eval\';';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeEval);
expect(violations.length).toBe(3);
expect(violations.every((v) => v.severity === Severity.MEDIUM_MAYBE))
.toBeTrue();
});
it('CheckScriptUnsafeEvalInDefaultSrc', () => {
const test = 'default-src \'unsafe-eval\'';
const violations = checkCsp(test, securityChecks.checkScriptUnsafeEval);
expect(violations.length).toBe(1);
});
/** Tests for csp.securityChecks.checkPlainUrlSchemes */
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 === 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 === 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 === 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 === Severity.HIGH)).toBeTrue();
expect(violations[0].directive).toBe(Directive.DEFAULT_SRC);
expect(violations[1].directive).toBe(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);
});
/** Tests for csp.securityChecks.checkWildcards */
it('CheckWildcardsInScriptSrc', () => {
const test =
'script-src * http://* //*; script-src-attr * http://* //*; script-src-elem * http://* //*';
const violations = checkCsp(test, securityChecks.checkWildcards);
expect(violations.length).toBe(9);
expect(violations.every((v) => v.severity === 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 === 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 === 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 === Severity.HIGH)).toBeTrue();
expect(violations[0].directive).toBe(Directive.DEFAULT_SRC);
expect(violations[1].directive).toBe(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);
});
/** Tests for csp.securityChecks.checkMissingDirectives */
it('CheckMissingDirectivesMissingObjectSrc', () => {
const test = 'script-src \'none\'';
const violations = checkCsp(test, securityChecks.checkMissingDirectives);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(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(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(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(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(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);
});
/** Tests for csp.securityChecks.checkScriptAllowlistBypass */
it('checkScriptAllowlistBypassJSONPBypass', () => {
const test = 'script-src *.google.com';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(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\'; script-src-elem *.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\'; script-src-elem https://googletagmanager.com \'unsafe-eval\'';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === Severity.HIGH)).toBeTrue();
});
it('checkScriptAllowlistBypassJSONPBypassEvalRequiredNotPresent', () => {
const test =
'script-src https://googletagmanager.com; script-src-elem https://googletagmanager.com;';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === Severity.MEDIUM_MAYBE))
.toBeTrue();
});
it('checkScriptAllowlistBypassAngularBypass', () => {
const test = 'script-src gstatic.com; script-src-elem gstatic.com';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === Severity.HIGH)).toBeTrue();
expect(violations.every(
(v) => v.description.includes(
'gstatic.com is known to host Angular libraries which')))
.toBeTrue();
});
it('checkScriptAllowlistBypassNoBypassWarningOnly', () => {
const test = 'script-src foo.bar; script-src-elem foo.bar';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === Severity.MEDIUM_MAYBE))
.toBeTrue();
});
it('checkScriptAllowlistBypassNoBypassSelfWarningOnly', () => {
const test =
'script-src \'self\'; script-src-attr \'self\'; script-src-elem \'self\'';
const violations =
checkCsp(test, securityChecks.checkScriptAllowlistBypass);
expect(violations.length).toBe(2);
expect(violations.every((v) => v.severity === Severity.MEDIUM_MAYBE))
.toBeTrue();
});
/** Tests for csp.securityChecks.checkFlashObjectAllowlistBypass */
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(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(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(Severity.MEDIUM_MAYBE);
expect(violations[0].description)
.toBe('Can you restrict object-src to \'none\' only?');
});
/** Tests for csp.securityChecks.checkIpSource */
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 === 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(Severity.INFO);
});
it('CheckDeprecatedDirectiveReferrer', () => {
const test = 'referrer origin';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(Severity.INFO);
});
it('CheckDeprecatedDirectivePrefetchSrc', () => {
const test = 'prefetch-src test';
const violations = checkCsp(test, securityChecks.checkDeprecatedDirective);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(Severity.INFO);
});
/** Tests for csp.securityChecks.checkNonceLength */
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(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(Severity.INFO);
});
/** Tests for csp.securityChecks.checkSrcHttp */
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 === Severity.MEDIUM)).toBeTrue();
});
/** Tests for csp.securityChecks.checkHasConfiguredReporting */
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(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(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);
});
// The nonce that is present in the script-src directive should not override
// the unsafe-inline in the script-src-elem directive.
it('checkScriptUnsafeInline_notOverriddenForScriptSrcElem', () => {
const test =
'script-src \'nonce-aaaaaaaaaa\' strict-dynamic; script-src-elem \'unsafe-inline\';';
// Make sure there are no ignored directives.
const parsedCsp = (new CspParser(test)).csp;
const findings: Finding[] = [];
const effectiveCsp = parsedCsp.getEffectiveCsp(Version.CSP3, findings);
expect(findings.length).toBe(0);
// And make sure testing the normalized CSP does not have any unexpected
// violations.
const violations = checkCsp(
effectiveCsp.convertToString(), securityChecks.checkScriptUnsafeInline);
expect(violations.length).toBe(1);
expect(violations[0].severity).toBe(Severity.HIGH);
});
});