-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
84 changed files
with
7,777 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
FROM python:3.10 | ||
|
||
WORKDIR /root | ||
|
||
# Install dependencies | ||
RUN apt-get -y update | ||
RUN apt-get -y install python3-poetry nodejs | ||
RUN mkdir codeql_home | ||
|
||
# Setup codeql | ||
WORKDIR /root/codeql_home | ||
RUN mkdir codeql-repo | ||
RUN git clone --depth 1 https://github.com/github/codeql codeql-repo/ | ||
RUN wget https://github.com/github/codeql-cli-binaries/releases/download/v2.13.3/codeql-linux64.zip | ||
RUN unzip codeql-linux64.zip | ||
|
||
# Copy argus files and queries | ||
COPY argus.py poetry.lock pyproject.toml /root/ | ||
COPY argus_components /root/argus_components | ||
COPY qlqueries /root/qlqueries | ||
RUN poetry install | ||
|
||
# Now run argus | ||
WORKDIR /root | ||
RUN mkdir results | ||
ENTRYPOINT ["poetry", "run", "python3", "argus.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
# Argus | ||
|
||
This repo contains the code for our USENIX Security '23 paper "ARGUS: A Framework for Staged Static Taint Analysis of GitHub Workflows and Actions". Argus is a comprehensive security analysis tool specifically designed for GitHub Actions. Built with an aim to enhance the security of CI/CD workflows, Argus utilizes taint-tracking techniques and an impact classifier to detect potential vulnerabilities in GitHub Action workflows. | ||
|
||
## Features | ||
|
||
- **Taint-Tracking**: Argus uses sophisticated algorithms to track the flow of potentially untrusted data from specific sources to security-critical sinks within GitHub Actions workflows. This enables the identification of vulnerabilities that could lead to code injection attacks. | ||
|
||
- **Impact Classifier**: Argus classifies identified vulnerabilities into High, Medium, and Low severity classes, providing a clearer understanding of the potential impact of each identified vulnerability. This is crucial in prioritizing mitigation efforts. | ||
|
||
## Usage | ||
|
||
This Python script provides a command line interface for interacting with GitHub repositories and GitHub actions. | ||
|
||
```bash | ||
python argus.py --mode [mode] --url [url] [--output-folder path_to_output] [--config path_to_config] [--verbose] [--branch branch_name] [--commit commit_hash] [--tag tag_name] [--action-path path_to_action] [--workflow-path path_to_workflow] | ||
``` | ||
|
||
### Parameters: | ||
|
||
- `--mode`: The mode of operation. Choose either 'repo' or 'action'. This parameter is required. | ||
- `--url`: The GitHub URL. Use `USERNAME:TOKEN@URL` for private repos. This parameter is required. | ||
- `--output-folder`: The output folder. The default value is '/tmp'. This parameter is optional. | ||
- `--config`: The config file. This parameter is optional. | ||
- `--verbose`: Verbose mode. If this option is provided, the logging level is set to DEBUG. Otherwise, it is set to INFO. This parameter is optional. | ||
- `--branch`: The branch name. You must provide exactly one of: `--branch`, `--commit`, `--tag`. This parameter is optional. | ||
- `--commit`: The commit hash. You must provide exactly one of: `--branch`, `--commit`, `--tag`. This parameter is optional. | ||
- `--tag`: The tag. You must provide exactly one of: `--branch`, `--commit`, `--tag`. This parameter is optional. | ||
- `--action-path`: The (relative) path to the action. You cannot provide `--action-path` in repo mode. This parameter is optional. | ||
- `--workflow-path`: The (relative) path to the workflow. You cannot provide `--workflow-path` in action mode. This parameter is optional. | ||
|
||
### Example: | ||
|
||
To use this script to interact with a GitHub repo, you might run a command like the following: | ||
|
||
```bash | ||
python argus.py --mode repo --url https://github.com/username/repo.git --branch master | ||
``` | ||
|
||
This would run the script in repo mode on the master branch of the specified repository. | ||
|
||
### How to use | ||
|
||
Argus can be run inside a docker container. To do so, follow the steps: | ||
- Install docker and docker-compose | ||
- apt-get -y install docker.io docker-compose | ||
- Clone the release branch of this repo | ||
- git clone <> | ||
- Build the docker container | ||
- docker-compose build | ||
- Now you can run argus. Example run: | ||
- docker-compose run argus --mode {mode} --url {url to target repo} | ||
- Results will be available inside the `results` folder | ||
|
||
## Viewing SARIF Results | ||
|
||
You can view SARIF results either through an online viewer or with a Visual Studio Code (VSCode) extension. | ||
|
||
1. **Online Viewer:** The [SARIF Web Viewer](https://microsoft.github.io/sarif-web-component/) is an online tool that allows you to visualize SARIF files. You can upload your SARIF file (`argus_report.sarif`) directly to the website to view the results. | ||
|
||
2. **VSCode Extension:** If you prefer to use VSCode, you can install the [SARIF Viewer](https://marketplace.visualstudio.com/items?itemName=MS-SarifVSCode.sarif-viewer) extension. After installing the extension, you can open your SARIF file (`argus_report.sarif`) in VSCode. The results will appear in the SARIF Explorer pane, which provides a detailed and navigable view of the results. | ||
|
||
Remember to handle the SARIF file with care, especially if it contains sensitive information from your codebase. | ||
|
||
## Troubleshooting | ||
|
||
If there is an issue with needing the Github authorization for running, you can provide `username:TOKEN` in the `GITHUB_CREDS` environment variable. This will be used for all the requests made to Github. Note, we do not store this information anywhere, neither create any thing in the Github account - we only use this for cloning the repositories. | ||
|
||
## Contributions | ||
|
||
Argus is an open-source project, and we welcome contributions from the community. Whether it's reporting a bug, suggesting a feature, or writing code, your contributions are always appreciated! | ||
|
||
## Cite Argus | ||
|
||
If you use Argus in your research, please cite our paper: | ||
|
||
``` | ||
``` | ||
|
||
## License | ||
|
||
Argus is licensed under GPL License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# _____ __________ ________ ____ ___ _________ | ||
# / _ \\______ \/ _____/| | \/ _____/ | ||
# / /_\ \| _/ \ ___| | /\_____ \ | ||
# / | \ | \ \_\ \ | / / \ | ||
# \____|__ /____|_ /\______ /______/ /_______ / | ||
# \/ \/ \/ \/ | ||
# | ||
# Copyright (C) 2023 Siddharth Muralee | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
import click | ||
import logging | ||
|
||
import argus_components | ||
from argus_components.common.config import parse_config | ||
from argus_components.common.pylogger import set_global_log_level | ||
|
||
@click.command() | ||
@click.option("--mode", type=click.Choice(['repo', 'action']), required=True, help="The mode of operation. Choose either 'repo' or 'action'.") | ||
@click.option("--url", required=True, type=str, help="The GitHub URL. use USERNAME:TOKEN@URL for private repos.") | ||
@click.option("--output-folder", required=False, default="/tmp", help="The output folder.", type=click.Path(exists=True)) | ||
@click.option("--config", required=False, default=None, help="The config file.", type=click.Path(exists=True)) | ||
@click.option("--verbose", is_flag=True, default=False, help="Verbose mode.") | ||
@click.option("--branch", default=None, type=str, help="The branch name.") | ||
@click.option("--commit", default=None, type=str, help="The commit hash.") | ||
@click.option("--tag", default=None, type=str, help="The tag.") | ||
@click.option("--action-path", default=None, type=str, help="The (relative) path to the action.") | ||
@click.option("--workflow-path", default=None, type=str, help="The (relative) path to the workflow.") | ||
def main(mode, url, branch, commit, tag, output_folder, config, verbose, action_path, workflow_path): | ||
|
||
if verbose: | ||
set_global_log_level(logging.DEBUG) | ||
else: | ||
set_global_log_level(logging.INFO) | ||
|
||
options = [branch, commit, tag] | ||
options_names = ['branch', 'commit', 'tag'] | ||
num_of_options_provided = sum(option is not None for option in options) | ||
|
||
if num_of_options_provided > 1: | ||
raise click.BadParameter("You must provide exactly one of: --branch, --commit, --tag") | ||
|
||
option_provided, option_value = next(((name, value) for name, value in zip(options_names, options) if value is not None), (None, None)) | ||
|
||
if config: | ||
parse_config(config) | ||
|
||
option_dict = { | ||
"type": option_provided, | ||
"value": option_value | ||
} if option_provided and option_value else {} | ||
|
||
if mode == "repo": | ||
if action_path: | ||
raise click.BadParameter("You cannot provide --action-path in repo mode.") | ||
|
||
repo = argus_components.Repo(url, option_dict) | ||
repo.run(workflow_path) | ||
# repo.print_report() | ||
repo.save_report_to_file() | ||
elif mode == "action": | ||
if workflow_path: | ||
raise click.BadParameter("You cannot provide --workflow-path in action mode.") | ||
|
||
action = argus_components.Action(url, option_dict, action_path) | ||
action.run() | ||
# action.print_report() | ||
action.save_report_to_file() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# _____ __________ ________ ____ ___ _________ | ||
# / _ \\______ \/ _____/| | \/ _____/ | ||
# / /_\ \| _/ \ ___| | /\_____ \ | ||
# / | \ | \ \_\ \ | / / \ | ||
# \____|__ /____|_ /\______ /______/ /_______ / | ||
# \/ \/ \/ \/ | ||
# | ||
# Copyright (C) 2023 Siddharth Muralee | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from .action import Action | ||
from .repo import Repo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
# _____ __________ ________ ____ ___ _________ | ||
# / _ \\______ \/ _____/| | \/ _____/ | ||
# / /_\ \| _/ \ ___| | /\_____ \ | ||
# / | \ | \ \_\ \ | / / \ | ||
# \____|__ /____|_ /\______ /______/ /_______ / | ||
# \/ \/ \/ \/ | ||
# | ||
# Copyright (C) 2023 Siddharth Muralee | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
from urllib.parse import urlparse | ||
|
||
from argus_components.common.config import LOCAL_FOLDER, RESULTS_FOLDER | ||
from argus_components.common.pylogger import get_logger | ||
from argus_components.common.githandler import clone_repo | ||
|
||
from argus_components.plugins import GHAction | ||
|
||
logger = get_logger("repo") | ||
|
||
class Action: | ||
LOCAL_ACTION = 1 | ||
REMOTE_ACTION = 2 | ||
|
||
def __init__(self, action_url, options_dict, action_path, action_type = REMOTE_ACTION): | ||
self.action_url = action_url | ||
self.options_dict = options_dict | ||
self.action_path = action_path | ||
self.action_type = action_type | ||
|
||
if self.action_type == self.REMOTE_ACTION and "github.com" not in self.action_url: | ||
raise Exception("Only GitHub Actions are supported for now") | ||
|
||
if self.action_type == self.LOCAL_ACTION: | ||
pass | ||
elif self.action_type == self.REMOTE_ACTION: | ||
self.action_name = self._get_action_name_from_url() | ||
self.name = self.action_name.replace("#", "/") | ||
else: | ||
raise Exception("Invalid action type") | ||
|
||
logger.info(f"Initialzed Action : {self.action_name}") | ||
|
||
def run(self): | ||
if self.action_type == self.LOCAL_ACTION: | ||
self._run_local_action() | ||
elif self.action_type == self.REMOTE_ACTION: | ||
self._run_remote_action() | ||
|
||
def _run_local_action(self): | ||
pass | ||
|
||
def _run_remote_action(self): | ||
folder = LOCAL_FOLDER / self.action_name | ||
logger.info(f"Cloning action to {folder}") | ||
# clone the repository | ||
clone_repo(self.action_url, folder, self.options_dict) | ||
# Get action Object | ||
action_obj = GHAction.identify_action(self.name, self.action_path, folder, self) | ||
self.report = action_obj.run() | ||
|
||
def _get_action_name_from_url(self): | ||
# https://github.com/repo/action_name/optional_path/optional_path2 | ||
# need to return action_name | ||
# let's get both the repo name and the action name | ||
path = urlparse(self.action_url).path | ||
repo, action = path.split("/")[1], path.split("/")[2] | ||
|
||
return repo + "#" + action | ||
|
||
def save_report_to_file(self): | ||
file_name = RESULTS_FOLDER / f"{self.action_name}_{self.options_dict['value']}.sarif" | ||
return self.report.get_report(file_name) | ||
|
||
def print_report(self): | ||
return self.report.get_report(None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# _____ __________ ________ ____ ___ _________ | ||
# / _ \\______ \/ _____/| | \/ _____/ | ||
# / /_\ \| _/ \ ___| | /\_____ \ | ||
# / | \ | \ \_\ \ | / / \ | ||
# \____|__ /____|_ /\______ /______/ /_______ / | ||
# \/ \/ \/ \/ | ||
# | ||
# Copyright (C) 2023 Siddharth Muralee | ||
|
||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 3 of the License, or | ||
# (at your option) any later version. | ||
|
||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
# You should have received a copy of the GNU General Public License | ||
# along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
||
from .github import GithubCI |
Oops, something went wrong.