packages/plugin/index.js
function checkCodeDoesNotInterfere(astNode, exprKey, isExpression) {
      let expr = astNode[exprKey];
      const seen = new Set();

      const type = typeof expr;
      if (type !== 'string') {
        // expr may be true, not "true".
        // This occurs for inferred expressions like valueless attributes.
        expr = `${ expr }`;
        astNode[exprKey] = expr;
      }

      let warnedPug = false;
      let warnedModule = false;
      // Allows check to take into account the context in which a node appears.
      // Flattened pairs of [ancestor, keyInAncestorToDescendent].
      const jsAstPath = [];

      function check(jsAst) {
        if (jsAst && typeof jsAst === 'object' && jsAst.type === 'Identifier') {
          const { name } = jsAst;
          if (/^pug_/.test(name) || name === 'eval') {
            if (!warnedPug) {
              distrust(`Expression (${ expr }) may interfere with PUG internals ${ jsAst.name }`);
              warnedPug = true;
            }
          } else if (name === 'require' &&
                     // Allow trusted plugin code to require modules they need.
                     !(Object.hasOwnProperty.call(astNode, 'mayRequire') && astNode.mayRequire) &&
                     // Allow require.moduleKeys and require.resolve but not require(moduleId).
                     !(jsAstPath.length && jsAstPath[jsAstPath.length - 2].type === 'MemberExpression' &&
                       jsAstPath[jsAstPath.length - 1] === 'object')) {
            // Defang expression.
            astNode[exprKey] = 'null';
            // We trust trusted plugin code and PUG code to use the module's private key
            // but not template code.
            if (!warnedModule) {
              distrust(`Expression (${ expr }) may interfere with module internals ${ jsAst.name }`);
              warnedModule = true;
            }
          }
        }
        checkChildren(jsAst); // eslint-disable-line no-use-before-define
      }

      function checkChildren(jsAst) {
        if (!seen.has(jsAst)) {
          seen.add(jsAst);
          const jsAstPathLength = jsAstPath.length;
          jsAstPath[jsAstPathLength] = jsAst;
          for (const key in jsAst) {
            if (Object.hasOwnProperty.call(jsAst, key)) {
              jsAstPath[jsAstPathLength + 1] = key;
              check(jsAst[key]);
            }
          }
          jsAstPath.length = jsAstPathLength;
        }
      }

      let root = null;
      try {
        root = isExpression ? parseExpression(expr) : parse(expr);
      } catch (exc) {
        distrust(`Malformed expression (${ expr })`);
        return;
      }
      check(root);
    }
function checkCodeDoesNotInterfere(astNode, exprKey, isExpression) {
      let expr = astNode[exprKey];
      const seen = new Set();

      const type = typeof expr;
      if (type !== 'string') {
        // expr may be true, not "true".
        // This occurs for inferred expressions like valueless attributes.
        expr = `${ expr }`;
        astNode[exprKey] = expr;
      }

      let warnedPug = false;
      let warnedModule = false;
      // Allows check to take into account the context in which a node appears.
      // Flattened pairs of [ancestor, keyInAncestorToDescendent].
      const jsAstPath = [];

      function check(jsAst) {
        if (jsAst && typeof jsAst === 'object' && jsAst.type === 'Identifier') {
          const { name } = jsAst;
          if (/^pug_/.test(name) || name === 'eval') {
            if (!warnedPug) {
              distrust(`Expression (${ expr }) may interfere with PUG internals ${ jsAst.name }`);
              warnedPug = true;
            }
          } else if (name === 'require' &&
                     // Allow trusted plugin code to require modules they need.
                     !(Object.hasOwnProperty.call(astNode, 'mayRequire') && astNode.mayRequire) &&
                     // Allow require.moduleKeys and require.resolve but not require(moduleId).
                     !(jsAstPath.length && jsAstPath[jsAstPath.length - 2].type === 'MemberExpression' &&
                       jsAstPath[jsAstPath.length - 1] === 'object')) {
            // Defang expression.
            astNode[exprKey] = 'null';
            // We trust trusted plugin code and PUG code to use the module's private key
            // but not template code.
            if (!warnedModule) {
              distrust(`Expression (${ expr }) may interfere with module internals ${ jsAst.name }`);
              warnedModule = true;
            }
          }
        }
        checkChildren(jsAst); // eslint-disable-line no-use-before-define
      }

      function checkChildren(jsAst) {
        if (!seen.has(jsAst)) {
          seen.add(jsAst);
          const jsAstPathLength = jsAstPath.length;
          jsAstPath[jsAstPathLength] = jsAst;
          for (const key in jsAst) {
            if (Object.hasOwnProperty.call(jsAst, key)) {
              jsAstPath[jsAstPathLength + 1] = key;
              check(jsAst[key]);
            }
          }
          jsAstPath.length = jsAstPathLength;
        }
      }

      let root = null;
      try {
        root = isExpression ? parseExpression(expr) : parse(expr);
      } catch (exc) {
        distrust(`Malformed expression (${ expr })`);
        return;
      }
      check(root);
    }
