@salesforce/uibundle-sourcemap-validator-engine 11.35.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.
Files changed (63) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +243 -0
  3. package/dist/engine.d.ts +17 -0
  4. package/dist/engine.d.ts.map +1 -0
  5. package/dist/engine.js +142 -0
  6. package/dist/engine.js.map +1 -0
  7. package/dist/index.d.ts +19 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +18 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/plugin.d.ts +12 -0
  12. package/dist/plugin.d.ts.map +1 -0
  13. package/dist/plugin.js +22 -0
  14. package/dist/plugin.js.map +1 -0
  15. package/dist/rules.d.ts +9 -0
  16. package/dist/rules.d.ts.map +1 -0
  17. package/dist/rules.js +108 -0
  18. package/dist/rules.js.map +1 -0
  19. package/dist/validators/classification.d.ts +51 -0
  20. package/dist/validators/classification.d.ts.map +1 -0
  21. package/dist/validators/classification.js +120 -0
  22. package/dist/validators/classification.js.map +1 -0
  23. package/dist/validators/coverage-analysis.d.ts +32 -0
  24. package/dist/validators/coverage-analysis.d.ts.map +1 -0
  25. package/dist/validators/coverage-analysis.js +147 -0
  26. package/dist/validators/coverage-analysis.js.map +1 -0
  27. package/dist/validators/invalid-source-references.d.ts +9 -0
  28. package/dist/validators/invalid-source-references.d.ts.map +1 -0
  29. package/dist/validators/invalid-source-references.js +56 -0
  30. package/dist/validators/invalid-source-references.js.map +1 -0
  31. package/dist/validators/missing-sourcemap.d.ts +9 -0
  32. package/dist/validators/missing-sourcemap.d.ts.map +1 -0
  33. package/dist/validators/missing-sourcemap.js +92 -0
  34. package/dist/validators/missing-sourcemap.js.map +1 -0
  35. package/dist/validators/path-leakage.d.ts +9 -0
  36. package/dist/validators/path-leakage.d.ts.map +1 -0
  37. package/dist/validators/path-leakage.js +38 -0
  38. package/dist/validators/path-leakage.js.map +1 -0
  39. package/dist/validators/source-content-verification.d.ts +13 -0
  40. package/dist/validators/source-content-verification.d.ts.map +1 -0
  41. package/dist/validators/source-content-verification.js +465 -0
  42. package/dist/validators/source-content-verification.js.map +1 -0
  43. package/dist/validators/sourcemap-io.d.ts +21 -0
  44. package/dist/validators/sourcemap-io.d.ts.map +1 -0
  45. package/dist/validators/sourcemap-io.js +44 -0
  46. package/dist/validators/sourcemap-io.js.map +1 -0
  47. package/dist/validators/structural-coherence.d.ts +29 -0
  48. package/dist/validators/structural-coherence.d.ts.map +1 -0
  49. package/dist/validators/structural-coherence.js +247 -0
  50. package/dist/validators/structural-coherence.js.map +1 -0
  51. package/dist/validators/token-consistency.d.ts +32 -0
  52. package/dist/validators/token-consistency.d.ts.map +1 -0
  53. package/dist/validators/token-consistency.js +260 -0
  54. package/dist/validators/token-consistency.js.map +1 -0
  55. package/dist/validators/types.d.ts +19 -0
  56. package/dist/validators/types.d.ts.map +1 -0
  57. package/dist/validators/types.js +7 -0
  58. package/dist/validators/types.js.map +1 -0
  59. package/dist/validators/vlq-integrity.d.ts +9 -0
  60. package/dist/validators/vlq-integrity.d.ts.map +1 -0
  61. package/dist/validators/vlq-integrity.js +93 -0
  62. package/dist/validators/vlq-integrity.js.map +1 -0
  63. package/package.json +63 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,82 @@
