Skip to content

Commit 1b58848

Browse files
authored
Merge pull request #1534 from forcedotcom/release-4.3.1
RELEASE @W-16153325@ Conducting v4.3.2 patch release
2 parents 3e8e7c9 + 2cdd033 commit 1b58848

File tree

11 files changed

+1153
-920
lines changed

11 files changed

+1153
-920
lines changed

.github/workflows/create-release-branch.yml

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ jobs:
6060
with:
6161
node-version: 'lts/*' # Always use Node LTS for building dependencies.
6262
- run: yarn
63-
# Increment the version as desired.
64-
- name: Increment version
63+
# Increment the version as desired locally, without actually commiting anything.
64+
- name: Locally increment version
6565
run: |
6666
# A workflow dispatch event lets the user specify what release type they want.
6767
if [[ "${{ github.event_name }}" = "workflow_dispatch" ]]; then
@@ -72,22 +72,25 @@ jobs:
7272
fi
7373
# Increment the version as needed.
7474
npm --no-git-tag-version version $RELEASE_TYPE
75-
# Create the new branch as a direct copy of `dev` and push it to GitHub so the API can
76-
# interact with it later.
77-
- id: create-branch
75+
# The branch protection rule for `release-x.y.z` branches prevents pushing commits directly. To work around this,
76+
# we create an interim branch that we _can_ push commits to, and we'll do our version bookkeeping in that branch
77+
# instead.
78+
- id: create-interim-branch
79+
name: Create interim branch
7880
run: |
7981
NEW_VERSION=$(jq -r ".version" package.json)
80-
git checkout -b release-$NEW_VERSION
81-
# Push the branch immediately without committing anything.
82-
git push --set-upstream origin release-$NEW_VERSION
83-
# Output the branch name so we can use it in later jobs.
84-
echo "branch_name=release-$NEW_VERSION" >> "$GITHUB_OUTPUT"
85-
# Update our dependencies.
82+
INTERIM_BRANCH_NAME=${NEW_VERSION}-interim
83+
# Create and check out the interim branch.
84+
git checkout -b $INTERIM_BRANCH_NAME
85+
# Immediately push the interim branch with no changes, so GraphQL can push to it later.
86+
git push --set-upstream origin $INTERIM_BRANCH_NAME
87+
# Update dependencies.
8688
- run: |
8789
yarn upgrade
8890
node tools/UpdateRetireJsVulns.js
8991
# Use the GraphQL API to create a signed commit with the various changes.
90-
- run: |
92+
- name: Commit to interim branch
93+
run: |
9194
# GraphQL needs to know what branch to push to.
9295
BRANCH=$(git rev-parse --abbrev-ref HEAD)
9396
# GraphQL needs a message for the commit.
@@ -130,6 +133,19 @@ jobs:
130133
}
131134
}
132135
}'
136+
# Now that we've done our bookkeeping commits on the interim branch, use it as the base for the real release branch.
137+
- name: Create release branch
138+
id: create-branch
139+
run: |
140+
# The commit happened on the remote end, not ours, so we need to clean the directory and pull.
141+
git checkout -- .
142+
git pull
143+
# Now we can create the actual release branch.
144+
NEW_VERSION=$(jq -r ".version" package.json)
145+
git checkout -b release-$NEW_VERSION
146+
git push --set-upstream origin release-$NEW_VERSION
147+
# Output the branch name so we can use it in later jobs.
148+
echo "branch_name=release-$NEW_VERSION" >> "$GITHUB_OUTPUT"
133149
# Run all the various tests against the newly created branch.
134150
test-release-branch:
135151
needs: create-release-branch

.github/workflows/production-heartbeat.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ jobs:
2626
- uses: actions/setup-node@v4
2727
with:
2828
node-version: ${{ matrix.node }}
29+
- uses: actions/setup-java@v4
30+
with:
31+
distribution: 'temurin'
32+
java-version: '11'
2933
- run: mkdir smoke-test-results
3034

