@@ -1446,4 +1446,147 @@ describe('ReactFlight', () => {
14461446 ) ;
14471447 } ) ;
14481448 } ) ;
1449+
1450+ // @gate enableTaint
1451+ it ( 'errors when a tainted object is serialized' , async ( ) => {
1452+ function UserClient ( { user} ) {
1453+ return < span > { user . name } </ span > ;
1454+ }
1455+ const User = clientReference ( UserClient ) ;
1456+
1457+ const user = {
1458+ name : 'Seb' ,
1459+ age : 'rather not say' ,
1460+ } ;
1461+ ReactServer . unstable_taintShallowObject (
1462+ "Don't pass the raw user object to the client" ,
1463+ user ,
1464+ ) ;
1465+ const errors = [ ] ;
1466+ ReactNoopFlightServer . render ( < User user = { user } /> , {
1467+ onError ( x ) {
1468+ errors . push ( x . message ) ;
1469+ } ,
1470+ } ) ;
1471+
1472+ expect ( errors ) . toEqual ( [ "Don't pass the raw user object to the client" ] ) ;
1473+ } ) ;
1474+
1475+ // @gate enableTaint
1476+ it ( 'errors with a specific message when a tainted function is serialized' , async ( ) => {
1477+ function UserClient ( { user} ) {
1478+ return < span > { user . name } </ span > ;
1479+ }
1480+ const User = clientReference ( UserClient ) ;
1481+
1482+ function change ( ) { }
1483+ ReactServer . unstable_taintShallowObject (
1484+ 'A change handler cannot be passed to a client component' ,
1485+ change ,
1486+ ) ;
1487+ const errors = [ ] ;
1488+ ReactNoopFlightServer . render ( < User onChange = { change } /> , {
1489+ onError ( x ) {
1490+ errors . push ( x . message ) ;
1491+ } ,
1492+ } ) ;
1493+
1494+ expect ( errors ) . toEqual ( [
1495+ 'A change handler cannot be passed to a client component' ,
1496+ ] ) ;
1497+ } ) ;
1498+
1499+ // @gate enableTaint
1500+ it ( 'errors when a tainted string is serialized' , async ( ) => {
1501+ function UserClient ( { user} ) {
1502+ return < span > { user . name } </ span > ;
1503+ }
1504+ const User = clientReference ( UserClient ) ;
1505+
1506+ const process = {
1507+ env : {
1508+ SECRET : '3e971ecc1485fe78625598bf9b6f85db' ,
1509+ } ,
1510+ } ;
1511+ ReactServer . unstable_taintValue (
1512+ 'Cannot pass a secret token to the client' ,
1513+ process ,
1514+ process . env . SECRET ,
1515+ ) ;
1516+
1517+ const errors = [ ] ;
1518+ ReactNoopFlightServer . render ( < User token = { process . env . SECRET } /> , {
1519+ onError ( x ) {
1520+ errors . push ( x . message ) ;
1521+ } ,
1522+ } ) ;
1523+
1524+ expect ( errors ) . toEqual ( [ 'Cannot pass a secret token to the client' ] ) ;
1525+
1526+ // This just ensures the process object is kept alive for the life time of
1527+ // the test since we're simulating a global as an example.
1528+ expect ( process . env . SECRET ) . toBe ( '3e971ecc1485fe78625598bf9b6f85db' ) ;
1529+ } ) ;
1530+
1531+ it ( 'errors when a tainted bigint is serialized' , async ( ) => {
1532+ function UserClient ( { user} ) {
1533+ return < span > { user . name } </ span > ;
1534+ }
1535+ const User = clientReference ( UserClient ) ;
1536+
1537+ const currentUser = {
1538+ name : 'Seb' ,
1539+ token : BigInt ( '0x3e971ecc1485fe78625598bf9b6f85dc' ) ,
1540+ } ;
1541+ ReactServer . unstable_taintValue (
1542+ 'Cannot pass a secret token to the client' ,
1543+ currentUser ,
1544+ currentUser . token ,
1545+ ) ;
1546+
1547+ function App ( { user} ) {
1548+ return < User token = { user . token } /> ;
1549+ }
1550+
1551+ const errors = [ ] ;
1552+ ReactNoopFlightServer . render ( < App user = { currentUser } /> , {
1553+ onError ( x ) {
1554+ errors . push ( x . message ) ;
1555+ } ,
1556+ } ) ;
1557+
1558+ expect ( errors ) . toEqual ( [ 'Cannot pass a secret token to the client' ] ) ;
1559+ } ) ;
1560+
1561+ // @gate enableTaint && enableBinaryFlight
1562+ it ( 'errors when a tainted binary value is serialized' , async ( ) => {
1563+ function UserClient ( { user} ) {
1564+ return < span > { user . name } </ span > ;
1565+ }
1566+ const User = clientReference ( UserClient ) ;
1567+
1568+ const currentUser = {
1569+ name : 'Seb' ,
1570+ token : new Uint32Array ( [ 0x3e971ecc , 0x1485fe78 , 0x625598bf , 0x9b6f85dd ] ) ,
1571+ } ;
1572+ ReactServer . unstable_taintValue (
1573+ 'Cannot pass a secret token to the client' ,
1574+ currentUser ,
1575+ currentUser . token ,
1576+ ) ;
1577+
1578+ function App ( { user} ) {
1579+ const clone = user . token . slice ( ) ;
1580+ return < User token = { clone } /> ;
1581+ }
1582+
1583+ const errors = [ ] ;
1584+ ReactNoopFlightServer . render ( < App user = { currentUser } /> , {
1585+ onError ( x ) {
1586+ errors . push ( x . message ) ;
1587+ } ,
1588+ } ) ;
1589+
1590+ expect ( errors ) . toEqual ( [ 'Cannot pass a secret token to the client' ] ) ;
1591+ } ) ;
14491592} ) ;
0 commit comments