1
+ Terms of Use
2
+
3
+ Copyright 2026 Salesforce, Inc. All rights reserved.
4
+
5
+ These Terms of Use govern the download, installation, and/or use of this
6
+ software provided by Salesforce, Inc. ("Salesforce") (the "Software"), were
7
+ last updated on April 15, 2025, and constitute a legally binding
8
+ agreement between you and Salesforce. If you do not agree to these Terms of
9
+ Use, do not install or use the Software.
10
+
11
+ Salesforce grants you a worldwide, non-exclusive, no-charge, royalty-free
12
+ copyright license to reproduce, prepare derivative works of, publicly
13
+ display, publicly perform, sublicense, and distribute the Software and
14
+ derivative works subject to these Terms. These Terms shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ Subject to the limited rights expressly granted hereunder, Salesforce
18
+ reserves all rights, title, and interest in and to all intellectual
19
+ property subsisting in the Software. No rights are granted to you hereunder
20
+ other than as expressly set forth herein. Users residing in countries on
21
+ the United States Office of Foreign Assets Control sanction list, or which
22
+ are otherwise subject to a US export embargo, may not use the Software.
23
+
24
+ Implementation of the Software may require development work, for which you
25
+ are responsible. The Software may contain bugs, errors and
26
+ incompatibilities and is made available on an AS IS basis without support,
27
+ updates, or service level commitments.
28
+
29
+ Salesforce reserves the right at any time to modify, suspend, or
30
+ discontinue, the Software (or any part thereof) with or without notice. You
31
+ agree that Salesforce shall not be liable to you or to any third party for
32
+ any modification, suspension, or discontinuance.
33
+
34
+ You agree to defend Salesforce against any claim, demand, suit or
35
+ proceeding made or brought against Salesforce by a third party arising out
36
+ of or accruing from (a) your use of the Software, and (b) any application
37
+ you develop with the Software that infringes any copyright, trademark,
38
+ trade secret, trade dress, patent, or other intellectual property right of
39
+ any person or defames any person or violates their rights of publicity or
40
+ privacy (each a "Claim Against Salesforce"), and will indemnify Salesforce
41
+ from any damages, attorney fees, and costs finally awarded against
42
+ Salesforce as a result of, or for any amounts paid by Salesforce under a
43
+ settlement approved by you in writing of, a Claim Against Salesforce,
44
+ provided Salesforce (x) promptly gives you written notice of the Claim
45
+ Against Salesforce, (y) gives you sole control of the defense and
46
+ settlement of the Claim Against Salesforce (except that you may not settle
47
+ any Claim Against Salesforce unless it unconditionally releases Salesforce
48
+ of all liability), and (z) gives you all reasonable assistance, at your
49
+ expense.
50
+
51
+ WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE SOFTWARE IS NOT
52
+ SUPPORTED AND IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ IMPLIED. IN NO EVENT SHALL SALESFORCE HAVE ANY LIABILITY FOR ANY DAMAGES,
54
+ INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
55
+ PUNITIVE, OR CONSEQUENTIAL DAMAGES, OR DAMAGES BASED ON LOST PROFITS, DATA,
56
+ OR USE, IN CONNECTION WITH THE SOFTWARE, HOWEVER CAUSED AND WHETHER IN
57
+ CONTRACT, TORT, OR UNDER ANY OTHER THEORY OF LIABILITY, WHETHER OR NOT YOU
58
+ HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
59
+
60
+ These Terms of Use shall be governed exclusively by the internal laws of
61
+ the State of California, without regard to its conflicts of laws
62
+ rules. Each party hereby consents to the exclusive jurisdiction of the
63
+ state and federal courts located in San Francisco County, California to
64
+ adjudicate any dispute arising out of or relating to these Terms of Use and
65
+ the download, installation, and/or use of the Software. Except as expressly
66
+ stated herein, these Terms of Use constitute the entire agreement between
67
+ the parties, and supersede all prior and contemporaneous agreements,
68
+ proposals, or representations, written or oral, concerning their subject
69
+ matter. No modification, amendment, or waiver of any provision of these
70
+ Terms of Use shall be effective unless it is by an update to these Terms of
71
+ Use that Salesforce makes available, or is in writing and signed by the
72
+ party against whom the modification, amendment, or waiver is to be
73
+ asserted.
74
+
75
+ Data Privacy: Salesforce may collect, process, and store device,
76
+ system, and other information related to your use of the Software. This
77
+ information includes, but is not limited to, IP address, user metrics, and
78
+ other data ("Usage Data"). Salesforce may use Usage Data for analytics,
79
+ product development, and marketing purposes. You acknowledge that files
80
+ generated in conjunction with the Software may contain sensitive or
81
+ confidential data, and you are solely responsible for anonymizing and
82
+ protecting such data.
package/README.md ADDED
@@ -0,0 +1,243 @@
1
+ # uibundle-sourcemap-validator-engine
2
+
3
+ A Salesforce Code Analyzer (SFCA v5+) custom engine that verifies UI Bundle build-output integrity by cross-checking each shipped `dist/` artifact against its declared sourcemap and the submitted `src/` tree.
4
+
5
+ **At a glance**
6
+
7
+ | | |
8
+ | ---------------------------------------------------------------------- | ------------------------------------------------- |
9
+ | npm package | `@salesforce/uibundle-sourcemap-validator-engine` |
10
+ | Engine identifier (in `--rule-selector`, `engines:`, violation output) | `uibundle-sourcemap-validator` |
11
+ | Aggregate tag (selects every rule this engine ships) | `UIBundleIntegrity` |
12
+ | Common tags every rule carries | `Recommended`, `Security`, `Javascript` |
13
+
14
+ ## What it does
15
+
16
+ Eight rules total. Each rule is tagged `Recommended` + `Security` + `Javascript` + `UIBundleIntegrity`. Five are gating (Layer 1: findings mean the bundle should fail review); three are informational (Layers 2–4: signal-generating diagnostics for suspicious mappings that do not on their own warrant a hard fail).
17
+
18
+ **Layer 1 — Gating (Critical / High / Moderate):**
19
+
20
+ | Rule | Severity | What it checks |
21
+ | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
22
+ | `missing-sourcemap` | High | Every `.js` in `dist/` has a co-located `.js.map` or an inline `//# sourceMappingURL`. Also flags orphan `.js` files that contain dangerous API substrings (e.g. `document.cookie`, `XMLHttpRequest`, dynamic-code sinks). |
23
+ | `path-leakage` | Moderate | `sources[]` entries are relative — no `/Users/...`, `C:\...`, `file://...` |
24
+ | `invalid-source-references` | High | Every `sources[]` entry (without inline `sourcesContent`) resolves to a real file on disk |
25
+ | `vlq-integrity` | High | `mappings` field is valid JSON, valid VLQ, and source/name indices are in range |
26
+ | `source-content-verification` | Critical | Byte-equal `sourcesContent` vs submitted source, virtual-source ratio cap (>20% flagged), AST coverage vs threshold (95% for files ≥500 nodes, 70% otherwise), AST type-mismatch (0.20 threshold with a compatibility matrix), dangerous-API pattern check on unmapped AST snippets. |
27
+
28
+ **Layers 2–4 — Informational (Info):**
29
+
30
+ | Rule | Severity | What it checks |
31
+ | ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32
+ | `coverage-analysis` | Info | Character-level coverage: per-line unmapped regions ≥ 50 chars, cumulative unmapped percentage > 2% (line-1 preamble discounted up to 150 chars). |
33
+ | `structural-coherence` | Info | Bounds check (mapped positions inside source file), whitespace/comment-only sampling every 10th mapping (>80% suspicious), cross-file jump ratio (>50% on consecutive same-line tokens). |
34
+ | `token-consistency` | Info | Every 20th token: source-vs-generated token category match (StringLiteral / NumericLiteral / Identifier / Punctuation / Other), name existence check within ±3 col of claimed position, verdict bands 0.85 warn / 0.70 suspicious. |
35
+
36
+ All eight rules are pure TypeScript — no native binaries, one npm install.
37
+
38
+ ## Lifecycle
39
+
40
+ This engine runs on **build output**, not source. Every UI Bundle must be built (`npm run build`) before `sf code-analyzer run` — otherwise the engine finds no `dist/` directory and logs an info message with zero violations (not a failure). This is a deliberate mismatch with SFCA's usual source-static model; documented at length in the design discussion in `docs/`.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ npm install --save-dev @salesforce/uibundle-sourcemap-validator-engine
46
+ ```
47
+
48
+ Enable in `code-analyzer.yml` at the SFDX project root. Note the split: the plugin is registered by its **npm package name** (`@salesforce/uibundle-sourcemap-validator-engine`), but the **engine identifier** used everywhere else in the config — and in `--rule-selector` on the CLI — is `uibundle-sourcemap-validator` (no `-engine` suffix, matching the SFCA convention where `@salesforce/code-analyzer-retirejs-engine` exposes an engine named `retire-js`, `code-analyzer-eslint-engine` exposes `eslint`, etc.).
49
+
50
+ ```yaml
51
+ custom_engine_plugin_modules:
52
+ - "@salesforce/uibundle-sourcemap-validator-engine" # npm package (has -engine suffix)
53
+
54
+ engines:
55
+ uibundle-sourcemap-validator: # engine identifier (no suffix)
56
+ disable_engine: false
57
+ ```
58
+
59
+ ### Recommended `code-analyzer.yml`
60
+
61
+ The following config is what the two demo projects use. It (a) registers the plugin, (b) tells every _other_ engine to ignore `dist/**` so they don't false-positive on minified bundler runtime code (the sourcemap-validator engine locates each UI Bundle via its `ui-bundle.json` marker in `src/` and reads the sibling `dist/` directly from disk, so it is unaffected by this ignore), and (c) disables the JVM-based engines that don't apply to a JS/UI-Bundle codebase:
62
+
63
+ ```yaml
64
+ custom_engine_plugin_modules:
65
+ - "@salesforce/uibundle-sourcemap-validator-engine"
66
+
67
+ # dist/** is built output. Excluding it from the workspace file list means the
68
+ # other engines (eslint, retire-js, regex, ...) never see it — no false positives
69
+ # on minified bundler runtime code. The sourcemap validator locates each UI
70
+ # Bundle via its `ui-bundle.json` / `*.uibundle-meta.xml` marker in src/ and
71
+ # reads the sibling dist/ directly from disk, so it is unaffected by this ignore.
72
+ ignores:
73
+ files:
74
+ - "**/dist/**"
75
+
76
+ suppressions:
77
+ "force-app/main/default/uiBundles":
78
+ - rule_selector: "eslint:@lwc/lwc"
79
+ - rule_selector: "eslint:@lwc/lwc-platform"
80
+
81
+ engines:
82
+ pmd:
83
+ disable_engine: true
84
+ cpd:
85
+ disable_engine: true
86
+ sfge:
87
+ disable_engine: true
88
+ flow:
89
+ disable_engine: true
90
+ uibundle-sourcemap-validator:
91
+ disable_engine: false
92
+ ```
93
+
94
+ ### Recommended invocation
95
+
96
+ Build every UI Bundle first (otherwise the engine finds no `dist/` and emits zero violations), then run the canonical AppExchange + Recommended-Security scan with the engine explicitly named:
97
+
98
+ ```bash
99
+ # 1. Build every UI Bundle in the SFDX project
100
+ for bundle in force-app/main/default/uiBundles/*/; do
101
+ (cd "$bundle" && npm run build)
102
+ done
103
+
104
+ # 2. Run the scan
105
+ sf code-analyzer run \
106
+ --rule-selector AppExchange \
107
+ --rule-selector Recommended:Security \
108
+ --rule-selector UIBundleIntegrity \
109
+ --output-file CodeAnalyzerReport.html
110
+ ```
111
+
112
+ Every selector is a **tag** — a label attached to rules, matched against the shape SFCA already uses (`AppExchange`, `Recommended:Security`). The three compose as a union:
113
+
114
+ | Selector | What it selects |
115
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
116
+ | `AppExchange` | Every rule tagged for AppExchange package review (from `pmd`, `regex`, `retire-js`, `eslint`, etc.) |
117
+ | `Recommended:Security` | Every rule tagged both `Recommended` and `Security` — this already picks up the eight `uibundle-sourcemap-validator` rules by their tags. |
118
+ | `UIBundleIntegrity` | Belt-and-braces: an engine-specific tag on every rule in `uibundle-sourcemap-validator`, so all eight run even if a future recommendation-tag pruning removed one of them from `Recommended:Security`. |
119
+
120
+ ## What the engine looks for
121
+
122
+ The engine scans targeted files for two UI Bundle markers:
123
+
124
+ 1. **Bundle roots** — directories containing `ui-bundle.json` or `*.uibundle-meta.xml`
125
+ 2. **`dist/` ancestors** — any targeted file living inside a `dist/` folder
126
+
127
+ For each bundle root found, the engine runs all eight validators against `<bundleRoot>/dist`. `source-content-verification`, `structural-coherence`, and `token-consistency` additionally require `<bundleRoot>/src` as the source path — if it doesn't exist those rules are skipped with a warn-level log message; the other five rules still run.
128
+
129
+ ## Sample output
130
+
131
+ Both scans below were produced with the recommended invocation against the two demo UI Bundles that ship with this repo (`demo/testb2epkgapp1` clean and `demo/testb2epkgapp1_vuln` after `node scripts/tamper.mjs --src <path>` planted six independent tamper vectors).
132
+
133
+ **Clean bundle** — 14 violations, 1 Critical + 13 Info. The single Critical is `source-content-verification` flagging two GraphQL `?raw` imports that the bundler inlines as pseudo-sources; every other finding is Info-tier signal (coverage anomalies on line 1 preamble, JSX runtime name narrowing, Radix member-expression name reporting).
134
+
135
+ ![Clean bundle SFCA report — 14 violations, all from uibundle-sourcemap-validator](docs/report-clean.png)
136
+
137
+ **Tampered bundle** — 48 violations across all planted vectors: absolute-path leakage in `sources[0]`, phantom source reference in `sources[1]`, byte-corrupted `sourcesContent[]`, 5 appended stealth functions after `//# sourceMappingURL`, 35% virtual-source ratio, and a planted `stealth-orphan.js` with dangerous-API substrings. 14 Critical + 3 High + 1 Moderate + 30 Info.
138
+
139
+ ![Tampered bundle SFCA report — 48 violations across missing-sourcemap, path-leakage, invalid-source-references, source-content-verification, coverage-analysis, structural-coherence, and token-consistency](docs/report-vuln.png)
140
+
141
+ Both HTML reports are checked into `docs/report-clean.html` and `docs/report-vuln.html` — open either in a browser to explore the full findings interactively.
142
+
143
+ ## Output
144
+
145
+ Violations are emitted in the standard SFCA format — SARIF, JSON, HTML, and CSV are all produced by SFCA's built-in formatters. CI integrations (GitHub code scanning, Sonar, etc.) that already ingest SFCA output work without changes.
146
+
147
+ ## Development
148
+
149
+ ```bash
150
+ npm install
151
+ npm run build # tsc → dist/
152
+ npm test # vitest
153
+ ```
154
+
155
+ ### Demo scripts
156
+
157
+ Three helper scripts under `scripts/` make it easy to see the engine catch real tampering without spinning up SFCA. All three require `--src <uiBundleRoot>` — the directory that contains the bundle's `src/` and `dist/`:
158
+
159
+ ```bash
160
+ # 1. Baseline scan of a clean bundle
161
+ node scripts/scan.mjs --src path/to/uiBundles/myBundle
162
+
163
+ # 2. Plant six tampering vectors in the bundle's dist/
164
+ node scripts/tamper.mjs --src path/to/uiBundles/myBundle
165
+
166
+ # 3. Re-scan and watch every vector get caught
167
+ node scripts/scan.mjs --src path/to/uiBundles/myBundle
168
+
169
+ # 4. Restore the bundle from .orig backups
170
+ node scripts/revert.mjs --src path/to/uiBundles/myBundle
171
+ ```
172
+
173
+ The tamper script plants six independent vectors, one per Layer-1 rule surface:
174
+
175
+ 1. `path-leakage` — rewrites `sources[0]` to `/Users/attacker/...`.
176
+ 2. `invalid-source-references` — rewrites `sources[1]` to a phantom path and nulls its inline `sourcesContent`.
177
+ 3. `source-content-verification` (AST/dangerous) — appends 5 exfil/backdoor functions after the `//# sourceMappingURL` comment.
178
+ 4. `source-content-verification` (byte-equal) — corrupts a `sourcesContent[i]` entry so it no longer matches the submitted source.
179
+ 5. `missing-sourcemap` (orphan-JS scan) — writes `stealth-orphan.js` into `dist/` with dangerous API patterns and no map.
180
+ 6. `source-content-verification` (virtual-source ratio) — rewrites ~35% of `sources[]` to bundler pseudo-paths (`webpack/…`, `vite/…`, `<runtime>`) to breach the 20% gate.
181
+
182
+ Tampering writes `<file>.orig` next to the modified files, so `revert.mjs` is always safe to run (it also deletes `stealth-orphan.js`).
183
+
184
+ Package layout:
185
+
186
+ ```
187
+ src/
188
+ ├── index.ts # Public exports
189
+ ├── engine.ts # SourcemapValidatorEngine (implements SFCA Engine)
190
+ ├── plugin.ts # SourcemapValidatorEnginePlugin (SFCA plugin entry)
191
+ ├── rules.ts # RuleDescription[]
192
+ └── validators/
193
+ ├── types.ts # ValidatorFinding, ValidatorResult
194
+ ├── sourcemap-io.ts # Shared: walk + collectSourceMaps
195
+ ├── classification.ts # Path helpers + dangerous-API pattern list
196
+ ├── missing-sourcemap.ts # Rule 1 (+ orphan-JS API scan)
197
+ ├── path-leakage.ts # Rule 2
198
+ ├── invalid-source-references.ts # Rule 3
199
+ ├── vlq-integrity.ts # Rule 4
200
+ ├── source-content-verification.ts # Rule 5 — byte-equal + AST coverage/type/dangerous
201
+ ├── coverage-analysis.ts # Rule 6 — Layer 2 char-level coverage (Info)
202
+ ├── structural-coherence.ts # Rule 7 — Layer 3 bounds/whitespace/jump (Info)
203
+ └── token-consistency.ts # Rule 8 — Layer 4 token type + name (Info)
204
+ tests/
205
+ ├── missing-sourcemap.test.ts
206
+ ├── path-leakage.test.ts
207
+ ├── invalid-source-references.test.ts
208
+ ├── vlq-integrity.test.ts
209
+ ├── source-content-verification.test.ts
210
+ ├── coverage-analysis.test.ts
211
+ ├── structural-coherence.test.ts
212
+ └── token-consistency.test.ts
213
+ ```
214
+
215
+ Validators are SFCA-agnostic — each takes a `distPath: string` and returns `ValidatorResult`. The engine layer maps findings to SFCA `Violation` objects. This keeps the validation logic independently testable and reusable outside SFCA.
216
+
217
+ ## Known limitations
218
+
219
+ - `source-content-verification` uses the bundle's `src/` sibling as the source root. Bundles that use a different layout will produce spurious "source not found" findings — configurable source path is on the roadmap.
220
+ - `invalid-source-references` skips inline `sourcesContent`. That's technically correct per the sourcemap spec (self-contained sources need not exist), but it also means an attacker can hide a fabricated source by embedding it inline. The `source-content-verification` rule is the mitigation — it walks compiled AST nodes and confirms each maps into a source file that actually exists.
221
+ - `@babel/parser` is used with `sourceType: 'unambiguous'` and JSX + TypeScript plugins enabled with `errorRecovery: true`, which handles the vast majority of UI Bundle build output. Extremely exotic dialects (e.g. Flow syntax, custom Babel plugin output) may fail to parse and surface a "compiled JS failed to parse" finding rather than a coverage measurement.
222
+
223
+ ## Inputs
224
+
225
+ The engine takes no CLI arguments — both the source and dist paths are derived automatically from the files SFCA passes in. For each targeted file, the engine walks up to find a `dist/` ancestor (or a `ui-bundle.json` / `*.uibundle-meta.xml` marker) and treats its parent as the bundle root. It then uses:
226
+
227
+ - `<bundleRoot>/dist` for all eight rules
228
+ - `<bundleRoot>/src` for `source-content-verification`, `structural-coherence`, and `token-consistency` (skipped with a `Warn` log if missing; the other five rules still run)
229
+
230
+ Example — scanning a UI bundle via the helper script:
231
+
232
+ ```bash
233
+ node scripts/scan.mjs --src path/to/uiBundles/myBundle
234
+ ```
235
+
236
+ ## Why pure TypeScript
237
+
238
+ Earlier iterations of this engine wrapped a Rust binary (`uibundle-sourcemap-validator`) for the AST-based Layer 1 check. That was dropped in favor of a pure-TS implementation using `@babel/parser` and `@jridgewell/trace-mapping`:
239
+
240
+ - **One npm install, no native binary** — the engine ships as a single package and works out of the box in every environment SFCA runs in (Node ≥ 18).
241
+ - **No output-format brittleness** — the earlier design shelled out and regex-parsed unstructured text from the Rust tool; direct API calls remove that failure mode.
242
+ - **Slower but fast enough** — `@babel/parser` is measurably slower than `oxc` on very large files, but SFCA's per-bundle scan is not a hot path.
243
+ - **Behavior parity** — all four Rust validation layers (source content, AST, coverage, coherence, token consistency) are ported line-for-line with the same thresholds (95/70% coverage, 0.20 type-mismatch, 20% virtual-source ratio, 2% cumulative unmapped, 50%/80% coherence, 0.70/0.85 token bands, ±3 col name tolerance) and the same significant-node set.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { Engine, type DescribeOptions, type EngineRunResults, type RuleDescription, type RunOptions } from "@salesforce/code-analyzer-engine-api";
7
+ export declare const ENGINE_NAME = "uibundle-sourcemap-validator";
8
+ export declare class SourcemapValidatorEngine extends Engine {
9
+ getName(): string;
10
+ getEngineVersion(): Promise<string>;
11
+ describeRules(_options: DescribeOptions): Promise<RuleDescription[]>;
12
+ runRules(ruleNames: string[], runOptions: RunOptions): Promise<EngineRunResults>;
13
+ private runOnTarget;
14
+ private consumeResult;
15
+ private findBundleTargets;
16
+ }
17
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EACN,MAAM,EAEN,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,UAAU,EAEf,MAAM,sCAAsC,CAAC;AA8B9C,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAO1D,qBAAa,wBAAyB,SAAQ,MAAM;IACnD,OAAO,IAAI,MAAM;IAIX,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAInC,aAAa,CAAC,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAIpE,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAoBxE,WAAW;IA8CzB,OAAO,CAAC,aAAa;YAkBP,iBAAiB;CA6B/B"}
package/dist/engine.js ADDED
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { promises as fs } from "node:fs";
7
+ import * as path from "node:path";
8
+ import { Engine, LogLevel, } from "@salesforce/code-analyzer-engine-api";
9
+ import { RULES, RULE_NAMES } from "./rules.js";
10
+ import { COVERAGE_ANALYSIS_RULE, validateCoverageAnalysis, } from "./validators/coverage-analysis.js";
11
+ import { INVALID_SOURCE_REFERENCES_RULE, validateInvalidSourceReferences, } from "./validators/invalid-source-references.js";
12
+ import { MISSING_SOURCEMAP_RULE, validateMissingSourcemaps, } from "./validators/missing-sourcemap.js";
13
+ import { PATH_LEAKAGE_RULE, validatePathLeakage } from "./validators/path-leakage.js";
14
+ import { SOURCE_CONTENT_VERIFICATION_RULE, validateSourceContent, } from "./validators/source-content-verification.js";
15
+ import { STRUCTURAL_COHERENCE_RULE, validateStructuralCoherence, } from "./validators/structural-coherence.js";
16
+ import { TOKEN_CONSISTENCY_RULE, validateTokenConsistency, } from "./validators/token-consistency.js";
17
+ import { VLQ_INTEGRITY_RULE, validateVlqIntegrity } from "./validators/vlq-integrity.js";
18
+ export const ENGINE_NAME = "uibundle-sourcemap-validator";
19
+ export class SourcemapValidatorEngine extends Engine {
20
+ getName() {
21
+ return ENGINE_NAME;
22
+ }
23
+ async getEngineVersion() {
24
+ return "0.1.0";
25
+ }
26
+ async describeRules(_options) {
27
+ return RULES;
28
+ }
29
+ async runRules(ruleNames, runOptions) {
30
+ const selected = ruleNames.filter((name) => RULE_NAMES.has(name));
31
+ if (selected.length === 0)
32
+ return { violations: [] };
33
+ const targets = await this.findBundleTargets(runOptions);
34
+ if (targets.length === 0) {
35
+ this.emitLogEvent(LogLevel.Info, `[${ENGINE_NAME}] No UI Bundle dist/ directories found. Run 'npm run build' in each UI Bundle before code analysis.`);
36
+ return { violations: [] };
37
+ }
38
+ const violations = [];
39
+ for (const target of targets) {
40
+ await this.runOnTarget(target, selected, violations);
41
+ }
42
+ return { violations };
43
+ }
44
+ async runOnTarget(target, selected, violations) {
45
+ const distOnlyDispatch = [
46
+ [MISSING_SOURCEMAP_RULE, () => validateMissingSourcemaps(target.distPath)],
47
+ [PATH_LEAKAGE_RULE, () => validatePathLeakage(target.distPath)],
48
+ [INVALID_SOURCE_REFERENCES_RULE, () => validateInvalidSourceReferences(target.distPath)],
49
+ [VLQ_INTEGRITY_RULE, () => validateVlqIntegrity(target.distPath)],
50
+ [COVERAGE_ANALYSIS_RULE, () => validateCoverageAnalysis(target.distPath)],
51
+ ];
52
+ for (const [ruleName, runValidator] of distOnlyDispatch) {
53
+ if (!selected.includes(ruleName))
54
+ continue;
55
+ const result = await runValidator();
56
+ this.consumeResult(ruleName, target.distPath, result, violations);
57
+ }
58
+ // Rules that also require the submitted source tree
59
+ const sourceDispatch = [
60
+ [SOURCE_CONTENT_VERIFICATION_RULE, validateSourceContent],
61
+ [STRUCTURAL_COHERENCE_RULE, validateStructuralCoherence],
62
+ [TOKEN_CONSISTENCY_RULE, validateTokenConsistency],
63
+ ];
64
+ for (const [ruleName, runValidator] of sourceDispatch) {
65
+ if (!selected.includes(ruleName))
66
+ continue;
67
+ if (!target.sourcePath) {
68
+ this.emitLogEvent(LogLevel.Warn, `[${ENGINE_NAME}] Skipping ${ruleName} for ${target.distPath}: could not locate a source directory sibling to dist/.`);
69
+ continue;
70
+ }
71
+ const result = await runValidator({
72
+ sourcePath: target.sourcePath,
73
+ distPath: target.distPath,
74
+ });
75
+ this.consumeResult(ruleName, target.distPath, result, violations);
76
+ }
77
+ }
78
+ consumeResult(ruleName, distPath, result, violations) {
79
+ if (result.skipped) {
80
+ this.emitLogEvent(LogLevel.Warn, `[${ENGINE_NAME}] ${ruleName} skipped for ${distPath}: ${result.skipped.reason}`);
81
+ return;
82
+ }
83
+ for (const finding of result.findings) {
84
+ violations.push(toViolation(finding));
85
+ }
86
+ }
87
+ async findBundleTargets(runOptions) {
88
+ const targetedFiles = await runOptions.workspace.getTargetedFiles();
89
+ const bundleRoots = new Set();
90
+ for (const file of targetedFiles) {
91
+ const base = path.basename(file);
92
+ if (base === "ui-bundle.json" || base.endsWith(".uibundle-meta.xml")) {
93
+ bundleRoots.add(path.dirname(file));
94
+ }
95
+ }
96
+ // Fallback: any file inside a dist/ directory contributes a bundle whose bundle root is that dist's parent.
97
+ for (const file of targetedFiles) {
98
+ const dist = findAncestorNamed(file, "dist");
99
+ if (dist)
100
+ bundleRoots.add(path.dirname(dist));
101
+ }
102
+ const targets = [];
103
+ for (const bundleRoot of bundleRoots) {
104
+ const distPath = path.join(bundleRoot, "dist");
105
+ if (!(await isDirectory(distPath)))
106
+ continue;
107
+ const srcPath = path.join(bundleRoot, "src");
108
+ const sourcePath = (await isDirectory(srcPath)) ? srcPath : null;
109
+ targets.push({ distPath, sourcePath });
110
+ }
111
+ return targets;
112
+ }
113
+ }
114
+ function toViolation(finding) {
115
+ // SFCA requires 1-based line/column; validators emit 0-based columns (Babel/trace-mapping).
116
+ const startLine = Math.max(1, finding.startLine ?? 1);
117
+ const rawCol = finding.startColumn;
118
+ const startColumn = rawCol == null ? 1 : Math.max(1, rawCol + 1);
119
+ return {
120
+ ruleName: finding.ruleName,
121
+ message: finding.message,
122
+ primaryLocationIndex: 0,
123
+ codeLocations: [{ file: finding.file, startLine, startColumn }],
124
+ };
125
+ }
126
+ async function isDirectory(p) {
127
+ try {
128
+ const stat = await fs.stat(p);
129
+ return stat.isDirectory();
130
+ }
131
+ catch {
132
+ return false;
133
+ }
134
+ }
135
+ function findAncestorNamed(filePath, name) {
136
+ const parts = filePath.split(path.sep);
137
+ const idx = parts.lastIndexOf(name);
138
+ if (idx <= 0)
139
+ return null;
140
+ return parts.slice(0, idx + 1).join(path.sep);
141
+ }
142
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ export { SourcemapValidatorEngine, ENGINE_NAME } from "./engine.js";
7
+ export { SourcemapValidatorEnginePlugin, createEnginePlugin } from "./plugin.js";
8
+ export { RULES } from "./rules.js";
9
+ export { MISSING_SOURCEMAP_RULE, validateMissingSourcemaps, } from "./validators/missing-sourcemap.js";
10
+ export { PATH_LEAKAGE_RULE, validatePathLeakage } from "./validators/path-leakage.js";
11
+ export { INVALID_SOURCE_REFERENCES_RULE, validateInvalidSourceReferences, } from "./validators/invalid-source-references.js";
12
+ export { VLQ_INTEGRITY_RULE, validateVlqIntegrity } from "./validators/vlq-integrity.js";
13
+ export { SOURCE_CONTENT_VERIFICATION_RULE, validateSourceContent, } from "./validators/source-content-verification.js";
14
+ export { COVERAGE_ANALYSIS_RULE, validateCoverageAnalysis, analyzeCoverage, } from "./validators/coverage-analysis.js";
15
+ export { STRUCTURAL_COHERENCE_RULE, validateStructuralCoherence, analyzeCoherence, pointsToWhitespaceOrComment, } from "./validators/structural-coherence.js";
16
+ export { TOKEN_CONSISTENCY_RULE, validateTokenConsistency, analyzeTokenConsistency, classifyTokenAt, } from "./validators/token-consistency.js";
17
+ export { DANGEROUS_API_PATTERNS, DANGEROUS_AST_EXTRA_PATTERNS, containsDangerousApi, containsDangerousPattern, isAsset, isDependency, isVirtualSource, normalizeSourcePath, } from "./validators/classification.js";
18
+ export type { ValidatorFinding, ValidatorResult } from "./validators/types.js";
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EACN,sBAAsB,EACtB,yBAAyB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EACN,8BAA8B,EAC9B,+BAA+B,GAC/B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EACN,gCAAgC,EAChC,qBAAqB,GACrB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,GACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACN,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,EACxB,OAAO,EACP,YAAY,EACZ,eAAe,EACf,mBAAmB,GACnB,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ export { SourcemapValidatorEngine, ENGINE_NAME } from "./engine.js";
7
+ export { SourcemapValidatorEnginePlugin, createEnginePlugin } from "./plugin.js";
8
+ export { RULES } from "./rules.js";
9
+ export { MISSING_SOURCEMAP_RULE, validateMissingSourcemaps, } from "./validators/missing-sourcemap.js";
10
+ export { PATH_LEAKAGE_RULE, validatePathLeakage } from "./validators/path-leakage.js";
11
+ export { INVALID_SOURCE_REFERENCES_RULE, validateInvalidSourceReferences, } from "./validators/invalid-source-references.js";
12
+ export { VLQ_INTEGRITY_RULE, validateVlqIntegrity } from "./validators/vlq-integrity.js";
13
+ export { SOURCE_CONTENT_VERIFICATION_RULE, validateSourceContent, } from "./validators/source-content-verification.js";
14
+ export { COVERAGE_ANALYSIS_RULE, validateCoverageAnalysis, analyzeCoverage, } from "./validators/coverage-analysis.js";
15
+ export { STRUCTURAL_COHERENCE_RULE, validateStructuralCoherence, analyzeCoherence, pointsToWhitespaceOrComment, } from "./validators/structural-coherence.js";
16
+ export { TOKEN_CONSISTENCY_RULE, validateTokenConsistency, analyzeTokenConsistency, classifyTokenAt, } from "./validators/token-consistency.js";
17
+ export { DANGEROUS_API_PATTERNS, DANGEROUS_AST_EXTRA_PATTERNS, containsDangerousApi, containsDangerousPattern, isAsset, isDependency, isVirtualSource, normalizeSourcePath, } from "./validators/classification.js";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EACN,sBAAsB,EACtB,yBAAyB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACtF,OAAO,EACN,8BAA8B,EAC9B,+BAA+B,GAC/B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EACN,gCAAgC,EAChC,qBAAqB,GACrB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,eAAe,GACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACN,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACN,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,eAAe,GACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,oBAAoB,EACpB,wBAAwB,EACxB,OAAO,EACP,YAAY,EACZ,eAAe,EACf,mBAAmB,GACnB,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { EnginePluginV1, type ConfigObject, type Engine } from "@salesforce/code-analyzer-engine-api";
7
+ export declare class SourcemapValidatorEnginePlugin extends EnginePluginV1 {
8
+ getAvailableEngineNames(): string[];
9
+ createEngine(engineName: string, _resolvedConfig: ConfigObject): Promise<Engine>;
10
+ }
11
+ export declare function createEnginePlugin(): SourcemapValidatorEnginePlugin;
12
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,cAAc,EACd,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,MAAM,sCAAsC,CAAC;AAG9C,qBAAa,8BAA+B,SAAQ,cAAc;IACjE,uBAAuB,IAAI,MAAM,EAAE;IAI7B,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;CAMtF;AAED,wBAAgB,kBAAkB,IAAI,8BAA8B,CAEnE"}
package/dist/plugin.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { EnginePluginV1, } from "@salesforce/code-analyzer-engine-api";
7
+ import { ENGINE_NAME, SourcemapValidatorEngine } from "./engine.js";
8
+ export class SourcemapValidatorEnginePlugin extends EnginePluginV1 {
9
+ getAvailableEngineNames() {
10
+ return [ENGINE_NAME];
11
+ }
12
+ async createEngine(engineName, _resolvedConfig) {
13
+ if (engineName !== ENGINE_NAME) {
14
+ throw new Error(`Unknown engine: ${engineName}`);
15
+ }
16
+ return new SourcemapValidatorEngine();
17
+ }
18
+ }
19
+ export function createEnginePlugin() {
20
+ return new SourcemapValidatorEnginePlugin();
21
+ }
22
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,cAAc,GAGd,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAEpE,MAAM,OAAO,8BAA+B,SAAQ,cAAc;IACjE,uBAAuB;QACtB,OAAO,CAAC,WAAW,CAAC,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAkB,EAAE,eAA6B;QACnE,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,mBAAmB,UAAU,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,wBAAwB,EAAE,CAAC;IACvC,CAAC;CACD;AAED,MAAM,UAAU,kBAAkB;IACjC,OAAO,IAAI,8BAA8B,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+ import { type RuleDescription } from "@salesforce/code-analyzer-engine-api";
7
+ export declare const RULES: RuleDescription[];
8
+ export declare const RULE_NAMES: Set<string>;
9
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAGN,KAAK,eAAe,EACpB,MAAM,sCAAsC,CAAC;AAE9C,eAAO,MAAM,KAAK,EAAE,eAAe,EA2GlC,CAAC;AAEF,eAAO,MAAM,UAAU,aAAoC,CAAC"}