-
Notifications
You must be signed in to change notification settings - Fork 30
Add lotp_targets field to untrusted_checkout_exec findings #386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Resolves the target file(s) an attacker should inject into when exploiting a pwn request vulnerability. Static targets use a lookup table (npm→package.json, make→Makefile, etc.), dynamic targets extract file paths via regex from step.run content. The field is an array (lotp_targets) to handle cases where a single run: block references multiple scripts. URL-based references are filtered out to only surface local repository files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds a lotp_targets field to untrusted_checkout_exec findings to identify which files an attacker would need to inject into when exploiting a pwn request vulnerability. The implementation uses static lookup tables for tools with standard configuration files (e.g., npm→package.json) and dynamic regex-based extraction for tools that reference script files in their execution commands (e.g., bash→*.sh files). URL-based references are filtered out to surface only local repository files.
Changes:
- Added
LOTPTargetsfield toFindingMetastruct in results.go as a string array with JSON taglotp_targets - Implemented target resolution logic in utils.rego with static mappings for 32 tools and dynamic patterns for bash, powershell, python, and chmod
- Integrated target resolution into untrusted_checkout_exec findings for GitHub Actions, Azure DevOps, and Tekton pipelines
- Added comprehensive test coverage including static targets, dynamic multi-file scenarios, and URL filtering
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| results/results.go | Added LOTPTargets field to FindingMeta struct for storing target file paths |
| opa/rego/poutine/utils.rego | Implemented lotp_targets resolution with static lookup table and dynamic regex patterns, including URL filtering and path normalization |
| opa/rego/rules/untrusted_checkout_exec.rego | Integrated lotp_targets into findings via _lotp_targets_meta helper function across GitHub Actions, Azure DevOps, and Tekton |
| scanner/inventory_test.go | Updated test expectations to verify lotp_targets for various tools including npm, pre-commit, bash, chmod, and vale |
| scanner/testdata/.github/workflows/test_new_fields.yml | Added test workflow with multi-script bash execution to test dynamic target extraction |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| lotp_static_targets := { | ||
| "ant": "build.xml", | ||
| "bundler": "Gemfile", | ||
| "cargo": "Cargo.toml", | ||
| "checkov": ".checkov.yml", | ||
| "docker": "Dockerfile", | ||
| "eslint": "eslint.config.js", | ||
| "golangci-lint": ".golangci.yml", | ||
| "gomplate": ".gomplate.yaml", | ||
| "goreleaser": ".goreleaser.yaml", | ||
| "gradle": "build.gradle", | ||
| "make": "Makefile", | ||
| "maven": "pom.xml", | ||
| "mkdocs": "mkdocs.yml", | ||
| "msbuild": "Directory.Build.props", | ||
| "mypy": "mypy.ini", | ||
| "npm": "package.json", | ||
| "phpstan": "phpstan.neon", | ||
| "pip": "requirements.txt", | ||
| "pre-commit": ".pre-commit-config.yaml", | ||
| "rake": "Rakefile", | ||
| "rubocop": ".rubocop.yml", | ||
| "sonar-scanner": "sonar-project.properties", | ||
| "stylelint": ".stylelintrc.js", | ||
| "terraform": "main.tf", | ||
| "tflint": ".tflint.hcl", | ||
| "tofu": "main.tf", | ||
| "vale": ".vale.ini", | ||
| "webpack": "webpack.config.js", | ||
| "yarn": "package.json", | ||
| } |
Copilot
AI
Jan 31, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some tools in the static targets mapping use only one specific config file name, but many of these tools support multiple config file formats and names. For example:
- eslint supports: .eslintrc.js, .eslintrc.json, .eslintrc.yml, .eslintrc.yaml, .eslintrc, eslint.config.js, eslint.config.mjs, eslint.config.cjs, and package.json
- stylelint supports: .stylelintrc.js, .stylelintrc.json, .stylelintrc.yml, .stylelintrc.yaml, .stylelintrc, stylelint.config.js, stylelint.config.cjs, and package.json
- mypy supports: mypy.ini, .mypy.ini, pyproject.toml, and setup.cfg
While using the most common config file is a reasonable starting point, attackers could potentially use alternative config files that aren't listed here. Consider either:
- Expanding the mapping to support multiple possible target files per tool (e.g., making the value an array instead of a string)
- Adding a comment documenting that only the most common config file is listed for each tool
- Using dynamic patterns for tools with many config file variations
Resolves the target file(s) an attacker should inject into when exploiting a pwn request vulnerability. Static targets use a lookup table (npm→package.json, make→Makefile, etc.), dynamic targets extract file paths via regex from step.run content.
The field is an array (lotp_targets) to handle cases where a single run: block references multiple scripts. URL-based references are filtered out to only surface local repository files.