diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..a72d9e3 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,47 @@ +name: Security + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + secret-detection: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: TruffleHog secret detection + uses: trufflesecurity/trufflehog@main + with: + extra_args: --results=verified,unknown + + sast: + runs-on: ubuntu-latest + container: + image: semgrep/semgrep + steps: + - uses: actions/checkout@v6 + + - name: Semgrep SAST + run: semgrep scan --error --config p/python --config p/bandit --config p/secrets . + + dependency-review: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + permissions: + contents: read + pull-requests: write + steps: + - uses: actions/checkout@v6 + + - name: Dependency review + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high diff --git a/src/vowl/contracts/check_reference_generated.py b/src/vowl/contracts/check_reference_generated.py index ef87e1d..7766b88 100644 --- a/src/vowl/contracts/check_reference_generated.py +++ b/src/vowl/contracts/check_reference_generated.py @@ -583,7 +583,8 @@ def count_where(*conditions: exp.Expression) -> exp.Expression: if pattern is None: # Fall through to JDK format pattern (validated in __init__) pattern = _jdk_format_to_regex(val) - assert pattern is not None # guaranteed by _validate_format + if pattern is None: + raise RuntimeError(f"_jdk_format_to_regex returned None for '{val}' — _validate_format should have rejected this") cast_col = exp.TryCast( this=col, to=exp.DataType.build("VARCHAR"), safe=True ) @@ -596,7 +597,8 @@ def count_where(*conditions: exp.Expression) -> exp.Expression: # date / timestamp / time — already validated in _validate_format pattern = _jdk_format_to_regex(val) - assert pattern is not None # guaranteed by _validate_format + if pattern is None: + raise RuntimeError(f"_jdk_format_to_regex returned None for '{val}' — _validate_format should have rejected this") cast_col = exp.TryCast( this=col, to=exp.DataType.build("VARCHAR"), safe=True ) diff --git a/src/vowl/contracts/models/generate_models.py b/src/vowl/contracts/models/generate_models.py index 1fd271e..d963d8b 100644 --- a/src/vowl/contracts/models/generate_models.py +++ b/src/vowl/contracts/models/generate_models.py @@ -21,7 +21,7 @@ # Bandit B404: This is a trusted, repository-maintained developer utility script # that intentionally invokes a local codegen CLI; subprocess is required here. -import subprocess # nosec B404 +import subprocess # nosec B404 # nosemgrep: gitlab.bandit.B404 import sys from pathlib import Path