Security · Scan report

FixGrid Platform — Security Scan Report

Scan date: May 1, 2026  |  Environment: Production (app.fixgrid.app)  |  Codebase: 25,252 lines scanned
Download the latest security-assurance summary (PDF)
0
High Severity
0
Medium Severity
16
Low (All False Positives)
1
CVE Remediated
Overall posture: PASS. No High or Medium severity findings. One dependency CVE identified and remediated in this scan cycle. All Low findings are confirmed false positives documented below.

Scan 1 — Bandit (Static Application Security Testing)

Banditv1.9.4 · Python SAST scannerPASS

Bandit performs static analysis on Python source code, identifying common security issues including hardcoded credentials, injection risks, weak cryptography, and unsafe function calls.

Command: bandit -r routes models services utils -f txt -o bandit_report_app.txt

Scope: 25,252 lines across routes/, models/, services/, utils/  |  Files skipped: 0  |  #nosec suppressions: 0

SeverityCountStatus
High0CLEAR
Medium0CLEAR
Low16False Positives — documented below

B105 — Hardcoded Password String (6 findings)

B105 LOW "Pass" in inspection result label maps
Locations: models/gridvault/backflow_log.py:45, models/gridvault/boiler_inspection_log.py:49, models/gridvault/elevator_log.py:49, services/gridvault_backflow_log_service.py:140, services/gridvault_boiler_inspection_log_service.py:163, services/gridvault_elevator_log_service.py:171
Triage — False Positive: These are UI display label dictionaries mapping inspection outcomes to human-readable strings: 'pass': 'Pass', 'fail': 'Fail'. Bandit detects the string value "Pass" as a possible hardcoded password. These dicts contain no credentials, no tokens, and no secret material of any kind. Confirmed safe.

B110 — Try/Except/Pass (10 findings)

B110 LOW Silent exception handling on non-critical operations
Locations: routes/company_admin_assets_routes.py:631, routes/company_admin_core_routes.py:350 & 379, routes/company_admin_make_ready_routes.py:2106, routes/company_admin_pm_routes.py:48, routes/document_routes.py:284, routes/gridvault_routes.py:556, routes/inspection_routes.py:44 & 952, services/document_service.py:135
Triage — False Positive / Intentional Pattern: All 10 instances are intentional silent-failure patterns on secondary operations where a failure must never block the primary user action. Examples: (1) R2 cloud storage file deletion — a failed delete should not prevent a record from being removed from the database; (2) Stripe price retrieval — a billing API failure should not prevent the billing page from rendering; (3) compliance ticket auto-generation on page load — a failure should not crash the inspections or PM dashboard. This is an established application pattern per project standards. These are not swallowed exceptions masking logic errors.

Scan 2 — pip-audit (Dependency CVE Scan)

pip-auditv2.10.0 · PyPA CVE database1 CVE REMEDIATED

pip-audit scans all Python dependencies declared in requirements.txt against the PyPA advisory database and OSV.dev for known CVEs.

Command: pip-audit

PackageVersion ScannedCVEFix VersionScopeStatus
python-dotenv1.2.1CVE-2026-286841.2.2RuntimeREMEDIATED — upgraded to 1.2.2
pip25.0.1CVE-2025-886925.3Local Tooling OnlyNOT DEPLOYED — local dev tool, not on Render
pip25.0.1CVE-2026-170326.0Local Tooling OnlyNOT DEPLOYED — local dev tool, not on Render
pip25.0.1CVE-2026-3219No fix availableLocal Tooling OnlyNOT DEPLOYED — local dev tool, not on Render
Note on pip CVEs: The pip package is the Python package manager used on the development machine only. It is not included in the application's runtime dependencies deployed to Render. CVEs in pip carry no risk to the production application or its users.

Scan 3 — Safety (Dependency CVE Scan, Alternative Advisory Database)

Safety CLIv3.7.0 · Safety DB advisory databaseAUTHENTICATION REQUIRED

Safety scans Python dependencies against the Safety DB, a separate advisory database from pip-audit's PyPA source. Cross-scanning with two advisory databases catches CVEs that may appear in one source before the other.

Scan not completed: Safety CLI v3.7.0 now requires interactive login or an API key to run. The non-interactive scan was blocked by the authentication prompt. pip-audit (Scan 2) covers the same dependency surface using the PyPA/OSV advisory database. Safety will be re-run manually after authentication is configured, or replaced with safety scan --key <API_KEY> in the next CI pipeline update.

Scan Methodology & Cadence

ToolTypeCadenceAdvisory Source
BanditStatic Analysis (SAST)Before every push to productionCWE / Bandit ruleset
pip-auditDependency CVE scanBefore every push to productionPyPA Advisory DB / OSV.dev
SafetyDependency CVE scanAfter every major sprintSafety DB (separate advisory)
OWASP ZAPDynamic scan (DAST)Before beta user onboardsOWASP attack signatures
SemgrepSAST (Flask-specific rules)Planned — GitHub Actions CISemgrep community rulesets

Security Controls Summary

ControlImplementationStatus
CSRF ProtectionFlask-WTF CSRFProtect globally active. Explicit token on every POST form and AJAX request.ACTIVE
Tenant IsolationAll queries enforce company_id at the database query level. No post-fetch access checks.ACTIVE
AuthenticationFlask-Login session management. bcrypt password hashing. Invite-based user creation.ACTIVE
Rate LimitingFlask-Limiter on all unauthenticated public endpoints. Authenticated routes are not rate-limited.ACTIVE
Secret ManagementAll API keys and credentials via environment variables only. No hardcoded secrets in codebase.ACTIVE
Dependency Scanningpip-audit run before every production push. python-dotenv CVE-2026-28684 remediated this cycle.CURRENT
Transport SecurityHTTPS enforced via Cloudflare. All R2 assets served via CDN-backed custom domain (assets.fixgrid.app).ACTIVE
Permission ModelRole-based permissions with per-company override matrix. Module-level feature flags enforced at route level.ACTIVE
Generated by automated security scan pipeline · FixGrid Platform · May 1, 2026
Bandit 1.9.4 · pip-audit 2.10.0 · Safety 3.7.0 · Python 3.12 · Flask 3.1.3