codeaudit 1.9.2__tar.gz → 1.9.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {codeaudit-1.9.2 → codeaudit-1.9.3}/CHANGELOG.md +16 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/PKG-INFO +3 -2
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/codeauditcommands.md +1 -1
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_api_example_scanning.ipynb +1 -1
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/codeauditchecks.html +2 -2
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/demoscan.json +2 -2
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/makeitbetter.md +13 -1
- {codeaudit-1.9.2 → codeaudit-1.9.3}/pyproject.toml +5 -4
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/__about__.py +1 -1
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/altairplots.py +7 -29
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/api_interfaces.py +29 -11
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/api_reporting.py +23 -7
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/data/sastchecks.csv +1 -1
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/dashboardapp.py +137 -36
- codeaudit-1.9.3/src/dashboard/pyodide/dashboardapp_192.html +299 -0
- codeaudit-1.9.3/src/dashboard/pyodide/dashboardapp_fixedTMPfor_v1.9.0.js +91 -0
- codeaudit-1.9.3/src/dashboard/pyodide/deployed/dashboardapp_192.html +299 -0
- codeaudit-1.9.3/src/dashboard/pyodide/deployed/dashboardapp_fixedTMPfor_v1.9.0.js +91 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/test_count_weaknesses.py +12 -0
- codeaudit-1.9.3/tests/unit_tests/test_get_weakness_counts.py +495 -0
- codeaudit-1.9.3/tests/validationfiles/zip_example.json +144 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/.github/workflows/python-test.yml +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/.github/workflows/sast_validation.yml +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/.gitignore +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/CONTRIBUTE.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/LICENSE.txt +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/README.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/SECURITY.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/.gitignore +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/class_index.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/coverage_html_cb_dd2e7eb5.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/favicon_32_cb_c827f16f.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/function_index.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/index.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/keybd_closed_cb_900cfef5.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/status.json +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/style_cb_9ff733b0.css +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8___about___py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8___init___py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_altairplots_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_api_helpers_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_api_interfaces_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_api_reporting_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_checkmodules_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_codeaudit_dashboard_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_codeaudit_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_complexitycheck_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_dashboard_reports_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_filehelpfunctions_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_htmlhelpfunctions_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_issuevalidations_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_privacy_lint_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_pypi_package_scan_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_reporting_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_security_checks_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_suppression_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/cov_html/z_15dab3f49bf85fa8_totals_py.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/CLIcommands.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/CONTRIBUTE.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/_config.yml +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/_static/nocxstyle.css +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/_toc.yml +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/about.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/apidocs/api_intro.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/apidocs/codeaudit.rst +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/apidocs/modules.rst +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/architecture.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/changelog.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/assert_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/base64_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/binding_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/builtinfunctions_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/chmod_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/directorycreation_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/dynamicimport_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/exception_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/ftp_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/hash_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/httpserver_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/input_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/loggingconf_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/marshal_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/mktemp_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/multiprocessing_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/pickle_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/random_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/shelve_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/shutil_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/subprocess_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/syscalls_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/systemcalls_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/tarfile_extract_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/xml_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checks/zipfile_check.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/checksinformation.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/cimode.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/codeauditchecks.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/codeauditoverview.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/complexitycheck.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/data_egress_implementation.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/data_exfiltration_detection.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_api_example_basic.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_api_example_checks.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_api_example_json.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_api_example_overview.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/ca_checks.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/demofile.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/directoryscan.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/example_risk_heatmap.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/example_weakness_perfile_view.ipynb +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/filescan.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/modulescan.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/examples/overview.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/features.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/filescan.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/filescan.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/handling_errors.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/help.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/howtoscan.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/OO.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/ROI_logo.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/YourLogoHere.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/ai_use.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/architecture_overview.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/codeauditlogo.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/filescan_screenshot_16012026.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/modulescan_screenshot_16012026.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/nocxbanner.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/overview_linkaudit.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/images/overview_screenshot_16012026.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/implementedvalidations.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/installation.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/intro.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/issues.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/license.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/markingissues.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/modulescan.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/overviewplot.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/pca_overview.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/project_philosophy.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/sponsors.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/userguide.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/warnings.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/whatissast.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/docs/whysast.md +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/filescan.png +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/__init__.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/api_helpers.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/checkmodules.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/ci_workflowscan.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/complexitycheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/corecli.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/dashboard_reports.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/data/secretslist.txt +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/filehelpfunctions.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/htmlhelpfunctions.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/issuevalidations.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/privacy_lint.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/pypi_package_scan.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/reporting.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/security_checks.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/simple.css +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/suppression.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/codeaudit/totals.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/__init__.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/module_load_validation.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/module_load_validation2.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_171.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_171.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_190.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_190.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_191.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_191.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_version162.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_version162.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_version166.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/dashboardapp_version166.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/deployed/dashboardapp_171.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/deployed/dashboardapp_171.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/deployed/dashboardapp_180.html +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/pyodide/deployed/dashboardapp_180.js +0 -0
- /codeaudit-1.9.2/src/dashboard/pyodide/deployed/dashboardapp.html → /codeaudit-1.9.3/src/dashboard/pyodide/deployed/dashboardapp_191.html +0 -0
- /codeaudit-1.9.2/src/dashboard/pyodide/deployed/dashboardapp.js → /codeaudit-1.9.3/src/dashboard/pyodide/deployed/dashboardapp_191.js +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/src/dashboard/requirements.txt +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/__init__.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/count_lines_file1.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/clean.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/elastic.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/example1.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/klyne.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/mixed.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/telemetry.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/spytestdir/telemetryfile2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/suppression/sastsuppression_0.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/suppression/sastsuppression_1.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/suppression/sastsuppression_2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_apicalls.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_apicalls2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_base64.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_basicpatterns.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_chmod.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_constructspart2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_correctexceptionuse.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_count_commentlines.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_directorycreation.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_directorycreation2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_dynamic_import.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_edgecases.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_filescan_api.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_ftp.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_hashstrenght.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_importlib_util.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_modulecheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_obfuscatingbuiltins.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_oschecks.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_pylintreport.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_pypiscan.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_random.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_secretfinding.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_standardlibconstructs.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_subprocess.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_suppression.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_suppressionlogic.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_totalscheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_valid_python.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_wasmsafe_funtions.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/test_zstd.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/__init__.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/test_clean_import_list.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/test_collectsourcefiles.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/test_filehelpfunctions.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/unit_tests/test_readinsourcefile.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/allshit.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/apivalidations.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/assert.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/base64.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/chmod_things.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/codeaudit_scan.json +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/complexitycheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/correctcounts.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/danger_imports.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/directorycreation.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/directorycreation2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/dunderexec_with_parsing_error.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/eval.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/eval2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/exception.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/file3.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/file_with_warnings.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/ftp.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/gzip.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/hashcheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/httpserver.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/incorrect_python_file.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/inputstatement.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/linkaudit-0.9.9.tar.gz +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/malware.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/malwareAI.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/marshal.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/modulecheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/multiprocessing.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/obfuscating.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/oschecks.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/pickle.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/python2_file_willnotwork.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/random.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/shelve.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/shutil.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/subprocess.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/syslibrary.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/tarfilevalidation.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/tempcheck.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/validation1.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/validation2.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/xml.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/zipfile.py +0 -0
- {codeaudit-1.9.2 → codeaudit-1.9.3}/tests/validationfiles/zstd.py +0 -0
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## Version 1.9.3:
|
|
4
|
+
|
|
5
|
+
**Changed**
|
|
6
|
+
|
|
7
|
+
* Updated functions `weaknesses_overview` and `total_weaknesses`.
|
|
8
|
+
|
|
9
|
+
**Fixed**
|
|
10
|
+
|
|
11
|
+
* Fixed issue in API function `get_weakness_counts` and included extra tests.
|
|
12
|
+
* Corrected severity for the `input` function.
|
|
13
|
+
|
|
14
|
+
**Documentation**
|
|
15
|
+
* Validated and documented correct working and compatibility for Python 3.15.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
3
19
|
## Version 1.9.2:
|
|
4
20
|
|
|
5
21
|
* Fixed issue for API scan
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: codeaudit
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.3
|
|
4
4
|
Summary: A modern Python security source code analyzer (SAST) based on distrust.
|
|
5
5
|
Project-URL: Homepage, https://codeaudit.nocomplexity.com
|
|
6
6
|
Project-URL: Documentation, https://github.com/nocomplexity/codeaudit#readme
|
|
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
21
22
|
Classifier: Topic :: Security
|
|
22
23
|
Classifier: Topic :: Software Development :: Quality Assurance
|
|
23
24
|
Requires-Python: >=3.12
|
|
@@ -422,7 +422,7 @@ footer {
|
|
|
422
422
|
<tr>
|
|
423
423
|
<td>Input Function</td>
|
|
424
424
|
<td>input</td>
|
|
425
|
-
<td>
|
|
425
|
+
<td>High</td>
|
|
426
426
|
<td>User input must be strictly sanitized and validated to prevent injection vulnerabilities.</td>
|
|
427
427
|
</tr>
|
|
428
428
|
<tr>
|
|
@@ -774,4 +774,4 @@ footer {
|
|
|
774
774
|
<td>Vulnerable to path traversal attacks if used with untrusted archives.</td>
|
|
775
775
|
</tr>
|
|
776
776
|
</tbody>
|
|
777
|
-
</table><br><p>Number of implemented security validations:<b>89</b></p><p>Version of codeaudit: <b>1.9.
|
|
777
|
+
</table><br><p>Number of implemented security validations:<b>89</b></p><p>Version of codeaudit: <b>1.9.3</b><p>Because Python and cybersecurity are constantly changing, issue reports <b>SHOULD</b> specify the codeaudit version used.</p><p><b>Disclaimer:</b> <i>This SAST tool <a href="https://github.com/nocomplexity/codeaudit" target="_blank"><b>Python Code Audit</b></a> provides a powerful, automatic security analysis for Python source code. However, it's not a substitute for human review in combination with business knowledge. Undetected vulnerabilities may still exist.</i></p><p>This Python security report was created on: <b>2026-10-30 18:27</b> with <a href="https://github.com/nocomplexity/codeaudit" target="_blank"><b>Python Code Audit</b></a> version <b>1.9.3</b></p><hr><footer><div class="footer-links">Check the <a href="https://nocomplexity.com/documents/codeaudit/intro.html" target="_blank">documentation</a> for help on found issues.<br>Codeaudit is made with <span class="heart">❤</span> by cyber security professionals who advocate for <a href="https://nocomplexity.com/simplify-security/" target="_blank">open simple security solutions</a>.<br><a href="https://nocomplexity.com/documents/codeaudit/CONTRIBUTE.html" target="_blank">Join the community</a> and contribute to make this tool better!</div></footer></div></body></html>
|
|
@@ -38,6 +38,16 @@ To lower the barrier for new contributors, I'd make the tone more welcoming, red
|
|
|
38
38
|
|
|
39
39
|
Welcome! This guide will help you set up a local development environment for Python Code Audit and start contributing to the project.
|
|
40
40
|
|
|
41
|
+
### 0. Create and activate an new environment
|
|
42
|
+
|
|
43
|
+
I prefer using [`conda`](https://nocomplexity.com/documents/pythonbook/environments.html#environments) but use what you want.
|
|
44
|
+
|
|
45
|
+
Set up a new environment:
|
|
46
|
+
```bash
|
|
47
|
+
conda create --name codeaudit_dev python=3.15
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
|
|
41
51
|
### 1. Clone the repository
|
|
42
52
|
|
|
43
53
|
We recommend working in a dedicated virtual environment to avoid conflicts with other Python projects.
|
|
@@ -48,14 +58,16 @@ The Python Code Audit source code is hosted on GitHub.
|
|
|
48
58
|
```bash
|
|
49
59
|
git clone https://github.com/nocomplexity/codeaudit
|
|
50
60
|
cd codeaudit
|
|
61
|
+
pip install -e .
|
|
51
62
|
```
|
|
52
63
|
|
|
64
|
+
|
|
53
65
|
### 2. Install development dependencies
|
|
54
66
|
|
|
55
67
|
Install `pytest`, which is used for running the test suite:
|
|
56
68
|
|
|
57
69
|
```bash
|
|
58
|
-
pip install pytest
|
|
70
|
+
pip install -U pytest
|
|
59
71
|
```
|
|
60
72
|
|
|
61
73
|
### 3. Install Hatch
|
|
@@ -25,6 +25,7 @@ classifiers = [
|
|
|
25
25
|
"Programming Language :: Python :: 3.12",
|
|
26
26
|
"Programming Language :: Python :: 3.13",
|
|
27
27
|
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Programming Language :: Python :: 3.15",
|
|
28
29
|
]
|
|
29
30
|
|
|
30
31
|
[project.optional-dependencies]
|
|
@@ -57,14 +58,14 @@ extra-dependencies = [
|
|
|
57
58
|
check = "mypy --install-types --non-interactive {args:src/codeaudit tests}"
|
|
58
59
|
|
|
59
60
|
[[tool.hatch.envs.hatch-test.matrix]]
|
|
60
|
-
python = ["3.14", "3.13", "3.12"]
|
|
61
|
+
python = ["3.15", "3.14", "3.13", "3.12"]
|
|
61
62
|
|
|
62
63
|
[tool.hatch.envs.hatch-test]
|
|
63
64
|
randomize = true
|
|
64
65
|
dependencies = ["pytest", "pytest-cov", "coverage"]
|
|
65
66
|
|
|
66
67
|
[tool.black]
|
|
67
|
-
target-version = ["
|
|
68
|
+
target-version = ["py312", "py313", "py314","py315"]
|
|
68
69
|
extend-exclude ='(python2_file_willnotwork|dunderexec_with_parsing_error).py|validationfiles|suppression|spytestdir'
|
|
69
70
|
|
|
70
71
|
[tool.coverage.run]
|
|
@@ -78,8 +79,8 @@ show_missing = true
|
|
|
78
79
|
dependencies = ["black", "pylint"]
|
|
79
80
|
|
|
80
81
|
[tool.hatch.envs.hatch-static-analysis.scripts]
|
|
81
|
-
format-check = "black --target-version
|
|
82
|
-
format-fix = "black --target-version
|
|
82
|
+
format-check = "black --target-version py314 --check src tests"
|
|
83
|
+
format-fix = "black --target-version py314 src tests"
|
|
83
84
|
lint-check = "pylint src tests"
|
|
84
85
|
|
|
85
86
|
[tool.pytest]
|
|
@@ -18,7 +18,8 @@ import pandas as pd
|
|
|
18
18
|
|
|
19
19
|
from collections import Counter
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
|
|
21
|
+
from codeaudit.api_interfaces import get_weakness_counts
|
|
22
|
+
from codeaudit.api_reporting import total_weaknesses
|
|
22
23
|
|
|
23
24
|
def module_count_barchart(scanresult):
|
|
24
25
|
"""Create a bar chart showing module counts by category.
|
|
@@ -689,20 +690,8 @@ def weaknesses_overview(scanresult):
|
|
|
689
690
|
.mark_text()
|
|
690
691
|
.encode(text="msg:N")
|
|
691
692
|
)
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
counter = Counter()
|
|
695
|
-
for file_info in file_security_info.values():
|
|
696
|
-
if not isinstance(file_info, dict):
|
|
697
|
-
continue
|
|
698
|
-
sast_result = file_info.get("sast_result")
|
|
699
|
-
if not isinstance(sast_result, dict):
|
|
700
|
-
continue
|
|
701
|
-
for finding in sast_result.values():
|
|
702
|
-
if isinstance(finding, dict):
|
|
703
|
-
validation = finding.get("validation")
|
|
704
|
-
if validation and isinstance(validation, str):
|
|
705
|
-
counter[validation] += 1
|
|
693
|
+
# --- Count every validation across all files ---
|
|
694
|
+
counter = Counter(get_weakness_counts(scanresult))
|
|
706
695
|
|
|
707
696
|
if not counter:
|
|
708
697
|
return (
|
|
@@ -875,7 +864,7 @@ def sast_files_overview(scanresult):
|
|
|
875
864
|
"base_name": base_name,
|
|
876
865
|
"parent_folder": parent_folder,
|
|
877
866
|
"full_path": str(filepath),
|
|
878
|
-
"issues":
|
|
867
|
+
"issues": total_weaknesses(scanresult),
|
|
879
868
|
"complexity": file_info.get("Complexity_Score", 0),
|
|
880
869
|
}
|
|
881
870
|
)
|
|
@@ -977,19 +966,8 @@ def weaknesses_radial_overview(scanresult):
|
|
|
977
966
|
)
|
|
978
967
|
|
|
979
968
|
# --- Count every 'validation' across all files ---
|
|
980
|
-
counter = Counter()
|
|
981
|
-
|
|
982
|
-
if not isinstance(file_info, dict):
|
|
983
|
-
continue
|
|
984
|
-
sast_result = file_info.get("sast_result")
|
|
985
|
-
if not isinstance(sast_result, dict):
|
|
986
|
-
continue
|
|
987
|
-
for finding in sast_result.values():
|
|
988
|
-
if isinstance(finding, dict):
|
|
989
|
-
validation = finding.get("validation")
|
|
990
|
-
if validation and isinstance(validation, str):
|
|
991
|
-
counter[validation] += 1
|
|
992
|
-
|
|
969
|
+
counter = Counter(get_weakness_counts(scanresult))
|
|
970
|
+
|
|
993
971
|
if not counter:
|
|
994
972
|
return (
|
|
995
973
|
alt.Chart(
|
|
@@ -315,38 +315,56 @@ def read_input_file(filename, safe_directory="data_folder"):
|
|
|
315
315
|
|
|
316
316
|
def get_weakness_counts(input_file, nosec=False):
|
|
317
317
|
"""
|
|
318
|
-
|
|
318
|
+
Count SAST weaknesses.
|
|
319
|
+
|
|
320
|
+
Accepts either:
|
|
321
|
+
- A scan result dictionary.
|
|
322
|
+
- A file/package path that will be scanned.
|
|
319
323
|
"""
|
|
320
|
-
|
|
321
|
-
|
|
324
|
+
|
|
325
|
+
# Accept an existing scan result or scan a file/package
|
|
326
|
+
if isinstance(input_file, dict):
|
|
327
|
+
scan_result = input_file
|
|
328
|
+
else:
|
|
329
|
+
scan_result = filescan(input_file, nosec)
|
|
322
330
|
|
|
323
331
|
if not isinstance(scan_result, dict):
|
|
324
|
-
raise ValueError("
|
|
332
|
+
raise ValueError("Invalid scan result")
|
|
325
333
|
|
|
326
334
|
if "Error" in scan_result:
|
|
327
335
|
raise ValueError(scan_result["Error"])
|
|
328
336
|
|
|
329
337
|
file_security_info = scan_result.get("file_security_info")
|
|
338
|
+
|
|
330
339
|
if not isinstance(file_security_info, dict):
|
|
331
340
|
return {}
|
|
332
341
|
|
|
333
342
|
counter = Counter()
|
|
334
343
|
|
|
335
344
|
for file_info in file_security_info.values():
|
|
345
|
+
|
|
336
346
|
if not isinstance(file_info, dict):
|
|
337
347
|
continue
|
|
338
348
|
|
|
339
349
|
sast_result = file_info.get("sast_result", {})
|
|
350
|
+
|
|
340
351
|
if not isinstance(sast_result, dict):
|
|
341
352
|
continue
|
|
342
353
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if isinstance(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
354
|
+
for finding in sast_result.values():
|
|
355
|
+
|
|
356
|
+
# Support individual findings and lists of findings
|
|
357
|
+
findings = finding if isinstance(finding, list) else [finding]
|
|
358
|
+
|
|
359
|
+
for issue in findings:
|
|
360
|
+
|
|
361
|
+
if not isinstance(issue, dict):
|
|
362
|
+
continue
|
|
363
|
+
|
|
364
|
+
weakness_type = issue.get("validation", "Unknown")
|
|
365
|
+
|
|
366
|
+
if isinstance(weakness_type, str) and weakness_type:
|
|
367
|
+
counter[weakness_type] += 1
|
|
350
368
|
|
|
351
369
|
return dict(counter)
|
|
352
370
|
|
|
@@ -19,17 +19,33 @@ So all results are returned as Pandas Dataframe. This makes things easier for fu
|
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
|
|
23
22
|
def total_weaknesses(scan_result):
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
"""Count all individual weaknesses in a scan result.
|
|
24
|
+
|
|
25
|
+
Walks through each file's SAST findings and adds up every
|
|
26
|
+
individual weakness found.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
scan_result (dict): Scan output with a "file_security_info" key
|
|
30
|
+
mapping file names to their per-file results. Each file's
|
|
31
|
+
"sast_result" maps check names to either a single finding
|
|
32
|
+
or a list of findings.
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
Returns:
|
|
35
|
+
int: Total number of individual weaknesses across all files.
|
|
36
|
+
"""
|
|
29
37
|
total = 0
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
file_security_info = scan_result.get("file_security_info", {})
|
|
40
|
+
|
|
41
|
+
for file_info in file_security_info.values():
|
|
32
42
|
sast_result = file_info.get("sast_result", {})
|
|
33
|
-
|
|
43
|
+
|
|
44
|
+
for finding in sast_result.values():
|
|
45
|
+
if isinstance(finding, list):
|
|
46
|
+
total += len(finding)
|
|
47
|
+
else:
|
|
48
|
+
total += 1
|
|
34
49
|
|
|
35
50
|
return total
|
|
51
|
+
|
|
@@ -9,7 +9,7 @@ Directory Creation,os.mknod,Low,Direct file system calls require careful input v
|
|
|
9
9
|
Directory Creation,os.makedev,Low,Direct file system calls require careful input validation to prevent vulnerabilities.
|
|
10
10
|
OS Forking,os.fork,Low,"On macOS use of this function is unsafe when mixed with using higher-level system APIs, and that includes using urllib.request."
|
|
11
11
|
Dangerous Built-in: eval,eval,High,This function can execute arbitrary code. Never safe with untrusted input.
|
|
12
|
-
Input Function,input,
|
|
12
|
+
Input Function,input,High,User input must be strictly sanitized and validated to prevent injection vulnerabilities.
|
|
13
13
|
Overly Broad Exception Handling,pass,Low,Using `pass` in an `except` block can silently ignore critical security exceptions.
|
|
14
14
|
Overly Broad Exception Handling,continue,Low,Skipping over exceptions can mask critical errors and security risks.
|
|
15
15
|
Dangerous Built-in: exec,exec,High,This function can execute arbitrary code and should be used only with validated constructs.
|
|
@@ -88,42 +88,60 @@ async def get_pypi_download_info_wasm(package_name):
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
async def get_package_source_wasm(url):
|
|
91
|
-
import
|
|
92
|
-
import tarfile
|
|
91
|
+
import os
|
|
93
92
|
import tempfile
|
|
94
|
-
import zlib
|
|
95
|
-
|
|
96
93
|
from pyodide.http import pyfetch
|
|
97
94
|
|
|
95
|
+
tmpdir_obj = None
|
|
98
96
|
try:
|
|
99
97
|
response = await pyfetch(url)
|
|
100
98
|
if not response.ok:
|
|
101
99
|
return None
|
|
102
100
|
|
|
103
|
-
content = await response.bytes()
|
|
104
|
-
content_encoding = response.headers.get("Content-Encoding")
|
|
105
|
-
|
|
106
|
-
if content_encoding == "gzip":
|
|
107
|
-
content = gzip.decompress(content)
|
|
108
|
-
elif content_encoding == "deflate":
|
|
109
|
-
content = zlib.decompress(content, -zlib.MAX_WBITS)
|
|
110
|
-
|
|
111
101
|
tmpdir_obj = tempfile.TemporaryDirectory(prefix="codeaudit_")
|
|
112
102
|
temp_dir = tmpdir_obj.name
|
|
103
|
+
extract_dir = os.path.join(temp_dir, "extracted")
|
|
104
|
+
os.makedirs(extract_dir, exist_ok=True) #nosec
|
|
105
|
+
|
|
106
|
+
# Recommended Pyodide way – works reliably in MEMFS
|
|
107
|
+
await response.unpack_archive(extract_dir=extract_dir, format="gztar")
|
|
108
|
+
|
|
109
|
+
# Locate the actual package root (same logic as before)
|
|
110
|
+
entries = os.listdir(extract_dir)
|
|
111
|
+
directories = [
|
|
112
|
+
os.path.join(extract_dir, entry)
|
|
113
|
+
for entry in entries
|
|
114
|
+
if os.path.isdir(os.path.join(extract_dir, entry))
|
|
115
|
+
]
|
|
116
|
+
files = [
|
|
117
|
+
entry
|
|
118
|
+
for entry in entries
|
|
119
|
+
if os.path.isfile(os.path.join(extract_dir, entry))
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
if len(directories) == 1 and not files:
|
|
123
|
+
source_dir = directories[0]
|
|
124
|
+
else:
|
|
125
|
+
source_dir = extract_dir
|
|
126
|
+
|
|
127
|
+
# Verify that the extracted source contains Python files
|
|
128
|
+
has_python_files = any(
|
|
129
|
+
filename.endswith(".py")
|
|
130
|
+
for root, _, filenames in os.walk(source_dir)
|
|
131
|
+
for filename in filenames
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if not has_python_files:
|
|
135
|
+
print(f"WASM extraction found no .py files under {source_dir}")
|
|
136
|
+
tmpdir_obj.cleanup()
|
|
137
|
+
return None
|
|
113
138
|
|
|
114
|
-
|
|
115
|
-
with open(tar_path, "wb") as f:
|
|
116
|
-
f.write(content)
|
|
117
|
-
|
|
118
|
-
with tarfile.open(tar_path, "r:gz") as tar:
|
|
119
|
-
tar.extractall(
|
|
120
|
-
path=temp_dir, filter="data"
|
|
121
|
-
) # nosec Possible risks are mitigated and this happens in the WASM context.
|
|
122
|
-
|
|
123
|
-
return temp_dir, tmpdir_obj
|
|
139
|
+
return source_dir, tmpdir_obj
|
|
124
140
|
|
|
125
141
|
except Exception as e:
|
|
126
|
-
print(f"WASM fetch error: {e}")
|
|
142
|
+
print(f"WASM fetch/extraction error: {e}")
|
|
143
|
+
if tmpdir_obj is not None:
|
|
144
|
+
tmpdir_obj.cleanup()
|
|
127
145
|
return None
|
|
128
146
|
|
|
129
147
|
|
|
@@ -175,12 +193,28 @@ async def filescan_wasm(input_path, nosec=False):
|
|
|
175
193
|
try:
|
|
176
194
|
scan_output = _codeaudit_directory_scan_wasm(src_dir, nosec_flag=nosec)
|
|
177
195
|
output |= scan_output
|
|
178
|
-
#
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
196
|
+
# Normalize optional sections before updating them.
|
|
197
|
+
# The WASM scanner may omit these sections for some packages.
|
|
198
|
+
module_overview = output.setdefault(
|
|
199
|
+
"module_overview",
|
|
200
|
+
{"core_modules": [], "imported_modules": []},
|
|
183
201
|
)
|
|
202
|
+
if not isinstance(module_overview, dict):
|
|
203
|
+
module_overview = {
|
|
204
|
+
"core_modules": [],
|
|
205
|
+
"imported_modules": [],
|
|
206
|
+
}
|
|
207
|
+
output["module_overview"] = module_overview
|
|
208
|
+
|
|
209
|
+
# package_imports() can return None when module data is absent.
|
|
210
|
+
correct_imported_modules = package_imports(output) or []
|
|
211
|
+
module_overview["imported_modules"] = correct_imported_modules
|
|
212
|
+
|
|
213
|
+
statistics_overview = output.setdefault("statistics_overview", {})
|
|
214
|
+
if not isinstance(statistics_overview, dict):
|
|
215
|
+
statistics_overview = {}
|
|
216
|
+
output["statistics_overview"] = statistics_overview
|
|
217
|
+
statistics_overview["External Modules"] = len(correct_imported_modules)
|
|
184
218
|
finally:
|
|
185
219
|
if tmp_handle:
|
|
186
220
|
tmp_handle.cleanup()
|
|
@@ -190,6 +224,68 @@ async def filescan_wasm(input_path, nosec=False):
|
|
|
190
224
|
return {"Error": "Package not found on PyPI.org."}
|
|
191
225
|
|
|
192
226
|
|
|
227
|
+
# async def filescan_wasm(input_path, nosec=False):
|
|
228
|
+
# """
|
|
229
|
+
# WASM-compatible PyPI-only version of filescan function.
|
|
230
|
+
# Matches the behaviour of the original implementation for PyPI scans.
|
|
231
|
+
|
|
232
|
+
# PYPI PACKAGE ONLY (for now)
|
|
233
|
+
# """
|
|
234
|
+
# ca_version_info = version()
|
|
235
|
+
# now = datetime.datetime.now()
|
|
236
|
+
# timestamp_str = now.strftime("%Y-%m-%d %H:%M")
|
|
237
|
+
# output = ca_version_info | {"generated_on": timestamp_str}
|
|
238
|
+
# pypi_data = await get_pypi_download_info_wasm(input_path)
|
|
239
|
+
|
|
240
|
+
# if pypi_data:
|
|
241
|
+
# package_name = input_path
|
|
242
|
+
# url = pypi_data.get("download_url")
|
|
243
|
+
# release = pypi_data.get("release")
|
|
244
|
+
|
|
245
|
+
# if url is not None:
|
|
246
|
+
# # WASM-safe
|
|
247
|
+
# if IS_PYODIDE:
|
|
248
|
+
# decoded_res = await get_package_source_wasm(url)
|
|
249
|
+
# else:
|
|
250
|
+
# source_res = get_package_source(url)
|
|
251
|
+
|
|
252
|
+
# if inspect.isawaitable(source_res):
|
|
253
|
+
# decoded_res = await source_res
|
|
254
|
+
# else:
|
|
255
|
+
# decoded_res = source_res
|
|
256
|
+
# # Validation
|
|
257
|
+
# if decoded_res is None:
|
|
258
|
+
# return {
|
|
259
|
+
# "Error": f"Could not download or extract package from {url}. "
|
|
260
|
+
# f"This may be due to browser restrictions."
|
|
261
|
+
# }
|
|
262
|
+
|
|
263
|
+
# src_dir, tmp_handle = decoded_res
|
|
264
|
+
|
|
265
|
+
# # Match original structure EXACTLY
|
|
266
|
+
# output |= {
|
|
267
|
+
# "package_name": package_name,
|
|
268
|
+
# "package_release": release,
|
|
269
|
+
# }
|
|
270
|
+
|
|
271
|
+
# try:
|
|
272
|
+
# scan_output = _codeaudit_directory_scan_wasm(src_dir, nosec_flag=nosec)
|
|
273
|
+
# output |= scan_output
|
|
274
|
+
# # correct statistics for imported modules and modules count
|
|
275
|
+
# correct_imported_modules = package_imports(output)
|
|
276
|
+
# output["module_overview"]["imported_modules"] = correct_imported_modules
|
|
277
|
+
# output["statistics_overview"]["External Modules"] = len(
|
|
278
|
+
# correct_imported_modules
|
|
279
|
+
# )
|
|
280
|
+
# finally:
|
|
281
|
+
# if tmp_handle:
|
|
282
|
+
# tmp_handle.cleanup()
|
|
283
|
+
|
|
284
|
+
# return output
|
|
285
|
+
# # ---------------------------------------------------------
|
|
286
|
+
# return {"Error": "Package not found on PyPI.org."}
|
|
287
|
+
|
|
288
|
+
|
|
193
289
|
# - END of specific HELPERS to do CA things -#
|
|
194
290
|
|
|
195
291
|
|
|
@@ -213,13 +309,18 @@ loading = pn.indicators.LoadingSpinner(
|
|
|
213
309
|
value=False, size=60, color="primary", bgcolor="light", name="Scanning..."
|
|
214
310
|
)
|
|
215
311
|
|
|
312
|
+
placeholder = pn.pane.Markdown(
|
|
313
|
+
"*Run a scan to populate this tab.*",
|
|
314
|
+
sizing_mode="stretch_width",
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
overview_content = pn.Column(placeholder)
|
|
318
|
+
modules_content = pn.Column(placeholder)
|
|
319
|
+
complexity_content = pn.Column(placeholder)
|
|
320
|
+
weaknesses_content = pn.Column(placeholder)
|
|
321
|
+
weaknesses_files_content = pn.Column(placeholder)
|
|
322
|
+
weaknesses_details_content = pn.Column(placeholder)
|
|
216
323
|
|
|
217
|
-
overview_content = pn.Column()
|
|
218
|
-
modules_content = pn.Column()
|
|
219
|
-
complexity_content = pn.Column()
|
|
220
|
-
weaknesses_content = pn.Column()
|
|
221
|
-
weaknesses_files_content = pn.Column()
|
|
222
|
-
weaknesses_details_content = pn.Column()
|
|
223
324
|
|
|
224
325
|
tabs = pn.Tabs(
|
|
225
326
|
("Package Overview", overview_content),
|
|
@@ -259,7 +360,7 @@ async def run_scan(event):
|
|
|
259
360
|
|
|
260
361
|
try:
|
|
261
362
|
# ✅ Allow UI to update (spinner renders)
|
|
262
|
-
await asyncio.sleep(0.
|
|
363
|
+
await asyncio.sleep(0.5)
|
|
263
364
|
|
|
264
365
|
# ✅ WASM-safe: no threads, no nested event loops
|
|
265
366
|
result = await filescan_wasm(package_name, respect_marker)
|
|
@@ -310,7 +411,7 @@ async def run_scan(event):
|
|
|
310
411
|
]
|
|
311
412
|
|
|
312
413
|
except Exception as e:
|
|
313
|
-
status.object = f"❌
|
|
414
|
+
status.object = f"❌ Exception(!): {str(e)}"
|
|
314
415
|
|
|
315
416
|
finally:
|
|
316
417
|
# --- Reset UI state ---
|