diff --git a/Libraries/Image/AssetSourceResolver.js b/Libraries/Image/AssetSourceResolver.js index 624c6225c2008f..bc671090b25b5f 100644 --- a/Libraries/Image/AssetSourceResolver.js +++ b/Libraries/Image/AssetSourceResolver.js @@ -114,7 +114,12 @@ class AssetSourceResolver { */ scaledAssetURLNearBundle(): ResolvedAssetSource { const path = this.jsbundleUrl || 'file://'; - return this.fromSource(path + getScaledAssetPath(this.asset)); + return this.fromSource( + // Assets can have relative paths outside of the project root. + // When bundling them we replace `../` with `_` to make sure they + // don't end up outside of the expected assets directory. + path + getScaledAssetPath(this.asset).replace(/\.\.\//g, '_'), + ); } /** diff --git a/Libraries/Image/__tests__/resolveAssetSource-test.js b/Libraries/Image/__tests__/resolveAssetSource-test.js index 287e0657beb5ac..ee752bd7322c4a 100644 --- a/Libraries/Image/__tests__/resolveAssetSource-test.js +++ b/Libraries/Image/__tests__/resolveAssetSource-test.js @@ -143,6 +143,29 @@ describe('resolveAssetSource', () => { }, ); }); + + it('resolves an image with a relative path outside of root', () => { + expectResolvesAsset( + { + __packager_asset: true, + fileSystemLocation: '/module/a', + httpServerLocation: '/assets/../../module/a', + width: 100, + height: 200, + scales: [1], + hash: '5b6f00f', + name: 'logo', + type: 'png', + }, + { + __packager_asset: true, + width: 100, + height: 200, + uri: 'file:///Path/To/Sample.app/assets/__module/a/logo.png', + scale: 1, + }, + ); + }); }); describe('bundle was loaded from assets on Android', () => { @@ -175,6 +198,29 @@ describe('resolveAssetSource', () => { }, ); }); + + it('resolves an image with a relative path outside of root', () => { + expectResolvesAsset( + { + __packager_asset: true, + fileSystemLocation: '/module/a', + httpServerLocation: '/assets/../../module/a', + width: 100, + height: 200, + scales: [1], + hash: '5b6f00f', + name: 'logo', + type: 'png', + }, + { + __packager_asset: true, + width: 100, + height: 200, + uri: '__module_a_logo', + scale: 1, + }, + ); + }); }); describe('bundle was loaded from file on Android', () => {