3135
# === Set our environment variables, either using default values or the repo's secrets ===

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@salesforce/sfdx-scanner",
33
"description": "Static code scanner that applies quality and security rules to Apex code, and provides feedback.",
4-
"version": "4.3.0",
4+
"version": "4.3.2",
55
"author": "Salesforce Code Analyzer Team",
66
"bugs": "https://github.com/forcedotcom/sfdx-scanner/issues",
77
"dependencies": {

retire-js/RetireJsVulns.json

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,59 @@
15311531
"https://tiny.cloud/docs/tinymce/6/6.7.3-release-notes/"
15321532
]
15331533
},
1534+
{
1535+
"atOrAbove": "0",
1536+
"below": "5.11.0",
1537+
"cwe": [
1538+
"CWE-79"
1539+
],
1540+
"severity": "medium",
1541+
"identifiers": {
1542+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noneditable_regexp option",
1543+
"CVE": [
1544+
"CVE-2024-38356"
1545+
],
1546+
"githubID": "GHSA-9hcv-j9pv-qmph"
1547+
},
1548+
"info": [
1549+
"https://github.com/advisories/GHSA-9hcv-j9pv-qmph",
1550+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-9hcv-j9pv-qmph",
1551+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38356",
1552+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1553+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1554+
"https://github.com/tinymce/tinymce",
1555+
"https://owasp.org/www-community/attacks/xss",
1556+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1557+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview",
1558+
"https://www.tiny.cloud/docs/tinymce/latest/7.2-release-notes/#overview"
1559+
]
1560+
},
1561+
{
1562+
"atOrAbove": "0",
1563+
"below": "5.11.0",
1564+
"cwe": [
1565+
"CWE-79"
1566+
],
1567+
"severity": "medium",
1568+
"identifiers": {
1569+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noscript elements",
1570+
"CVE": [
1571+
"CVE-2024-38357"
1572+
],
1573+
"githubID": "GHSA-w9jx-4g6g-rp7x"
1574+
},
1575+
"info": [
1576+
"https://github.com/advisories/GHSA-w9jx-4g6g-rp7x",
1577+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-w9jx-4g6g-rp7x",
1578+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38357",
1579+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1580+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1581+
"https://github.com/tinymce/tinymce",
1582+
"https://owasp.org/www-community/attacks/xss",
1583+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1584+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview"
1585+
]
1586+
},
15341587
{
15351588
"atOrAbove": "6.0.0",
15361589
"below": "6.3.1",
@@ -1638,6 +1691,59 @@
16381691
"https://www.tiny.cloud/docs/tinymce/7/7.0-release-notes/#sandbox_iframes-editor-option-is-now-defaulted-to-true"
16391692
]
16401693
},
1694+
{
1695+
"atOrAbove": "6.0.0",
1696+
"below": "6.8.4",
1697+
"cwe": [
1698+
"CWE-79"
1699+
],
1700+
"severity": "medium",
1701+
"identifiers": {
1702+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noneditable_regexp option",
1703+
"CVE": [
1704+
"CVE-2024-38356"
1705+
],
1706+
"githubID": "GHSA-9hcv-j9pv-qmph"
1707+
},
1708+
"info": [
1709+
"https://github.com/advisories/GHSA-9hcv-j9pv-qmph",
1710+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-9hcv-j9pv-qmph",
1711+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38356",
1712+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1713+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1714+
"https://github.com/tinymce/tinymce",
1715+
"https://owasp.org/www-community/attacks/xss",
1716+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1717+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview",
1718+
"https://www.tiny.cloud/docs/tinymce/latest/7.2-release-notes/#overview"
1719+
]
1720+
},
1721+
{
1722+
"atOrAbove": "6.0.0",
1723+
"below": "6.8.4",
1724+
"cwe": [
1725+
"CWE-79"
1726+
],
1727+
"severity": "medium",
1728+
"identifiers": {
1729+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noscript elements",
1730+
"CVE": [
1731+
"CVE-2024-38357"
1732+
],
1733+
"githubID": "GHSA-w9jx-4g6g-rp7x"
1734+
},
1735+
"info": [
1736+
"https://github.com/advisories/GHSA-w9jx-4g6g-rp7x",
1737+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-w9jx-4g6g-rp7x",
1738+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38357",
1739+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1740+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1741+
"https://github.com/tinymce/tinymce",
1742+
"https://owasp.org/www-community/attacks/xss",
1743+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1744+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview"
1745+
]
1746+
},
16411747
{
16421748
"atOrAbove": "0",
16431749
"below": "7.0.0",
@@ -1661,6 +1767,59 @@
16611767
"https://www.tiny.cloud/docs/tinymce/6/6.8.1-release-notes/#new-convert_unsafe_embeds-option-that-controls-whether-object-and-embed-elements-will-be-converted-to-more-restrictive-alternatives-namely-img-for-image-mime-types-video-for-video-mime-types-audio-audio-mime-types-or-iframe-for-other-or-unspecified-mime-types",
16621768
"https://www.tiny.cloud/docs/tinymce/7/7.0-release-notes/#convert_unsafe_embeds-editor-option-is-now-defaulted-to-true"
16631769
]
1770+
},
1771+
{
1772+
"atOrAbove": "7.0.0",
1773+
"below": "7.2.0",
1774+
"cwe": [
1775+
"CWE-79"
1776+
],
1777+
"severity": "medium",
1778+
"identifiers": {
1779+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noneditable_regexp option",
1780+
"CVE": [
1781+
"CVE-2024-38356"
1782+
],
1783+
"githubID": "GHSA-9hcv-j9pv-qmph"
1784+
},
1785+
"info": [
1786+
"https://github.com/advisories/GHSA-9hcv-j9pv-qmph",
1787+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-9hcv-j9pv-qmph",
1788+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38356",
1789+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1790+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1791+
"https://github.com/tinymce/tinymce",
1792+
"https://owasp.org/www-community/attacks/xss",
1793+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1794+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview",
1795+
"https://www.tiny.cloud/docs/tinymce/latest/7.2-release-notes/#overview"
1796+
]
1797+
},
1798+
{
1799+
"atOrAbove": "7.0.0",
1800+
"below": "7.2.0",
1801+
"cwe": [
1802+
"CWE-79"
1803+
],
1804+
"severity": "medium",
1805+
"identifiers": {
1806+
"summary": "TinyMCE Cross-Site Scripting (XSS) vulnerability using noscript elements",
1807+
"CVE": [
1808+
"CVE-2024-38357"
1809+
],
1810+
"githubID": "GHSA-w9jx-4g6g-rp7x"
1811+
},
1812+
"info": [
1813+
"https://github.com/advisories/GHSA-w9jx-4g6g-rp7x",
1814+
"https://github.com/tinymce/tinymce/security/advisories/GHSA-w9jx-4g6g-rp7x",
1815+
"https://nvd.nist.gov/vuln/detail/CVE-2024-38357",
1816+
"https://github.com/tinymce/tinymce/commit/5acb741665a98e83d62b91713c800abbff43b00d",
1817+
"https://github.com/tinymce/tinymce/commit/a9fb858509f86dacfa8b01cfd34653b408983ac0",
1818+
"https://github.com/tinymce/tinymce",
1819+
"https://owasp.org/www-community/attacks/xss",
1820+
"https://www.tiny.cloud/docs/tinymce/6/6.8.4-release-notes/#overview",
1821+
"https://www.tiny.cloud/docs/tinymce/7/7.2-release-notes/#overview"
1822+
]
16641823
}
16651824
],
16661825
"extractors": {

src/lib/DefaultRuleManager.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class DefaultRuleManager implements RuleManager {
7474
return this.catalog.getRulesMatchingFilters(filters);
7575
}
7676

77-
async runRulesMatchingCriteria(filters: RuleFilter[], targets: string[], runOptions: RunOptions, engineOptions: EngineOptions): Promise<Results> {
77+
async runRulesMatchingCriteria(filters: RuleFilter[], targets: string[], runOptions: RunOptions, engineOptions: EngineOptions, projectDir?: string): Promise<Results> {
7878
// Declare a variable that we can later use to store the engine results, as well as something to help us track
7979
// which engines actually ran.
8080
let ruleResults: RuleResult[] = [];
@@ -100,7 +100,7 @@ export class DefaultRuleManager implements RuleManager {
100100
// them all in. Note that some engines (pmd) need groups while others (eslint) need the rules.
101101
const engineGroups = ruleGroups.filter(g => g.engine === e.getName());
102102
const engineRules = rules.filter(r => r.engine === e.getName());
103-
const engineTargets = await this.unpackTargets(e, targets, matchedTargets);
103+
const engineTargets = await this.unpackTargets(e, targets, matchedTargets, projectDir);
104104
this.logger.trace(`For ${e.getName()}, found ${engineGroups.length} groups, ${engineRules.length} rules, ${engineTargets.length} targets`);
105105

106106
if (e.shouldEngineRun(engineGroups, engineRules, engineTargets, engineOptions)) {
@@ -247,7 +247,7 @@ export class DefaultRuleManager implements RuleManager {
247247
*
248248
* Any items from the 'targets' array that result in a match are added to the 'matchedTargets' Set.
249249
*/
250-
protected async unpackTargets(engine: RuleEngine, targets: string[], matchedTargets: Set<string>): Promise<RuleTarget[]> {
250+
protected async unpackTargets(engine: RuleEngine, targets: string[], matchedTargets: Set<string>, projectDir?: string): Promise<RuleTarget[]> {
251251
const ruleTargets: RuleTarget[] = [];
252252
// Ask engines for their desired target patterns.
253253
const engineTargets = await engine.getTargetPatterns();
@@ -283,7 +283,7 @@ export class DefaultRuleManager implements RuleManager {
283283

284284
// We want to use a path matcher that can filter based on the engine's target patterns and any negative globs
285285
// provided to us.
286-
const pm = new PathMatcher([...engineTargets, ...negativePatterns]);
286+
const pm = new PathMatcher([...engineTargets, ...negativePatterns], projectDir);
287287
for (const target of positivePatterns) {
288288
// Used to detect if the target resulted in a match
289289
const ruleTargetsInitialLength: number = ruleTargets.length;

src/lib/InputProcessor.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface InputProcessor {
2121

2222
resolveTargetPaths(inputs: Inputs): string[];
2323

24-
resolveProjectDirPaths(inputs: Inputs): string[];
24+
resolveProjectDirPaths(inputs: Inputs, displayResolvedProjectDir?: boolean): string[];
2525

2626
createRunOptions(inputs: Inputs, isDfa: boolean): RunOptions;
2727

@@ -45,7 +45,7 @@ export class InputProcessorImpl implements InputProcessor {
4545
return (inputs.path as string[]).map(p => path.resolve(untildify(p)));
4646
}
4747

48-
public resolveProjectDirPaths(inputs: Inputs): string[] {
48+
public resolveProjectDirPaths(inputs: Inputs, displayResolvedProjectDir: boolean = true): string[] {
4949
// If projectdir is provided, then return it since at this point it has already been validated to exist
5050
if (inputs.projectdir && (inputs.projectdir as string[]).length > 0) {
5151
return (inputs.projectdir as string[]).map(p => path.resolve(normalize(untildify(p))))
@@ -58,7 +58,9 @@ export class InputProcessorImpl implements InputProcessor {
5858
const commonParentFolder = getFirstCommonParentFolder(this.getAllTargetFiles(inputs));
5959
let projectFolder: string = findFolderThatContainsSfdxProjectFile(commonParentFolder);
6060
projectFolder = projectFolder.length > 0 ? projectFolder : commonParentFolder
61-
this.displayInfoOnlyOnce('info.resolvedProjectDir', [projectFolder])
61+
if (displayResolvedProjectDir) {
62+
this.displayInfoOnlyOnce('info.resolvedProjectDir', [projectFolder])
63+
}
6264
return [projectFolder];
6365
}
6466

src/lib/RuleManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,5 @@ export interface RuleManager {
2929
/**
3030
* @param engineOptions - see RuleEngine#run
3131
*/
32-
runRulesMatchingCriteria(filters: RuleFilter[], target: string[], runOptions: RunOptions, engineOptions: EngineOptions): Promise<Results>;
32+
runRulesMatchingCriteria(filters: RuleFilter[], target: string[], runOptions: RunOptions, engineOptions: EngineOptions, projectDir?: string): Promise<Results>;
3333
}

src/lib/actions/AbstractRunAction.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,13 @@ export abstract class AbstractRunAction implements Action {
9090
const resultsProcessor: ResultsProcessor = this.resultsProcessorFactory.createResultsProcessor(
9191
this.display, outputOptions, jsonReturnValueHolder);
9292

93+
const primaryProjectDir: string = this.inputProcessor.resolveProjectDirPaths(inputs, false)[0];
94+
9395
// TODO: Inject RuleManager as a dependency to improve testability by removing coupling to runtime implementation
9496
const ruleManager: RuleManager = await Controller.createRuleManager();
9597

9698
try {
97-
const results: Results = await ruleManager.runRulesMatchingCriteria(filters, targetPaths, runOptions, engineOptions);
99+
const results: Results = await ruleManager.runRulesMatchingCriteria(filters, targetPaths, runOptions, engineOptions, primaryProjectDir);
98100
this.logger.trace(`Processing output with format ${outputOptions.format}`);
99101
await resultsProcessor.processResults(results);
100102
return jsonReturnValueHolder.get();

0 commit comments

Comments
 (0)