Skip to content

Commit

Permalink
Updated Exit Codes (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
swashko authored Oct 9, 2023
1 parent 19b0429 commit 3c87e3d
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 28 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ Remember models are just like any other form of digital media, you should scan c
**NOTE**: LLMs are large files, it can take a few minutes to download them before scanning. Expect the process
to take just a few minutes to complete.

##### CLI Exit Codes
The CLI exit status codes are:
- `0`: Scan completed successfully, no vulnerabilities found
- `1`: Scan completed successfully, vulnerabilities found
- `2`: Scan failed, modelscan threw an error while scanning
- `3`: No supported files were passed to the tool
- `4`: Usage error, CLI was passed invalid or incomplete options

### Understanding The Results

Once a scan has been completed you'll see output like this if an issue is found:
Expand Down
84 changes: 57 additions & 27 deletions modelscan/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])


# redefine format_usage so the appropriate command name shows up
class ModelscanCommand(click.Command):
def format_usage(self, ctx: click.Context, formatter: click.HelpFormatter) -> None:
pieces = self.collect_usage_pieces(ctx)
formatter.write_usage("modelscan", " ".join(pieces))


@click.command(
context_settings=CONTEXT_SETTINGS,
cls=ModelscanCommand,
help="Modelscan detects machine learning model files that perform suspicious actions",
)
@click.version_option(__version__, "-v", "--version")
Expand Down Expand Up @@ -65,39 +73,61 @@ def cli(
if log is not None:
logger.setLevel(getattr(logging, log))

try:
modelscan = Modelscan()
if path is not None:
pathlibPath = Path().cwd() if path == "." else Path(path).absolute()
if not pathlibPath.exists():
raise FileNotFoundError(f"Path {path} does not exist")
else:
modelscan.scan_path(pathlibPath)
# elif url is not None:
# modelscan.scan_url(url)
elif huggingface is not None:
modelscan.scan_huggingface_model(huggingface)
modelscan = Modelscan()
if path is not None:
pathlibPath = Path().cwd() if path == "." else Path(path).absolute()
if not pathlibPath.exists():
raise FileNotFoundError(f"Path {path} does not exist")
else:
raise click.UsageError(
"Command line must include either a path or a Hugging Face model"
)
ConsoleReport.generate(
modelscan.issues,
modelscan.errors,
modelscan._skipped,
show_skipped=show_skipped,
modelscan.scan_path(pathlibPath)
# elif url is not None:
# modelscan.scan_url(url)
elif huggingface is not None:
modelscan.scan_huggingface_model(huggingface)
else:
raise click.UsageError(
"Command line must include either a path or a Hugging Face model"
)
return 0
ConsoleReport.generate(
modelscan.issues,
modelscan.errors,
modelscan._skipped,
show_skipped=show_skipped,
)

except click.UsageError as e:
click.echo(e)
click.echo(ctx.get_help())
# exit code 3 if no supported files were passed
if not modelscan.scanned:
return 3
# exit code 2 if scan encountered errors
elif modelscan.errors:
return 2
# exit code 1 if scan completed successfully and vulnerabilities were found
elif modelscan.issues.all_issues:
return 1
# exit code 0 if scan completed successfully and no vulnerabilities were found
else:
return 0


def main() -> None:
try:
result = cli.main(standalone_mode=False)

except click.ClickException as e:
click.echo(f"Error: {e}")
with click.Context(cli) as ctx:
click.echo(cli.get_help(ctx))
# exit code 4 for CLI usage errors
result = 4

except Exception as e:
logger.exception(f"Exception: {e}")
return 2
click.echo(f"Exception: {e}")
# exit code 2 if scan throws exceptions
result = 2

finally:
sys.exit(result)


if __name__ == "__main__":
sys.exit(cli())
main()
6 changes: 6 additions & 0 deletions modelscan/modelscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def __init__(self) -> None:
self._issues = Issues()
self._errors: List[Error] = []
self._skipped: List[str] = []
self._scanned: List[str] = []

def scan_path(self, path: Path) -> None:
if path.is_dir():
Expand Down Expand Up @@ -124,6 +125,7 @@ def _scan_source(
if extension in scan.supported_extensions():
logger.info(f"Scanning {source} using {scan.name()} model scan")
issues, errors = scan.scan(source=source, data=data)
self._scanned.append(str(source))

self._issues.add_issues(issues)
self._errors.extend(errors)
Expand Down Expand Up @@ -154,6 +156,10 @@ def issues(self) -> Issues:
def errors(self) -> List[Error]:
return self._errors

@property
def scanned(self) -> List[str]:
return self._scanned

@property
def skipped(self) -> List[str]:
return self._skipped
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ packages = [{ include = "modelscan" }]
exclude = ["tests/*", "Makefile"]

[tool.poetry.scripts]
modelscan = "modelscan.cli:cli"
modelscan = "modelscan.cli:main"

[tool.poetry.dependencies]
python = ">=3.8,<3.12"
Expand Down

0 comments on commit 3c87e3d

Please sign in to comment.