{"record":{"id":"5606fba84d60fab3","repo":"peass-ng/PEASS-ng","slug":"global-variables-join-not-defined-global-va","errorCode":null,"errorMessage":"Global Variables '{', '.join(not_defined_global_vars)}' in module {path} are not defined inside the 'Generated Global Variables' metadata","messagePattern":"Global Variables '(.+?)' in module (.+?) are not defined inside the 'Generated Global Variables' metadata","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"linPEAS/builder/src/linpeasModule.py","lineNumber":227,"sourceCode":"            \"IDENTITY_HEADER\",\n            \"KUBERNETES_SERVICE_PORT_HTTPS\",\n            \"KUBERNETES_SERVICE_HOST\"\n        ]\n        main_base = None\n        \n        # Base global variables don't need to be defined\n        if self.id != \"BS_variables_base\":\n            main_base = LinpeasModule(os.path.join(os.path.dirname(__file__), \"..\", \"linpeas_parts\", \"linpeas_base\", \"0_variables_base.sh\"))\n        \n        not_defined_global_vars = []\n        for var in self.extract_variables(self.sh_code):\n            if len(var) > 2 and not var in linux_global_vars and var not in self.global_variables and var not in self.generated_global_variables:\n                if not var.startswith(\"PSTORAGE_\"):\n                    if not main_base or var not in main_base.generated_global_variables:\n                        not_defined_global_vars.append(\"$\"+var)\n        \n        if not_defined_global_vars:\n            raise Exception(f\"Global Variables '{', '.join(not_defined_global_vars)}' in module {path} are not defined inside the 'Generated Global Variables' metadata\")\n            \n\n    def __eq__(self, other):\n        # Check if other object is an instance of LinpeasModule\n        if isinstance(other, LinpeasModule):\n            return self.id == other.id\n        return NotImplemented  # Return NotImplemented for unsupported comparisons\n\n    def extract_function_names(self):\n        # This regular expression pattern matches function definitions in sh code\n        pattern = r'\\b(\\w+)\\s*\\(\\s*\\)\\s*{'\n        return re.findall(pattern, self.sh_code)\n\n    def extract_variables(self, sh_code):\n        # This regex pattern matches variables in the form $VAR_NAME or ${VAR_NAME}\n        pattern = r'\\$({?([a-zA-Z_][a-zA-Z0-9_]*)}?)'\n        matches = re.findall(pattern, sh_code)\n        # Extract the variable name from each match","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/peass-ng/PEASS-ng/blob/53fb989abc2219826385683a6fee826bd6cd38d6/linPEAS/builder/src/linpeasModule.py#L209-L245","documentation":"The builder statically scans the module's shell code for $VARIABLE references and requires every non-builtin variable to be declared either in '# Global Variables:', '# Generated Global Variables:', the linux_global_vars allowlist, the PSTORAGE_ namespace, or the base variables module. Undeclared variables would be empty at runtime, silently producing wrong results, so the builder refuses to compile the module.","triggerScenarios":"LinpeasModule.__init__ during build when module code references e.g. '$MY_VAR' with len>2, not in linux_global_vars, not in either metadata variable list, not prefixed PSTORAGE_, and not defined in 0_variables_base.sh.","commonSituations":"Adding new shell code that uses a variable without updating the '# Generated Global Variables:' header; typo-ing a variable name so it no longer matches the declared one; relying on a variable that only exists in another module instead of the base file.","solutions":["Add the variable to the module's '# Generated Global Variables:' metadata and generate/emit it in the code","Or add it to '# Global Variables:' if it comes from another module/base part","Fix the typo if the variable name in code does not match the declared one","Move shared variables into linpeas_parts/linpeas_base/0_variables_base.sh"],"exampleFix":"# before\necho \"Found: $FOUND binaries\"\n# after\n# (metadata)\n# Generated Global Variables: FOUND\n# (code)\nFOUND=$(echo \"$FOUND\" | sed 's/ /,/g')\necho \"Found: $FOUND binaries\"","handlingStrategy":"validation","validationCode":"import re\ncode = open(module_path).read()\nused_vars = {v for v in re.findall(r'\\$(\\w+)', code) if len(v) > 2}\ndeclared = set(parse_metadata(\"Global Variables\")) | set(parse_metadata(\"Generated Global Variables\"))\nmissing = {v for v in used_vars if v not in declared and not v.startswith(\"PSTORAGE_\")}\nassert not missing, f\"Undeclared: {missing}\"","typeGuard":null,"tryCatchPattern":"try:\n    LinpeasModule(path)\nexcept Exception as e:\n    print(f\"Module {path} failed validation: {e}\")\n    # add missing vars to metadata and retry","preventionTips":["Every new $VAR added to module code must be declared in metadata","Declare variables in the base variables file for cross-module reuse","Use the PSTORAGE_ prefix convention for auto-generated storage variables"],"tags":["build","metadata","shell","validation"],"backgroundTag":"undeclared-shell-variable","analyzedSha":"53fb989abc2219826385683a6fee826bd6cd38d6","analyzedAt":"2026-09-02T04:25:09.259Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}