function checkCodeDoesNotInterfere ( astNode , exprKey , isExpression ) { let expr = astNode [ exprKey ] ; const seen = new Set ( ) ; const type = typeof expr ; if ( type !== 'string' ) { // expr may be true, not "true". // This occurs for inferred expressions like valueless attributes. expr = ` ${ expr } ` ; astNode [ exprKey ] = expr ; } let warnedPug = false ; let warnedModule = false ; // Allows check to take into account the context in which a node appears. // Flattened pairs of [ancestor, keyInAncestorToDescendent]. const jsAstPath = [ ] ; function check ( jsAst ) { if ( jsAst && typeof jsAst === 'object' && jsAst . type === 'Identifier' ) { const { name } = jsAst ; if ( / ^pug_ / . test ( name ) || name === 'eval' ) { if ( ! warnedPug ) { distrust ( ` ${ expr } ${ jsAst . name } ` ) ; warnedPug = true ; } } else if ( name === 'require' && // Allow trusted plugin code to require modules they need. ! ( Object . hasOwnProperty . call ( astNode , 'mayRequire' ) && astNode . mayRequire ) && // Allow require.moduleKeys and require.resolve but not require(moduleId). ! ( jsAstPath . length && jsAstPath [ jsAstPath . length - 2 ] . type === 'MemberExpression' && jsAstPath [ jsAstPath . length - 1 ] === 'object' ) ) { // Defang expression. astNode [ exprKey ] = 'null' ; // We trust trusted plugin code and PUG code to use the module's private key // but not template code. if ( ! warnedModule ) { distrust ( ` ${ expr } ${ jsAst . name } ` ) ; warnedModule = true ; } } } checkChildren ( jsAst ) ; // eslint-disable-line no-use-before-define } function checkChildren ( jsAst ) { if ( ! seen . has ( jsAst ) ) { seen . add ( jsAst ) ; const jsAstPathLength = jsAstPath . length ; jsAstPath [ jsAstPathLength ] = jsAst ; for ( const key in jsAst ) { if ( Object . hasOwnProperty . call ( jsAst , key ) ) { jsAstPath [ jsAstPathLength + 1 ] = key ; check ( jsAst [ key ] ) ; } } jsAstPath . length = jsAstPathLength ; } } let root = null ; try { root = isExpression ? parseExpression ( expr ) : parse ( expr ) ; } catch ( exc ) { distrust ( ` ${ expr } ` ) ; return ; } check ( root ) ; }
If user expressions have free variables like pug_html then don't bless the output because we'd have to statically analyze the generated JS to preserve output integrity.
If user expressions have free variables like pug_html then don t bless the output because we d have to statically analyze the generated JS to preserve output integrity .