Back to skill

Security audit

Csharp Developer

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent C#/.NET coding guidance skill, but users should review its security-sensitive examples before copying them into real projects.

Install only if you want a broad C#/.NET coding assistant. Before using generated output in production, review authentication secrets, rate limiting, database migrations, and bulk delete examples for secure secret storage, trusted client identity, backups, and explicit operational controls.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
references/aspnet-core.md:180
Finding
Insecure JWT Signing Secret Configuration Template## Vulnerability Details **File Location**: `references/aspnet-core.md`, lines 180-188 **Vulnerability Type**: Hardcoded and predictably weak cryptographic secret **Risk Level**: Medium ### Vulnerable Code ```json // appsettings.json { "JwtSettings": { "Secret": "your-secret-key", "Issuer": "your-app", "Audience": "your-audience", "ExpiryMinutes": 60 } } ``` ### Technical Analysis The documented configuration places a predictable JWT signing secret directly in an application settings file. Although the value appears to be a placeholder, the example does not direct users to retrieve the secret from an environment variable, development secret store, or managed production vault. Applications created by copying this template may retain the placeholder or replace it with a real secret that is subsequently committed to source control. The authentication example later derives a symmetric signing key from this value. Anyone who knows or can predict the secret can create JWTs with arbitrary identity, claim, or role values that pass signature validation, subject to the configured issuer and audience checks. ### Attack Path 1. A developer copies the documented JWT configuration into an application. 2. The application is deployed with the placeholder secret, another weak secret, or a production secret committed to source control. 3. An attacker obtains the key by guessing the documented value, reading leaked configuration, or accessing source-code history. 4. The attacker creates a JWT containing a chosen user identity and privileged claims such as an administrative role. 5. The attacker signs the token using the recovered symmetric key and supplies the expected issuer and audience. 6. The application accepts the forged token and authorizes requests according to the injected claims. ### Impact Assessment Successful exploitation can allow authentication bypass and impersonation of arbitrary us ...[truncated 332 chars]
Remediation
## Remediation Suggestions - Do not place JWT signing secrets or realistic placeholder values in committed configuration files. - Load production keys from a managed secret store such as Azure Key Vault, AWS Secrets Manager, HashiCorp Vault, or an equivalent platform facility. - Use .NET user-secrets only for local development and environment variables or workload identity for deployment-time configuration. - Generate a cryptographically random key with sufficient entropy for the selected algorithm. - Add startup validation that rejects missing, default, short, or known placeholder values. - Rotate any key that may have been committed or deployed, and invalidate tokens signed with the old key. - Prefer asymmetric signing where appropriate so token-verifying services do not require access to the private signing key. - Replace the example with a non-secret configuration reference and an explicit secure provisioning example.

T09 · Insecure Skill Coding Practices

Warning
Location
references/aspnet-core.md:356
Finding
Rate-Limit Bypass Through an Attacker-Controlled Host Partition Key## Vulnerability Details **File Location**: `references/aspnet-core.md`, lines 356-364 **Vulnerability Type**: Untrusted request data used as a rate-limit identity **Risk Level**: Medium ### Vulnerable Code ```csharp builder.Services.AddRateLimiter(options => { options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(context => RateLimitPartition.GetFixedWindowLimiter( partitionKey: context.User.Identity?.Name ?? context.Request.Headers.Host.ToString(), factory: partition => new FixedWindowRateLimiterOptions { AutoReplenishment = true, PermitLimit = 100, QueueLimit = 0, Window = TimeSpan.FromMinutes(1) })); }); ``` ### Technical Analysis Authenticated users are partitioned by username, but unauthenticated clients are partitioned using the HTTP `Host` header. The `Host` header identifies the requested virtual host; it is not a stable or trustworthy client identity. Where allowed-host validation or an upstream proxy does not strictly constrain this header, a remote requester can vary it and cause the rate limiter to create a new fixed-window bucket for each value. This defeats the intended global throttling policy for unauthenticated traffic. It can also create large numbers of limiter partitions, increasing memory consumption. The exploitability depends on deployment configuration: strict host filtering or a trusted reverse proxy that normalizes the header can reduce the bypass, but the skill template does not require either control. ### Attack Path 1. An attacker identifies an unauthenticated endpoint protected by the global limiter. 2. The attacker sends up to 100 requests using one accepted `Host` value. 3. After that partition reaches its limit, the attacker changes the `Host` header. 4. The application derives a different partition key and creates a fre ...[truncated 771 chars]
Remediation
## Remediation Suggestions - Do not use `Host`, `User-Agent`, or another client-controlled header as the unauthenticated rate-limit identity. - Partition unauthenticated requests by a validated client IP address or another trusted, stable identifier. - When deployed behind a reverse proxy, configure forwarded-header middleware with explicit trusted proxy or network ranges before consuming the resolved remote address. - Enforce a strict `AllowedHosts` configuration and validate hostnames at the reverse proxy and application layers. - Apply dedicated, stricter policies to authentication, password-reset, and account-enumeration endpoints. - Consider layered limits, including per-account, per-IP, and service-wide limits, so changing one identifier does not bypass all controls. - Monitor rejected requests and limiter partition cardinality, and bound the lifetime or number of dynamically created partitions where possible.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Vague Triggers

Medium
Confidence
91% confidence
Finding
The trigger list is very broad and mixes core C# terms with adjacent technologies such as MAUI, SignalR, and generic .NET concepts, without any explicit activation boundaries. This can cause the skill to be invoked in situations where a narrower or safer specialist would be more appropriate, increasing the chance of overreach, irrelevant guidance, or unintended influence over unrelated development tasks.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The example places a JWT signing secret in appsettings.json without any warning, which can lead readers to store long-lived signing keys in source-controlled or broadly accessible configuration. If that secret is exposed, an attacker can forge valid tokens and bypass authentication across the application.

External Transmission

Medium
Category
Data Exfiltration
Content
```csharp
builder.Services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>()
    .AddUrlGroup(new Uri("https://api.example.com/health"), "External API");

app.MapHealthChecks("/health");
```
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This markdown file includes an `ExecuteDeleteAsync` example that permanently deletes records matching `IsDeleted` without any accompanying warning about its destructive nature. The surrounding documentation presents it as a routine pattern and does not disclose that this operation is irreversible and affects persisted data.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The markdown shows `context.Database.MigrateAsync()` as a direct startup action but does not warn that it changes database schema and can affect system availability or data integrity. For documentation that describes behavior affecting persistent system state, the lack of a cautionary note is a missing user warning.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
Line L448 sets `<InvariantGlobalization>true</InvariantGlobalization>`, which can force the application to ignore user locale and language conventions. This is a natural-language policy concern because it imposes a locale-related constraint without documenting user choice or a region-specific justification.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The inline comment at L146 states 'Transient: new instance per request', which contradicts the actual behavior of services.AddTransient at L147. In ASP.NET Core DI, transient services are created each time they are resolved, whereas per-request lifetime corresponds to scoped services.

Static analysis

No suspicious patterns detected.