Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
cc8cef1
feat: prepare bawbel-scanner for PyPI publishing (#1)
chaksaray Apr 18, 2026
26128b3
chore: remove stale root cli.py and setup.sh (moved to scanner/ and s…
chaksaray Apr 18, 2026
3ecabd4
feat: v0.1.0 — CONTRIBUTING, SECURITY, 15 rules, report command
chaksaray Apr 18, 2026
24afaf6
refactor: Remove cli.py and setup.sh (#5)
chaksaray Apr 18, 2026
b7ac389
Merge branch 'main' into develop
chaksaray Apr 18, 2026
48aac1d
Delete setup.sh
chaksaray Apr 18, 2026
02464a6
Delete cli.py
chaksaray Apr 18, 2026
e146376
Update CHANGELOG for version 0.1.0 release
chaksaray Apr 19, 2026
f372a19
docs: update CHANGELOG for v0.1.0 — 15 rules, 145 tests, full feature…
chaksaray Apr 19, 2026
855e00f
fix: TestPyPI gate before PyPI — requires manual approval (#11)
chaksaray Apr 19, 2026
2f58447
feat: add LiteLMM engine (#13)
chaksaray Apr 20, 2026
5129e07
Merge branch 'main' into develop
chaksaray Apr 20, 2026
22af2d4
feat: v0.2.0 — 15/15 AVE IDs, LiteLLM Stage 2, --watch, semgrep fix (…
chaksaray Apr 20, 2026
85780cc
Merge branch 'main' into develop
chaksaray Apr 20, 2026
c83700e
feat: hybrid sandbox (Hub pull + local fallback) (#18)
chaksaray Apr 23, 2026
7873477
feat: suppression — inline, block, .bawbelignore, --no-ignore, update…
chaksaray Apr 23, 2026
83e92de
feat: FP-1/2/3/4/5, Magika Stage 0, 24 AVE rules, bawbel init (#20)
chaksaray Apr 25, 2026
1256cc9
docs: add Magika Stage 0 and meta-analyzer to all documentation (#21)
chaksaray Apr 25, 2026
e598c5c
docs: v1.0.0 — 37 rules, 40 AVE records, IDE page, CI/CD split (#22)
chaksaray Apr 26, 2026
de732a5
fix: YARA engine SyntaxError on filenames with special characters (#23)
chaksaray Apr 26, 2026
558ca37
Merge branch 'main' into develop
chaksaray Apr 26, 2026
d956f85
fix: remove test one funding per rule (#26)
chaksaray Apr 26, 2026
38e3014
Merge branch 'main' into develop
chaksaray Apr 26, 2026
ff75b48
fix: not one rule per file (#28)
chaksaray Apr 26, 2026
5f3eb45
docs: Smithery top-100 scan results + scanner script (#32)
chaksaray Apr 30, 2026
a2981d0
feat: scan mcp server card (#34)
chaksaray May 1, 2026
9c9c220
feat: add bawbel pin + check-pins for rug pull detection (#35)
chaksaray May 3, 2026
9d2503e
Merge branch 'main' into develop
chaksaray May 3, 2026
a967a55
feat: map findings to OWASP MCP Top 10 (#37)
chaksaray May 3, 2026
8db1ea3
feat: toxic flow detection (#39)
chaksaray May 3, 2026
551c894
Merge branch 'main' into develop
chaksaray May 3, 2026
77ed21d
feat: MCP spec conformance scoring (#40)
chaksaray May 3, 2026
161d724
Merge branch 'main' into develop
chaksaray May 3, 2026
68e5137
docs: update README and CHANGELOG for v1.1.0 (#43)
chaksaray May 4, 2026
f8652f0
Merge branch 'main' into develop
chaksaray May 4, 2026
fdcfd2b
fix: tighten wheel verification checks in publish.yml (#45)
chaksaray May 4, 2026
16c19ee
feat: add server.json for MCP official registry submission (#47)
chaksaray May 6, 2026
2d78a11
Merge branch 'main' into develop
chaksaray May 6, 2026
46d97b3
docs: v1.1.1, add mcp-name marker for MCP registry submission (#49)
chaksaray May 6, 2026
160cfea
Merge branch 'main' into develop
chaksaray May 6, 2026
3aae1d7
feat: mapping OWASP AIVSS (#52)
chaksaray May 16, 2026
e9b1745
Merge branch 'main' into develop
chaksaray May 16, 2026
55470d2
feat: scan creds & chain (#54)
chaksaray May 16, 2026
1bdb8fa
Merge branch 'main' into develop
chaksaray May 16, 2026
a37a669
fix: risk score include toxic flow (#61)
chaksaray May 20, 2026
dec16f3
docs: publish scan smithery mcp servers result (#63)
chaksaray May 20, 2026
76ad1d2
chore: update readme and changelog for v1.2.2
chaksaray May 20, 2026
3829b9b
feat: update mcp v1.2.2 (#65)
chaksaray May 23, 2026
bea71c9
chore: add mcp-naem marker for MCP registry verification (#67)
chaksaray May 23, 2026
7f8bd3f
fix: conflict the bump version
chaksaray May 23, 2026
6f940f4
refactor: modular core and docs (#74)
chaksaray Jun 13, 2026
9e8f29c
chore: change pypi description
chaksaray Jun 13, 2026
511eb76
feat: confidence/evidence metadata, golden fixtures, v1.3.0 (Issues #…
chaksaray Jun 27, 2026
9292c2c
fix: conflict on the version
chaksaray Jun 27, 2026
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
24 changes: 24 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ BAWBEL_MAX_FILE_SIZE_MB=10
# Default: 30
BAWBEL_SCAN_TIMEOUT_SEC=30

# Minimum confidence score for a finding to pass FP-3 threshold check.
# The effective threshold depends on file profile (skill=0.60, mcp_manifest=0.55,
# documentation=0.85, unknown=0.60). This var overrides only the fallback threshold
# for files that don't match any named profile.
# Default: 0.80
# BAWBEL_CONFIDENCE_THRESHOLD=0.80


# ── Stage 2: LLM Semantic Analysis ───────────────────────────────────────────
# Requires: pip install "bawbel-scanner[llm]"
Expand Down Expand Up @@ -69,6 +76,23 @@ BAWBEL_SCAN_TIMEOUT_SEC=30
# BAWBEL_LLM_ENABLED=true


# ── FP-4: Meta-Analyzer ───────────────────────────────────────────────────────
# Requires: pip install "bawbel-scanner[llm]" (same dependency as Stage 2)
# Reviews medium-confidence findings (one LLM call per file) and reclassifies
# each as real (+0.15 confidence), needs_review (-0.05), or false_positive (suppressed).
# Skips automatically when no provider key is configured.

# Set to "false" to disable the LLM FP filter entirely
# Default: true
# BAWBEL_META_ANALYZER_ENABLED=true

# Confidence window — only findings within [MIN, MAX] are sent to the LLM.
# Findings above MAX are trusted as-is; findings below MIN are already suppressed.
# Default: 0.35 (min), 0.80 (max)
# BAWBEL_META_MIN_CONFIDENCE=0.35
# BAWBEL_META_MAX_CONFIDENCE=0.80


# ── Stage 3: Behavioral Sandbox ──────────────────────────────────────────────
# Requires: Docker Desktop or Docker Engine running
# Disabled by default — set BAWBEL_SANDBOX_ENABLED=true to enable.
Expand Down
139 changes: 69 additions & 70 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,73 @@ Versioning follows [Semantic Versioning](https://semver.org/).

---

## [1.3.0] - 2026-06-28

### Added

**Confidence and evidence metadata on every finding (Issue #69)**

Every `Finding` now carries four evidence fields populated at detection time:

- `confidence` — AVE-baseline confidence (0.0–1.0). Seeds from
`AVE_META[ave_id].confidence_baseline` when the engine fires, then adjusted by
FP-3 (score_confidence) and FP-4 (meta-analyzer). Always present in JSON output.
- `evidence_kind` — how evidence was gathered: `multi_engine`,
`tool_description_pattern`, `behavioral_pattern`, `semantic_inference`,
`file_type_mismatch`, or `config_schema`.
- `detection_stage` — `static_detection` or `runtime_observed`.
- `detection_layer` — `content`, `server_card`, `runtime`, or `registry_metadata`.

`ToxicFlow` gains a `confidence` field: `min(confidence_baseline)` across all
contributing findings, computed before the FP pipeline runs. Reflects raw detection
strength of the weakest link in the chain.

`scanner/ave_meta.py` is a new module with 51 `EveMeta` records (one per AVE ID
plus engine-specific overrides) providing `confidence_baseline`, `evidence_kind`,
`detection_stage`, and `detection_layer` for every known attack class. Engines that
produce no AVE match fall back to engine-type defaults.

**Golden JSON fixture for output contract stability (Issue #70)**

`tests/fixtures/golden/malicious_scan.json` is a committed snapshot of
`ScanResult.to_dict()` for the malicious fixture file. `TestGoldenSnapshot` in
`tests/unit/test_output_contracts.py` compares each live scan against the snapshot
to catch unintended schema changes. Regenerate the snapshot after intentional changes
with the command in the test module docstring.

25 schema contract tests lock: top-level field names, all 18 finding fields (including
the four new evidence fields), all 10 toxic flow fields, evidence kinds, detection
stages, confidence values, and risk score. YARA-dependent tests skip gracefully when
YARA is not installed.

**`confidence_band()` utility and evidence lifecycle documentation (Issue #71)**

`confidence_band(score)` in `scanner.core.fp_pipeline` maps a confidence score to
`"high"` (≥0.80), `"medium"` (0.55–0.79), or `"low"` (<0.55). Bands align with the
meta-analyzer window and profile thresholds.

`docs/guides/evidence-lifecycle.md` documents the full confidence pipeline: AVE
baseline → FP-2 negation → FP-3 scoring → threshold → FP-4 meta-analyzer →
`Finding.confidence`. Includes the ASCII flow diagram, FP-3 adjustment table,
`confidence_band()` tier table, pipeline ordering note, and lifecycle state reference.

34 evidence lifecycle tests cover: `confidence_band()` boundaries, all FP-3 context
adjustments (negation, table, heading, docs path, line number, cross-engine agreement,
skill name, AIVSS boost), threshold suppression per profile, all four meta-analyzer
verdict paths (`real`, `false_positive`, `needs_review`, no-provider skip), and
ToxicFlow confidence derivation.

### Fixed

- **LiteLLM Bedrock/SageMaker pre-load warnings** — two `WARNING` lines appeared on
every invocation (`could not pre-load bedrock-runtime response stream shape`) because
`logging.getLogger("LiteLLM").setLevel(logging.ERROR)` was called in `llm_engine.py`
*after* `import litellm`, giving litellm's module-level init code a window to log.
Fixed by setting the level at `meta_analyzer.py` module scope (runs at scanner import
time, before any lazy litellm import) and reordering the calls in `llm_engine.py`.

---

## [1.2.2] - 2026-05-20

### Fixed
Expand Down Expand Up @@ -113,75 +180,6 @@ Pattern engine: 37 rules -> 40 rules.

---

## [1.2.0] - 2026-05-16

### Added

**Justified suppression and false positive feedback (Part 14)**

Two new suppression keywords on top of the existing `bawbel-ignore` system:

- `bawbel-ignore` with metadata fields (`reason`, `reviewer`, `reviewed`) declares a
false positive permanently. The reason is recorded in the audit trail.
- `bawbel-accept` with an `expires` field declares an accepted risk. When the expiry
date passes, the finding resurfaces automatically as an active finding on the next scan.

`bawbel accept` CLI command inserts justified suppression comments directly into source
files. `bawbel accept --list` shows all accepted findings. `bawbel accept --expiring-soon`
shows findings expiring within a configurable window and exits 1 for CI use.

Anonymous FP signals can be sent to PiranhaDB via `--report`. Only AVE ID, engine,
confidence score, and a hash of the match context are sent. No file content.

`ScanResult.accepted_findings` is a new field in JSON output containing full metadata
for each justified suppression.

**New detection rules**

Three new AVE records and pattern rules:

- `bawbel-hook-hijack` (AVE-2026-00046): MCP tool hook hijacking. CRITICAL, AIVSS 9.1.
Detects skill files that register hooks to intercept or redirect tool execution calls.
- `bawbel-hardcoded-credential` (AVE-2026-00047): Hardcoded credentials. HIGH, AIVSS 7.8.
Detects API keys, tokens, passwords, private keys, and URL-embedded credentials.
- `bawbel-unsafe-delegation` (AVE-2026-00048): Unsafe agent delegation chain. HIGH, AIVSS 8.2.
Detects sub-agent spawning with inherited permissions and no trust boundary.

Pattern engine: 37 rules -> 40 rules.

**New commands**

- `bawbel creds <path>`: credential-focused scan, filters to AVE-2026-00047 and related
rules. Same output format as `bawbel scan`. Supports `--recursive`, `--no-ignore`,
`--fail-on-any`, `--format json`.
- `bawbel chain <path>`: delegation chain scanner, filters to AVE-2026-00048 and related
rules. Same flags as `bawbel creds`.

**`bawbel report` improvements**

- Added `--recursive` / `-r` flag. `bawbel report ./skills/ --recursive` generates
a full remediation report for every file in the directory.
- Added `--no-ignore` flag matching `bawbel scan`.

### Changed

- `scanner.py` Step 10 added: justified suppression runs after Step 9 (inline suppression).
Expired accepted risks are re-surfaced as active findings at this stage.
- Pattern engine rule count: 37 -> 40.

### Fixed

- `pr-review.yml` regression-check job: missing `pip install -e .` caused scan import
failures on clean repos.
- `ci.yml` test job: missing `pip install -e .` caused import failures.
- `ci.yml` Docker verify step: `python3 -c "..."` with f-strings caused shell brace
expansion to mangle the script before Python saw it. Replaced with single-line
assertion using no f-strings.
- `ci.yml` Docker verify step: wrong `aivss` field name (should be `aivss_score`),
wrong threshold (9.0 should be 7.0 to match actual fixture score).

---

## [1.1.1] - 2026-05-07

### Fixed
Expand Down Expand Up @@ -509,7 +507,8 @@ First public release.

---

[Unreleased]: https://github.com/bawbel/scanner/compare/v1.2.2...HEAD
[Unreleased]: https://github.com/bawbel/scanner/compare/v1.3.0...HEAD
[1.3.0]: https://github.com/bawbel/scanner/releases/tag/v1.3.0
[1.2.2]: https://github.com/bawbel/scanner/releases/tag/v1.2.2
[1.2.1]: https://github.com/bawbel/scanner/releases/tag/v1.2.1
[1.2.0]: https://github.com/bawbel/scanner/releases/tag/v1.2.0
Expand Down
12 changes: 6 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# docker run --rm bawbel/scanner:test
#
# production - minimal runtime image, non-root user, read-only fs
# docker build --target production -t bawbel/scanner:1.2.3 .
# docker run --rm -v $(pwd)/skills:/scan:ro bawbel/scanner:1.2.3 scan /scan
# docker build --target production -t bawbel/scanner:1.3.0 .
# docker run --rm -v $(pwd)/skills:/scan:ro bawbel/scanner:1.3.0 scan /scan
#
# Build args:
#
Expand All @@ -24,7 +24,7 @@
# ─────────────────────────────────────────────────────────────────────────────

ARG PYTHON_VERSION=3.12
ARG VERSION=1.2.3
ARG VERSION=1.3.0


# ── Base: shared system dependencies ──────────────────────────────────────────
Expand Down Expand Up @@ -101,7 +101,7 @@ CMD ["python", "-m", "pytest", "tests/", "-v", "--tb=short"]
# ── Production: minimal runtime image ─────────────────────────────────────────
FROM python:${PYTHON_VERSION}-slim AS production

ARG VERSION=1.2.3
ARG VERSION=1.3.0
ARG WITH_YARA=false
ARG WITH_SEMGREP=false
ARG WITH_LLM=false
Expand All @@ -117,7 +117,7 @@ LABEL org.opencontainers.image.title="Bawbel Scanner" \
org.opencontainers.image.vendor="Bawbel" \
org.opencontainers.image.documentation="https://bawbel.io/docs" \
bawbel.aivss.spec="0.8" \
bawbel.ave.records="45"
bawbel.ave.records="51"

WORKDIR /app

Expand Down Expand Up @@ -174,4 +174,4 @@ ENTRYPOINT ["python", "-m", "scanner.cli"]
# conform https://server.example.com
# pin /scan
# aibom /scan
CMD ["--help"]
CMD ["--help"]
Loading
Loading