CWE-614: Sensitive Cookie Without 'Secure' Flag - C# / ASP.NET Core
Overview
The Secure attribute on a cookie instructs the browser to only transmit the cookie over encrypted HTTPS connections. Without it, the cookie is also sent over plaintext HTTP. If a user navigates to an HTTP version of a page (or is redirected to one by an attacker), the browser sends the session cookie in the clear, allowing a network-level attacker to steal it.
In ASP.NET Core, cookies are created without the Secure flag by default unless explicitly configured. This applies to all cookies: session cookies, authentication cookies created by ASP.NET Core Identity, and any cookies set via Response.Cookies.Append(). The fix requires setting the flag at both the individual cookie level and globally via CookiePolicyOptions.
Primary Defence: Set Secure = true on every CookieOptions and configure CookiePolicyOptions.Secure = CookieSecurePolicy.Always as a global default. Enable HTTPS redirection (UseHttpsRedirection()) and HSTS (UseHsts()) to ensure no session exists over HTTP.
Common Vulnerable Patterns
Cookie Without Secure Flag
// VULNERABLE - cookie transmitted over HTTP as well as HTTPS
Response.Cookies.Append("auth_token", tokenValue, new CookieOptions
{
HttpOnly = true,
SameSite = SameSiteMode.Strict,
// Secure is false by default - cookie will be sent over HTTP
});
Why this is vulnerable:
- Without
Secure = true, the browser sends theauth_tokencookie on HTTP requests too. An attacker on the same network (corporate Wi-Fi, ISP, or a man-in-the-middle) can capture it and impersonate the victim's session.
Session Configuration Without Secure Policy
// VULNERABLE - session cookie not flagged as Secure
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.HttpOnly = true;
// options.Cookie.SecurePolicy is not set - defaults to SameAsRequest
// (sends cookie over HTTP if the request came via HTTP)
});
Why this is vulnerable:
SameAsRequestmeans the cookie is only markedSecureif the request that created the session was HTTPS. During development or behind certain reverse proxies, this can result in session cookies being issued without theSecureflag.
Authentication Cookie Without Secure Policy
// VULNERABLE - authentication cookie may be sent over HTTP
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Strict;
// SecurePolicy not set - authentication cookie transmitted over HTTP
});
Why this is vulnerable:
- Authentication cookies contain or reference session credentials. Sending them over HTTP exposes them to passive network interception (e.g., network sniffing at public Wi-Fi).
Secure Patterns
Global Cookie Policy (Recommended)
// Program.cs - enforce Secure flag globally on ALL cookies
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.Secure = CookieSecurePolicy.Always; // Force Secure flag on every cookie
options.HttpOnly = HttpOnlyPolicy.Always; // Force HttpOnly on every cookie
options.MinimumSameSitePolicy = SameSiteMode.Strict;
});
var app = builder.Build();
app.UseHttpsRedirection(); // Redirect HTTP -> HTTPS
app.UseHsts(); // Instruct browsers to always use HTTPS (after first visit)
app.UseCookiePolicy(); // Apply the policy above
Why this works:
CookieSecurePolicy.Alwaysoverrides theSecureflag on every cookie, including those set by third-party middleware that may not set it themselves.UseHsts()instructs browsers to refuse HTTP connections after the first HTTPS visit.
Authentication Cookie
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // SECURE
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.Name = "__Host-Auth"; // __Host- prefix forces Secure + Path=/
options.SlidingExpiration = true;
options.ExpireTimeSpan = TimeSpan.FromHours(8);
});
Why this works:
CookieSecurePolicy.Alwaysensures theSecureattribute is always set. The__Host-cookie name prefix adds additional browser-enforced security: the browser will reject the cookie if it arrives withoutSecure, with aDomainattribute, or with aPathother than/.
Session Cookie
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
options.Cookie.SecurePolicy = CookieSecurePolicy.Always; // SECURE
options.Cookie.HttpOnly = true;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.IsEssential = true;
});
Manual Cookie with Full Security Options
// SECURE: explicit options on a manually set cookie
Response.Cookies.Append("preference", userPreference, new CookieOptions
{
Secure = true,
HttpOnly = true,
SameSite = SameSiteMode.Strict,
Expires = DateTimeOffset.UtcNow.AddDays(30),
Path = "/",
});
Why this works:
- Explicitly setting
Secure = trueprevents the flag from being omitted regardless of global policy. UsingSameSite = Strictalso prevents the cookie from being sent on cross-site requests, mitigating CSRF.
Remediation Steps
Locate the Finding
- Source: Any
Response.Cookies.Append()call,AddSession(),AddCookie(),AddAuthentication() - Sink:
CookieOptionsorCookieAuthenticationOptionswithoutSecure = trueorSecurePolicy = Always
Apply the Fix
- PRIORITY 1: Add
CookiePolicyOptions.Secure = CookieSecurePolicy.Alwaysandapp.UseCookiePolicy()inProgram.cs - PRIORITY 2: Update individual
CookieOptionsinstances to setSecure = trueexplicitly - PRIORITY 3: Enable
UseHttpsRedirection()andUseHsts()to ensure HTTPS is enforced end-to-end
Verify the Fix
- Use browser developer tools to inspect cookies; confirm
Secureflag is present on all session/auth cookies - In staging, navigate to the HTTP version of the app and confirm session cookies are not present
- Rescan with the security scanner to confirm the finding is resolved
Check for Similar Issues
Search for: CookieOptions, AddSession(, AddCookie(, Response.Cookies.Append( - check each for Secure/SecurePolicy
Testing
- Normal input: sign in over HTTPS and confirm authentication, session, and preference cookies continue to work.
- Boundary input: test staging and reverse-proxy deployments where
X-Forwarded-Protoor HTTPS termination affects request scheme detection. - Malicious input: browse the HTTP origin directly and inspect requests; sensitive cookies must not be sent without HTTPS.