Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .bandit
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[bandit]
# Bandit configuration file
exclude_dirs = [
"tests",
"docs",
".git",
"__pycache__",
"build",
"dist"
]

# Skip specific test IDs
skips = [
"B101", # assert_used - OK in tests
"B601", # paramiko_calls - Not applicable
"B602", # subprocess_popen_with_shell_equals_true - Reviewed
]

# Test severity levels
tests = [
"B102", # exec_used
"B103", # set_bad_file_permissions
"B104", # hardcoded_bind_all_interfaces
"B105", # hardcoded_password_string
"B106", # hardcoded_password_funcarg
"B107", # hardcoded_password_default
"B108", # hardcoded_tmp_directory
"B110", # try_except_pass
"B112", # try_except_continue
"B201", # flask_debug_true
"B301", # pickle
"B302", # marshal
"B303", # md5
"B304", # des
"B305", # cipher
"B306", # mktemp_q
"B307", # eval
"B308", # mark_safe
"B309", # httpsconnection
"B310", # urllib_urlopen
"B311", # random
"B312", # telnetlib
"B313", # xml_bad_cElementTree
"B314", # xml_bad_ElementTree
"B315", # xml_bad_expatreader
"B316", # xml_bad_expatbuilder
"B317", # xml_bad_sax
"B318", # xml_bad_minidom
"B319", # xml_bad_pulldom
"B320", # xml_bad_etree
"B321", # ftplib
"B322", # input
"B323", # unverified_context
"B324", # hashlib_new_insecure_functions
"B325", # tempnam
"B401", # import_telnetlib
"B402", # import_ftplib
"B403", # import_pickle
"B404", # import_subprocess
"B405", # import_xml_etree
"B406", # import_xml_sax
"B407", # import_xml_expat
"B408", # import_xml_minidom
"B409", # import_xml_pulldom
"B410", # import_lxml
"B411", # import_xmlrpclib
"B412", # import_httpoxy
"B413", # import_pycrypto
"B501", # request_with_no_cert_validation
"B502", # ssl_with_bad_version
"B503", # ssl_with_bad_defaults
"B504", # ssl_with_no_version
"B505", # weak_cryptographic_key
"B506", # yaml_load
"B507", # ssh_no_host_key_verification
"B601", # paramiko_calls
"B602", # subprocess_popen_with_shell_equals_true
"B603", # subprocess_without_shell_equals_true
"B604", # any_other_function_with_shell_equals_true
"B605", # start_process_with_a_shell
"B606", # start_process_with_no_shell
"B607", # start_process_with_partial_path
"B608", # hardcoded_sql_expressions
"B609", # linux_commands_wildcard_injection
"B610", # django_extra_used
"B611", # django_rawsql_used
"B701", # jinja2_autoescape_false
"B702", # use_of_mako_templates
"B703", # django_mark_safe
]
52 changes: 52 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Pull Request

## Description
Brief description of the changes in this PR.

## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Security fix

## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] All tests pass locally
- [ ] Test coverage maintained/improved

## Security
- [ ] Security scan passed (Bandit)
- [ ] Dependency scan passed (Safety)
- [ ] No sensitive data exposed
- [ ] Input validation implemented

## Code Quality
- [ ] Code follows project style guidelines (Ruff)
- [ ] Self-review completed
- [ ] Type hints added for public APIs
- [ ] Docstrings added/updated

## Documentation
- [ ] README updated (if needed)
- [ ] API documentation updated
- [ ] CHANGELOG.md updated
- [ ] Breaking changes documented

## Checklist
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published

## Related Issues
Fixes #(issue number)

## Additional Notes
Any additional information that reviewers should know.
68 changes: 68 additions & 0 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: Security Scan

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 2 * * 1' # Weekly on Monday at 2 AM

jobs:
security-scan:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH

- name: Install dependencies
run: |
poetry install
pip install bandit safety semgrep

- name: Run Bandit security scan
run: |
bandit -r src/ -f json -o bandit-report.json || true
bandit -r src/ -f txt

- name: Run Safety check for vulnerabilities
run: |
safety check --json --output safety-report.json || true
safety check

- name: Run Semgrep security scan
run: |
semgrep --config=auto src/ --json --output=semgrep-report.json || true
semgrep --config=auto src/

- name: Upload security reports
uses: actions/upload-artifact@v4
if: always()
with:
name: security-reports
path: |
bandit-report.json
safety-report.json
semgrep-report.json

- name: Check for critical vulnerabilities
run: |
# Fail if critical vulnerabilities found
if [ -f safety-report.json ]; then
critical_count=$(jq '.vulnerabilities | length' safety-report.json 2>/dev/null || echo "0")
if [ "$critical_count" -gt 0 ]; then
echo "Critical vulnerabilities found: $critical_count"
exit 1
fi
fi
Loading