1+ import { createPublicKey } from 'node:crypto' ;
2+ import fs from 'node:fs' ;
3+ import path from 'node:path' ;
14import NativeScriptManager , {
25 type NormalizedScriptLocator ,
36} from '../NativeScriptManager.js' ;
@@ -31,6 +34,21 @@ webpackRequire.repack = {
3134
3235globalThis . __webpack_require__ = webpackRequire ;
3336
37+ const RSA_PUBLIC_KEY = fs
38+ . readFileSync (
39+ path . join (
40+ __dirname ,
41+ '../../../plugins/__tests__/__fixtures__/testRS256.pem.pub'
42+ ) ,
43+ 'utf8'
44+ )
45+ . trim ( ) ;
46+
47+ const PKCS1_RSA_PUBLIC_KEY = createPublicKey ( RSA_PUBLIC_KEY )
48+ . export ( { format : 'pem' , type : 'pkcs1' } )
49+ . toString ( )
50+ . trim ( ) ;
51+
3452class FakeCache {
3553 data : Record < string , string > = { } ;
3654
@@ -362,8 +380,7 @@ describe('ScriptManagerAPI', () => {
362380 return {
363381 url : Script . getRemoteURL ( `http://domain.ext/${ scriptId } ` ) ,
364382 verifyScriptSignature : 'strict' ,
365- publicKey :
366- '-----BEGIN PUBLIC KEY-----\\ncustom\\n-----END PUBLIC KEY-----' ,
383+ publicKey : RSA_PUBLIC_KEY ,
367384 } ;
368385 } ) ;
369386
@@ -379,8 +396,7 @@ describe('ScriptManagerAPI', () => {
379396 method : 'GET' ,
380397 timeout : Script . DEFAULT_TIMEOUT ,
381398 verifyScriptSignature : 'strict' ,
382- publicKey :
383- '-----BEGIN PUBLIC KEY-----\\ncustom\\n-----END PUBLIC KEY-----' ,
399+ publicKey : RSA_PUBLIC_KEY ,
384400 uniqueId : 'main_src_App_js' ,
385401 } ) ;
386402 } ) ;
@@ -401,13 +417,65 @@ describe('ScriptManagerAPI', () => {
401417 ) ;
402418 } ) ;
403419
420+ it ( 'should reject a truncated PEM public key' , async ( ) => {
421+ ScriptManager . shared . addResolver ( async ( scriptId ) => {
422+ return {
423+ url : Script . getRemoteURL ( `http://domain.ext/${ scriptId } ` ) ,
424+ verifyScriptSignature : 'strict' ,
425+ publicKey : RSA_PUBLIC_KEY . replace ( '-----END PUBLIC KEY-----' , '' ) ,
426+ } ;
427+ } ) ;
428+
429+ await expect (
430+ ScriptManager . shared . resolveScript ( 'src_App_js' , 'main' )
431+ ) . rejects . toThrow (
432+ 'Property publicKey must be a PEM-formatted public key enclosed in BEGIN/END PUBLIC KEY markers.'
433+ ) ;
434+ } ) ;
435+
436+ it ( 'should reject a PKCS#1 public key with RSA PUBLIC KEY markers' , async ( ) => {
437+ ScriptManager . shared . addResolver ( async ( scriptId ) => {
438+ return {
439+ url : Script . getRemoteURL ( `http://domain.ext/${ scriptId } ` ) ,
440+ verifyScriptSignature : 'strict' ,
441+ publicKey : PKCS1_RSA_PUBLIC_KEY ,
442+ } ;
443+ } ) ;
444+
445+ await expect (
446+ ScriptManager . shared . resolveScript ( 'src_App_js' , 'main' )
447+ ) . rejects . toThrow (
448+ 'Property publicKey must be a PEM-formatted public key enclosed in BEGIN/END PUBLIC KEY markers.'
449+ ) ;
450+ } ) ;
451+
452+ it ( 'should reject a large malformed public key without excessive backtracking' , async ( ) => {
453+ ScriptManager . shared . addResolver ( async ( scriptId ) => {
454+ return {
455+ url : Script . getRemoteURL ( `http://domain.ext/${ scriptId } ` ) ,
456+ verifyScriptSignature : 'strict' ,
457+ publicKey : `-----BEGIN PUBLIC KEY-----${ ' ' . repeat ( 4096 ) } x` ,
458+ } ;
459+ } ) ;
460+
461+ await expect (
462+ ScriptManager . shared . resolveScript ( 'src_App_js' , 'main' )
463+ ) . rejects . toThrow (
464+ 'Property publicKey must be a PEM-formatted public key enclosed in BEGIN/END PUBLIC KEY markers.'
465+ ) ;
466+ } ) ;
467+
404468 it ( 'should allow public key override with surrounding whitespace' , async ( ) => {
469+ const publicKeyWithWindowsLineEndings = RSA_PUBLIC_KEY . replaceAll (
470+ '\n' ,
471+ '\r\n'
472+ ) ;
473+
405474 ScriptManager . shared . addResolver ( async ( scriptId ) => {
406475 return {
407476 url : Script . getRemoteURL ( `http://domain.ext/${ scriptId } ` ) ,
408477 verifyScriptSignature : 'strict' ,
409- publicKey :
410- '\n -----BEGIN PUBLIC KEY-----\\ncustom\\n-----END PUBLIC KEY----- \n' ,
478+ publicKey : `\r\n ${ publicKeyWithWindowsLineEndings } \r\n` ,
411479 } ;
412480 } ) ;
413481
@@ -416,9 +484,7 @@ describe('ScriptManagerAPI', () => {
416484 'main'
417485 ) ;
418486
419- expect ( script . locator . publicKey ) . toBe (
420- '-----BEGIN PUBLIC KEY-----\\ncustom\\n-----END PUBLIC KEY-----'
421- ) ;
487+ expect ( script . locator . publicKey ) . toBe ( publicKeyWithWindowsLineEndings ) ;
422488 } ) ;
423489
424490 it ( 'should resolve with body' , async ( ) => {
0 commit comments