This document describes the security measures, architecture, and best practices implemented in OpenCashFlow.
It is intended as a reference for contributors, auditors, and operators.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Internet / Users β
ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββ
β
ββββββββββΌβββββββββ
β HTTPS / TLS β β Encryption in transit
ββββββββββ¬βββββββββ
β
βββββββββββββββΌββββββββββββββββ
β Rate Limiting β β DDoS protection
βββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββ
β CORS Policy β β Crossβorigin control
βββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββ
β JWT Authentication β β User authentication
βββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββ
β RoleβBased Authorization β β Permission enforcement
βββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββ
β Business Logic β
βββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββ
β PostgreSQL Database β β Encryption at rest
βββββββββββββββββββββββββββββββ
Implementation: ASP.NET Core Identity + JWT
Example configuration (OpenCashFlow.API/Program.cs):
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = jwtSettings.Issuer,
ValidAudience = jwtSettings.Audience,
IssuerSigningKey = new SymmetricSecurityKey(...)
};
});Token Storage
- Stored in HTTPβonly cookies
- Not accessible from JavaScript (XSS mitigation)
Secureflag enabled in productionSameSitepolicy configured
Token Lifecycle
- Lifetime: configurable (default 24h)
- Refresh: manual (reβlogin required)
- Revocation: clientβside logout (serverβside blacklist not implemented)
Model
AspNetUserβ UserAspNetRoleβ Role (InstanceAdmin,CompanyAdmin,Employee)AspNetUserRoleβ User β Role mappingAspNetUserPermissionβ Explicit permissionsAspNetUserDeniedPermissionβ Explicitly denied permissions
Default Roles
- InstanceAdmin β Self-hosted instance administration and global maintenance.
- CompanyAdmin β Company/workspace administration, payments, staff, reports and configuration.
- Employee β Daily operational access inside a company/workspace.
Usage
[Authorize(Policy = "InstanceAdmin")]
public IActionResult InstanceAdminOnly() { }
[Authorize(Roles = "CompanyAdmin")]
public IActionResult CompanyAdminOnly() { }Implementation
- Each user belongs to a
CompanyviaCompany_Staff TenantIDstored in JWT claims- All queries are automatically filtered by tenant
Service Pattern
var tenantId = _authenticationService.GetTenantID();
var payments = await _repository.GetPaymentsAsync(tenantId, filters);Isolation Rules
- No crossβcompany queries
- Admin users may bypass isolation via explicit flags
Purpose
- SaaS-era Billing/Stripe access control is not part of the community core runtime.
Removed From Core Runtime
- Subscription authorization middleware
- Billing API endpoints
- Stripe webhook endpoints
- Stripe client registration
- Pricing, upgrade and customer portal UI
Legacy Schema
- Some historical plan, subscription and Stripe columns/tables may remain until a migration-backed cleanup.
- They must not be used to authorize access to dashboard, company, payments or cash.
- Any future external Billing module needs a separate threat model and security review.
Before a public release, run:
dotnet restore OpenCashFlow.sln
dotnet list OpenCashFlow.sln package --vulnerable --include-transitive
dotnet build OpenCashFlow.sln
dotnet test OpenCashFlow.sln --no-buildRelease builds must not ship with unresolved NU1902 or NU1903 advisories unless a documented exception exists.
The July 2026 dependency audit remediated:
AutoMapperfrom14.0.0to16.2.0.MailKitfrom4.12.1to4.17.0.MimeKitfrom4.12.0to4.17.0.- Removed unused
Microsoft.EntityFrameworkCore.Sqlitefrom the test project to eliminate the vulnerable transitiveSQLitePCLRaw.lib.e_sqlite3dependency.
SMTP remains optional. Password reset token creation must continue to work even when email delivery is not configured.
The .NET 10 migration updates the supported runtime baseline to:
net10.0for all core and test projects.- Microsoft ASP.NET Core, EF Core and Extensions packages
10.0.9. Npgsql.EntityFrameworkCore.PostgreSQL10.0.2.System.IdentityModel.Tokens.Jwt8.19.1.System.Linq.Dynamic.Core1.7.2.Microsoft.OpenApi2.10.0.Swashbuckle.AspNetCore10.2.3.
Swashbuckle.AspNetCore was upgraded across a major version because the .NET 10 OpenAPI graph otherwise resolved a vulnerable Microsoft.OpenApi package and was not source-compatible with the safe Microsoft.OpenApi 2.x namespace layout.
The WebApp emits security headers from OpenCashFlow.WebApp/Program.cs:
Content-Security-PolicyX-Frame-Options: DENYX-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originPermissions-Policy
The CSP uses a per-request nonce for Razor-rendered <script> and <style> elements through the WebApp CSP nonce tag helper. The policy intentionally avoids unsafe-inline and unsafe-eval. External script/style sources must be explicit; broad wildcard sources are not allowed.
Shared layout scripts/styles and several small auth page scripts have been moved into static assets. Some legacy Razor views still use nonce-backed inline blocks while they are migrated page by page; runtime CDN usage is explicitly limited and tracked in Docs/architecture/frontend-csp-cleanup.md.
The ZAP Baseline workflow parses JSON reports and fails on any non-accepted Medium/High finding. CSP findings are not allowlisted.
In Transit
- HTTPS/TLS 1.2+
- HSTS enabled in production
At Rest
- Passwords: hashed via ASP.NET Identity (PBKDF2)
- Database: encryption at rest (infrastructureβlevel)
- Secrets: stored in secure vaults or environment variables
Sensitive Data Rules
- β Never log passwords, tokens, or API keys
- β Never commit secrets to Git
- β Mask sensitive values in logs
- β Exclude sensitive fields from DTO serialization
Secret Rotation
- Rotate
JWT_SECRETimmediately after a suspected leak and force users to log in again. - Rotate database and SMTP credentials by changing the environment variables, restarting the services and revoking the old credentials at the provider/database layer.
- Treat reset tokens, fast-login cookies and PINs as credentials. They must not be logged or copied into support tickets.
Model Validation
[Required, EmailAddress]
public string Email { get; set; }
[Range(0, 999999)]
public decimal Amount { get; set; }SQL Injection
- Entity Framework parameterized queries
- Raw SQL only with parameters
XSS Protection
- Automatic Razor encoding
- CSP headers
- Avoid
Html.Rawunless sanitized
Logged Events
- User login / logout
- Administrative actions
- Subscription changes
- Securityβrelated events
- External webhook processing
Retention
- Configurable (default example: 90 days)
Examples
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: no-referrer
Permissions-Policy: geolocation=(), camera=(), microphone=()
Strict-Transport-Security: max-age=31536000; includeSubDomainsExample Limits
- Global: 100 requests/minute per user
- Authentication endpoints: stricter limits
- Companyβscoped API usage
Response
- HTTP 429 β Too Many Requests
Rules
- Explicit allowβlist of origins
- Credentials allowed
- No wildcard origins in production
Webhook Verification
- Signature validation required
- Idempotency enforced
- Duplicate event detection
Secrets Management
- Environment variables or secret vaults
- No secrets in source code
- MultiβFactor Authentication (TOTP)
- Advanced audit log storage
- Automated security alerts
- Anomaly detection on login patterns
- Isolate affected systems
- Revoke compromised credentials
- Analyze logs and scope
- Patch vulnerabilities
- Notify affected users if required
- Document and review the incident
- OWASP Top 10
- ASP.NET Core Security Documentation
- GDPR / Data Protection Regulations
Last updated: 2026β01β04
Maintained by: OpenCashFlow contributors
Review cycle: Quarterly