@salesforce/internal-lightning-out-containers 2.2.6 → 2.2.7-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,8 +5,19 @@
5
5
  */
6
6
 
7
7
  import { assertBareSpecifier } from "../env";
8
+ import { isComponentNameCheckDisabled } from "../gater";
9
+
10
+ jest.mock("../gater", () => ({
11
+ isComponentNameCheckDisabled: jest.fn(() => false),
12
+ }));
13
+
14
+ const mockIsDisabled = isComponentNameCheckDisabled;
8
15
 
9
16
  describe("assertBareSpecifier", () => {
17
+ beforeEach(() => {
18
+ mockIsDisabled.mockReturnValue(false);
19
+ });
20
+
10
21
  describe("accepts bare identifiers", () => {
11
22
  it.each([
12
23
  "c/foo",
@@ -51,4 +62,17 @@ describe("assertBareSpecifier", () => {
51
62
  it("returns null for null input (missing URL param)", () => {
52
63
  expect(assertBareSpecifier(null)).toBeNull();
53
64
  });
65
+
66
+ describe("kill-switch gate", () => {
67
+ it("bypasses validation and returns value unchanged when gate is open", () => {
68
+ mockIsDisabled.mockReturnValue(true);
69
+ const unsafe = "https://evil.com/payload.js";
70
+ expect(assertBareSpecifier(unsafe)).toBe(unsafe);
71
+ });
72
+
73
+ it("still returns null for null input when gate is open", () => {
74
+ mockIsDisabled.mockReturnValue(true);
75
+ expect(assertBareSpecifier(null)).toBeNull();
76
+ });
77
+ });
54
78
  });
@@ -4,6 +4,8 @@
4
4
  * Company Confidential
5
5
  */
6
6
 
7
+ import { isComponentNameCheckDisabled } from "./gater";
8
+
7
9
  // Bare LWC (namespace/name) or Aura (namespace:name) identifier, with optional /v/<version> suffix.
8
10
  // Rejects URL-shaped strings — a specifier reaching `import()` must be resolved as a module,
9
11
  // not a URL. LWR's AMD loader treats URL-shaped specifiers as fetchable script sources, which
@@ -13,6 +15,7 @@ const BARE_SPECIFIER = /^[a-zA-Z][a-zA-Z0-9_-]*[/:][a-zA-Z][a-zA-Z0-9_-]*(\/v\/[
13
15
 
14
16
  export function assertBareSpecifier(value) {
15
17
  if (value === null) return null;
18
+ if (isComponentNameCheckDisabled()) return value;
16
19
  if (!BARE_SPECIFIER.test(value)) {
17
20
  throw new Error(`Invalid componentName: ${value}`);
18
21
  }
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Copyright 2026 salesforce.com, inc.
3
+ * All Rights Reserved
4
+ * Company Confidential
5
+ */
6
+
7
+ import disableComponentNameCheckGate from "@salesforce/gate/org.salesforce.lo2.lwr.disableComponentNameCheck";
8
+
9
+ /**
10
+ * Kill-switch for componentName bare-specifier validation (W-23730644).
11
+ * SECURITY: opening re-enables arbitrary-script-load via URL-shaped componentName;
12
+ * bounded only by CSP. See env.ts BARE_SPECIFIER for the regex + threat model.
13
+ */
14
+ let warned = false;
15
+
16
+ export function isComponentNameCheckDisabled() {
17
+ const disabled = disableComponentNameCheckGate.isOpen({ fallback: false });
18
+ if (disabled && !warned) {
19
+ warned = true;
20
+ console.warn(
21
+ "[LO2] componentName validation bypassed via kill-switch gate " +
22
+ "(org.salesforce.lo2.lwr.disableComponentNameCheck). Security fix W-23730644 inactive.",
23
+ );
24
+ }
25
+ return disabled;
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/internal-lightning-out-containers",
3
- "version": "2.2.6",
3
+ "version": "2.2.7-rc.0",
4
4
  "private": false,
5
5
  "description": "Lightning Out 2.0 Container Components",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",