Skip to content

Commit 7b2ab38

Browse files
committed
Merge remote-tracking branch 'upstream/alpha' into alpha
2 parents 7bc5c36 + 4c9e956 commit 7b2ab38

File tree

8 files changed

+325
-29
lines changed

8 files changed

+325
-29
lines changed

CONTRIBUTING.md

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
- [Releasing](#releasing)
2828
- [General Considerations](#general-considerations)
2929
- [Major Release / Long-Term-Support](#major-release--long-term-support)
30+
- [Preparing Release](#preparing-release)
31+
- [Publishing Release (forward-merge):](#publishing-release-forward-merge)
32+
- [Publishing Hotfix (back-merge):](#publishing-hotfix-back-merge)
33+
- [Publishing Major Release (Yearly Release)](#publishing-major-release-yearly-release)
3034
- [Versioning](#versioning)
3135
- [Code of Conduct](#code-of-conduct)
3236

@@ -385,20 +389,66 @@ If the commit reverts a previous commit, use the prefix `revert:`, followed by t
385389
386390
### General Considerations
387391
388-
- The `package-lock.json` file has to be deleted and recreated by npm from scratch in regular intervals using the `npm i` command. It is not enough to only update the file via automated security pull requests (e.g. dependabot, snyk), that can create inconsistencies between sub-devependencies of a dependency and increase the chances of vulnerabilities. The file should be recreated once every release cycle which is usually monthly.
392+
- The `package-lock.json` file has to be deleted and recreated by npm from scratch in regular intervals using the `npm i` command. It is not enough to only update the file via automated security pull requests (e.g. dependabot, snyk), that can create inconsistencies between sub-dependencies of a dependency and increase the chances of vulnerabilities. The file should be recreated once every release cycle which is usually monthly.
389393
390394
### Major Release / Long-Term-Support
391395
392396
Long-Term-Support (LTS) is provided for the previous Parse Server major version. For example, Parse Server 4.x will receive security updates until Parse Server 5.x is superseded by Parse Server 6.x and becomes the new LTS version. While the current major version is published on branch `release`, a LTS version is published on branch `release-#.x.x`, for example `release-4.x.x` for the Parse Server 4.x LTS branch.
393397
394-
#### Preparing Release
398+
### Preparing Release
395399
396400
The following changes are done in the `alpha` branch, before publishing the last `beta` version that will eventually become the major release. This way the changes trickle naturally through all branches and code consistency is ensured among branches.
397401
398402
- Make sure all [deprecations](https://github.com/parse-community/parse-server/blob/alpha/DEPRECATIONS.md) are reflected in code, old code is removed and the deprecations table is updated.
399403
- Add the future LTS branch `release-#.x.x` to the branch list in [release.config.js](https://github.com/parse-community/parse-server/blob/alpha/release.config.js) so that the branch will later be recognized for release automation.
400404
401-
#### Publishing Release
405+
406+
### Publishing Release (forward-merge):
407+
408+
1. Create new temporary branch `build` on branch `beta`.
409+
2. Create PR to merge `build` into `release`:
410+
- PR title: `build: release`
411+
- PR description: (leave empty)
412+
3. Resolve any conflicts:
413+
- For conflicts regarding the package version in `package.json` and `package-lock.json` it doesn't matter which version is chosen, as the version will be set by auto-release in a commit after merging. However, for both files the same version should be chosen when resolving the conflict.
414+
4. Merge PR with a "merge commit", do not "squash and merge":
415+
- Commit message: (use PR title)
416+
- Description: (leave empty)
417+
5. Wait for GitHub Action `release-automated` to finish:
418+
- If GitHub Action fails, investigate why; manual correction may be needed.
419+
6. Pull all remote branches into local branches.
420+
7. Delete temporary branch `build`.
421+
8. Create new temporary branch `build` on branch `alpha`.
422+
9. Create PR to merge `build` into `beta`:
423+
- PR title: `build: release`
424+
- PR description: (leave empty)
425+
8. Repeat steps 3-7 for PR from step 9.
426+
427+
### Publishing Hotfix (back-merge):
428+
429+
1. Create PR to merge hotfix PR into `release`:
430+
- Merge PR following the same rules as any PR would be merged into the working branch `alpha`.
431+
2. Wait for GitHub Action `release-automated` to finish:
432+
- GitHub Action will fail with error `! [rejected] HEAD -> beta (non-fast-forward)`; this is expected as auto-release currently cannot fully handle back-merging; docker will not publish the new release, so this has to be done manually using the GitHub workflow `release-manual-docker` and entering the version tag that has been created by auto-release.
433+
3. Pull all remote branches into local branches.
434+
4. Create a new temporary branch `backmerge` on branch `release`.
435+
5. Create PR to merge `backmerge` into `beta`:
436+
- PR title: `<pr-name> [skip release]` where `<pr-name>` is the PR title of step 1.
437+
- PR description: (leave empty)
438+
6. Resolve any conflicts:
439+
- During back-merging, usually all changes are preserved; current changes come from the hotfix in the `release` branch, the incoming changes come from the `beta` branch usually being ahead of the `release` branch. This makes back-merging so complex and bug-prone and is the main reason why it should be avoided if possible.
440+
7. Merge PR with "squash and merge", do not do a "merge commit":
441+
- Commit message: (use PR title)
442+
- Description: (leave empty)
443+
444+
ℹ️ Merging this PR will not trigger a release; the back-merge will not appear in changelogs of the `beta`, `alpha` branches; the back-merged fix will be an undocumented change of these branches' next releases; if necessary, the change needs to be added manually to the pre-release changelogs *after* the next pre-releases.
445+
8. Delete temporary branch `backmerge`.
446+
10. Create a new temporary branch `backmerge` on branch `beta`.
447+
11. Repeat steps 4-8 to merge PR into `alpha`.
448+
449+
⚠️ Long-term-support branches are excluded from the processes above and handled individually as they do not have pre-releases branches and are not considered part of the current codebase anymore. It may be necessary to significantly adapt a PR for a LTS branch due to the differences in codebase and CI tests. This adaption should be done in advance before merging any related PR, especially for security fixes, as to not publish a vulnerability while it may still take significant time to adapt the fix for the older codebase of a LTS branch.
450+
451+
### Publishing Major Release (Yearly Release)
402452
403453
1. Create LTS branch `release-#.x.x` off the latest version tag on `release` branch.
404454
2. Create temporary branch `build-release` off branch `beta` and create a pull request with `release` as the base branch.

changelogs/CHANGELOG_release.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## [5.2.3](https://github.com/parse-community/parse-server/compare/5.2.2...5.2.3) (2022-06-17)
2+
3+
4+
### Bug Fixes
5+
6+
* invalid file request not properly handled; this fixes a security vulnerability in which an invalid file request can crash the server ([GHSA-xw6g-jjvf-wwf9](https://github.com/parse-community/parse-server/security/advisories/GHSA-xw6g-jjvf-wwf9)) ([#8060](https://github.com/parse-community/parse-server/issues/8060)) ([5be375d](https://github.com/parse-community/parse-server/commit/5be375dec2fa35425c1003ae81c55995ac72af92))
7+
8+
## [5.2.2](https://github.com/parse-community/parse-server/compare/5.2.1...5.2.2) (2022-06-17)
9+
10+
11+
### Bug Fixes
12+
13+
* certificate in Apple Game Center auth adapter not validated; this fixes a security vulnerability in which authentication could be bypassed using a fake certificate; if you are using the Apple Gamer Center auth adapter it is your responsibility to keep its root certificate up-to-date and we advice you read the security advisory ([GHSA-rh9j-f5f8-rvgc](https://github.com/parse-community/parse-server/security/advisories/GHSA-rh9j-f5f8-rvgc)) ([ba2b0a9](https://github.com/parse-community/parse-server/commit/ba2b0a9cb9a568817a114b132a4c2e0911d76df1))
14+
115
## [5.2.1](https://github.com/parse-community/parse-server/compare/5.2.0...5.2.1) (2022-05-01)
216

317

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "parse-server",
3-
"version": "5.3.0-beta.1",
3+
"version": "5.2.3",
44
"description": "An express module providing a Parse-compatible API server",
55
"main": "lib/index.js",
66
"repository": {

spec/AuthenticationAdapters.spec.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,7 +1682,41 @@ describe('Apple Game Center Auth adapter', () => {
16821682
const gcenter = require('../lib/Adapters/Auth/gcenter');
16831683
const fs = require('fs');
16841684
const testCert = fs.readFileSync(__dirname + '/support/cert/game_center.pem');
1685+
1686+
it('can load adapter', async () => {
1687+
const options = {
1688+
gcenter: {
1689+
rootCertificateUrl:
1690+
'https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crt.pem',
1691+
},
1692+
};
1693+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1694+
'gcenter',
1695+
options
1696+
);
1697+
await adapter.validateAppId(
1698+
appIds,
1699+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1700+
providerOptions
1701+
);
1702+
});
1703+
16851704
it('validateAuthData should validate', async () => {
1705+
const options = {
1706+
gcenter: {
1707+
rootCertificateUrl:
1708+
'https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crt.pem',
1709+
},
1710+
};
1711+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1712+
'gcenter',
1713+
options
1714+
);
1715+
await adapter.validateAppId(
1716+
appIds,
1717+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1718+
providerOptions
1719+
);
16861720
// real token is used
16871721
const authData = {
16881722
id: 'G:1965586982',
@@ -1698,6 +1732,15 @@ describe('Apple Game Center Auth adapter', () => {
16981732
});
16991733

17001734
it('validateAuthData invalid signature id', async () => {
1735+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1736+
'gcenter',
1737+
{}
1738+
);
1739+
await adapter.validateAppId(
1740+
appIds,
1741+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1742+
providerOptions
1743+
);
17011744
const authData = {
17021745
id: 'G:1965586982',
17031746
publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-6.cer',
@@ -1712,6 +1755,21 @@ describe('Apple Game Center Auth adapter', () => {
17121755
});
17131756

17141757
it('validateAuthData invalid public key http url', async () => {
1758+
const options = {
1759+
gcenter: {
1760+
rootCertificateUrl:
1761+
'https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crt.pem',
1762+
},
1763+
};
1764+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1765+
'gcenter',
1766+
options
1767+
);
1768+
await adapter.validateAppId(
1769+
appIds,
1770+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1771+
providerOptions
1772+
);
17151773
const publicKeyUrls = [
17161774
'example.com',
17171775
'http://static.gc.apple.com/public-key/gc-prod-4.cer',
@@ -1739,6 +1797,78 @@ describe('Apple Game Center Auth adapter', () => {
17391797
)
17401798
);
17411799
});
1800+
1801+
it('should not validate Symantec Cert', async () => {
1802+
const options = {
1803+
gcenter: {
1804+
rootCertificateUrl:
1805+
'https://cacerts.digicert.com/DigiCertTrustedG4CodeSigningRSA4096SHA3842021CA1.crt.pem',
1806+
},
1807+
};
1808+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1809+
'gcenter',
1810+
options
1811+
);
1812+
await adapter.validateAppId(
1813+
appIds,
1814+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1815+
providerOptions
1816+
);
1817+
expect(() =>
1818+
gcenter.verifyPublicKeyIssuer(
1819+
testCert,
1820+
'https://static.gc.apple.com/public-key/gc-prod-4.cer'
1821+
)
1822+
);
1823+
});
1824+
1825+
it('adapter should load default cert', async () => {
1826+
const options = {
1827+
gcenter: {},
1828+
};
1829+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1830+
'gcenter',
1831+
options
1832+
);
1833+
await adapter.validateAppId(
1834+
appIds,
1835+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1836+
providerOptions
1837+
);
1838+
const previous = new Date();
1839+
await adapter.validateAppId(
1840+
appIds,
1841+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1842+
providerOptions
1843+
);
1844+
1845+
const duration = new Date().getTime() - previous.getTime();
1846+
expect(duration).toEqual(0);
1847+
});
1848+
1849+
it('adapter should throw', async () => {
1850+
const options = {
1851+
gcenter: {
1852+
rootCertificateUrl: 'https://example.com',
1853+
},
1854+
};
1855+
const { adapter, appIds, providerOptions } = authenticationLoader.loadAuthAdapter(
1856+
'gcenter',
1857+
options
1858+
);
1859+
await expectAsync(
1860+
adapter.validateAppId(
1861+
appIds,
1862+
{ publicKeyUrl: 'https://static.gc.apple.com/public-key/gc-prod-4.cer' },
1863+
providerOptions
1864+
)
1865+
).toBeRejectedWith(
1866+
new Parse.Error(
1867+
Parse.Error.OBJECT_NOT_FOUND,
1868+
'Apple Game Center auth adapter parameter `rootCertificateURL` is invalid.'
1869+
)
1870+
);
1871+
});
17421872
});
17431873

17441874
describe('phant auth adapter', () => {

spec/ParseFile.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,44 @@ describe('Parse.File testing', () => {
654654
});
655655
});
656656

657+
describe('getting files', () => {
658+
it('does not crash on file request with invalid app ID', async () => {
659+
const res1 = await request({
660+
url: 'http://localhost:8378/1/files/invalid-id/invalid-file.txt',
661+
}).catch(e => e);
662+
expect(res1.status).toBe(403);
663+
expect(res1.data).toEqual({ code: 119, error: 'Invalid application ID.' });
664+
// Ensure server did not crash
665+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
666+
expect(res2.status).toEqual(200);
667+
expect(res2.data).toEqual({ status: 'ok' });
668+
});
669+
670+
it('does not crash on file request with invalid path', async () => {
671+
const res1 = await request({
672+
url: 'http://localhost:8378/1/files/invalid-id//invalid-path/%20/invalid-file.txt',
673+
}).catch(e => e);
674+
expect(res1.status).toBe(403);
675+
expect(res1.data).toEqual({ error: 'unauthorized' });
676+
// Ensure server did not crash
677+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
678+
expect(res2.status).toEqual(200);
679+
expect(res2.data).toEqual({ status: 'ok' });
680+
});
681+
682+
it('does not crash on file metadata request with invalid app ID', async () => {
683+
const res1 = await request({
684+
url: `http://localhost:8378/1/files/invalid-id/metadata/invalid-file.txt`,
685+
});
686+
expect(res1.status).toBe(200);
687+
expect(res1.data).toEqual({});
688+
// Ensure server did not crash
689+
const res2 = await request({ url: 'http://localhost:8378/1/health' });
690+
expect(res2.status).toEqual(200);
691+
expect(res2.data).toEqual({ status: 'ok' });
692+
});
693+
});
694+
657695
xdescribe('Gridstore Range tests', () => {
658696
it('supports range requests', done => {
659697
const headers = {

0 commit comments

Comments
 (0)