
Research
GemStuffer Campaign Abuses RubyGems as Exfiltration Channel Targeting UK Local Government
GemStuffer abuses RubyGems as an exfiltration channel, packaging scraped UK council portal data into junk gems published from new accounts.
absolutealgorithm.api.common
Advanced tools
Reusable ASP.NET Core Web API infrastructure library. Configure once, get databases, storage, auth, resilience, docs, and more — wired automatically.
dotnet add package AbsoluteAlgorithm.Api.Common
Targets
net10.0. Bundles Dapper, Polly, NSwag, NLog, CsvHelper, and provider SDKs for S3, Azure Blob, GCP Storage, and MinIO.
var builder = WebApplication.CreateBuilder(args);
var appConfig = new ApplicationConfiguration
{
EnableRelationalDatabase = true,
DatabasePolicies =
[
new DatabasePolicy
{
Name = "primary",
DatabaseProvider = DatabaseProvider.PostgreSQL,
ConnectionStringName = "PRIMARY_DB_CONNECTION"
}
],
ConfigureAuthentication = true,
ConfigureAuthorization = true,
AuthManifest = new AuthManifest
{
EnableJwt = true,
EnableCookies = false
}
};
builder.RegisterAbsoluteWebApplicationBuilder(appConfig);
var app = builder.Build();
app.UseAbsolutePipeline(appConfig);
app.Run();
Two calls. That's it. The library validates config, registers services, and builds the middleware pipeline.
You can also bind from appsettings.json:
var appConfig = builder.Configuration
.GetSection("AbsoluteCommon")
.Get<ApplicationConfiguration>()
?? new ApplicationConfiguration();
Secrets are resolved from environment variables — not from config files.
| Variable | When Required |
|---|---|
JWT_SECRET (min 32 chars) | JWT auth enabled |
JWT_ISSUER, JWT_AUDIENCE | Optional (defaults: AbsoluteAlgorithm.Identity, AbsoluteAlgorithm.Apps) |
DatabasePolicy.ConnectionStringName | Per database policy |
StoragePolicy.ConnectionStringName | Per storage policy |
WebhookSignaturePolicy.SecretName | Per webhook policy |
AuthorizeKeyAttribute(secretName) | Per API key endpoint |
ConnectionStringNameandSecretNameare names of environment variables, not raw values.
All features are opt-in through the root configuration model.
| Property | Type | Purpose |
|---|---|---|
EnableRelationalDatabase | bool | Database + transaction middleware |
DatabasePolicies | List<DatabasePolicy>? | Named database registrations |
EnableStorage | bool | Object storage services |
StoragePolicies | List<StoragePolicy>? | Named storage registrations |
HttpClientPolicies | List<HttpClientPolicy>? | Named HTTP clients |
EnableApiVersioning | bool | API versioning |
ApiVersioningPolicy | ApiVersioningPolicy? | Versioning options |
EnableSwagger | bool | OpenAPI / Swagger |
SwaggerPolicy | SwaggerPolicy? | Swagger options |
EnableIdempotency | bool | Request replay protection |
IdempotencyPolicy | IdempotencyPolicy? | Idempotency options |
ConfigureAuthentication | bool | Auth handlers |
ConfigureAuthorization | bool | Authorization policies |
AuthManifest | AuthManifest? | Auth settings |
EnableWebhookSignatureValidation | bool | Webhook verification |
WebhookSignaturePolicies | List<WebhookSignaturePolicy>? | Webhook policies |
EnableRateLimit | bool | Rate limiting |
RateLimitPolicies | List<RateLimitPolicy>? | Rate limit policies |
EnableHealthChecks | bool | Health endpoints (default true) |
Dapper-based, request-scoped, transaction-aware repositories. Supports PostgreSQL and SQL Server.
new DatabasePolicy
{
Name = "primary",
DatabaseProvider = DatabaseProvider.PostgreSQL,
ConnectionStringName = "PRIMARY_DB_CONNECTION",
InitializeDatabase = true,
InitializeAuditTable = true,
InitializationScript = "CREATE TABLE IF NOT EXISTS ...",
MaxPoolSize = 100,
MinPoolSize = 10,
CommandTimeoutSeconds = 30,
ResiliencePolicy = new ResiliencePolicy
{
Retry = new RetryResiliencePolicy
{
MaxRetryAttempts = 3,
DelayStrategy = RetryDelayStrategy.Exponential,
DelayMilliseconds = 200,
BackoffMultiplier = 2
},
Timeout = new TimeoutResiliencePolicy { TimeoutSeconds = 30 },
CircuitBreaker = new CircuitBreakerResiliencePolicy
{
HandledEventsAllowedBeforeBreaking = 5,
DurationOfBreakSeconds = 30
}
}
}
public sealed class UsersService
{
private readonly Repository _repository;
public UsersService(IServiceProvider sp)
{
_repository = sp.GetRequiredKeyedService<Repository>("primary");
}
}
Prefer interpolated queries — values become parameters automatically:
var users = await _repository.QueryInterpolatedAsync<UserRow>(
$"SELECT id, email FROM users WHERE tenant_id = {tenantId} AND is_active = {true}",
cancellationToken: ct);
Raw SQL when needed:
var users = await _repository.QueryAsync<UserRow>(
"SELECT id, email FROM users WHERE tenant_id = @tenantId",
new { tenantId }, cancellationToken: ct);
Other methods: ExecuteAsync, ExecuteInterpolatedAsync, ExecuteStoredProcedureAsync, ExecuteScalarAsync.
Never let users provide SQL identifiers (table/column names). Only values are parameterized.
var query = new RepositoryPagedQuery
{
SelectSql = "SELECT u.id, u.email, u.display_name AS displayName FROM users u",
CountSql = "SELECT COUNT(1) FROM users u",
DefaultOrderBy = "u.updated_at DESC",
SortColumns = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["email"] = "u.email",
["displayName"] = "u.display_name"
},
FilterColumns = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["email"] = "u.email",
["status"] = "u.status"
},
SearchColumns = ["u.email", "u.display_name"]
};
var request = new PagedRequest
{
PageNumber = 1,
PageSize = 20,
SearchTerm = "lalith",
Sorts = [new SortDescriptor { Field = "email", Direction = SortDirection.Descending }],
Filters = [new FilterDescriptor { Field = "status", Operator = FilterOperator.Equals, Value = "active" }]
};
var result = await _repository.QueryPageAsync<UserListItem>(query, request, cancellationToken: ct);
// result.Items, result.TotalCount, result.TotalPages, result.HasNextPage, etc.
Clients send logical field names. SQL expressions stay server-owned via SortColumns/FilterColumns maps.
var definition = new RepositoryOptimisticUpdateDefinition
{
ResourceName = "user",
CurrentVersionSql = "SELECT version_token FROM users WHERE id = @id",
ExistsSql = "SELECT CASE WHEN EXISTS (SELECT 1 FROM users WHERE id = @id) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END",
UpdateSql = @"UPDATE users SET display_name = @displayName, version_token = @newVersionToken
WHERE id = @id AND version_token = @expectedVersionToken",
RequireIfMatchHeader = true
};
var result = await _repository.ExecuteOptimisticUpdateAsync(definition,
new { id, displayName, expectedVersionToken, newVersionToken }, cancellationToken: ct);
Throws E404 if not found, E409 on version mismatch, E412 if If-Match header is missing/stale.
DatabaseTransactionMiddleware manages request-scoped transactions automatically. All repository calls within one request share the same connection and transaction per named database. Commits on success, rolls back on failure.
The repository also sets provider session context for UserId and CorrelationId (useful for audit triggers).
Keyed StorageService per StoragePolicy.Name. Providers: MinIO, Azure Blob, GCP, S3.
new StoragePolicy
{
Name = "files",
StorageProvider = StorageProvider.S3,
ConnectionStringName = "S3_CONNECTION",
BucketName = "my-app-files",
GcpProjectId = "my-project" // only for GoogleCloud
}
var storage = sp.GetRequiredKeyedService<StorageService>("files");
// Upload
var objectName = await storage.UploadAsync(new FileContent
{
FileName = "photo.png",
ByteArrayContent = bytes,
ContentType = "image/png"
});
// Download URL
var url = await storage.GetDownloadUrlAsync(objectName, TimeSpan.FromMinutes(15));
Filenames are sanitized automatically. Extensions are preserved.
Named clients registered from HttpClientPolicy, resolved via IHttpClientFactory.
new HttpClientPolicy
{
Name = "github",
BaseAddress = "https://api.github.com/",
TimeoutSeconds = 30,
DefaultHeaders = new Dictionary<string, string> { ["User-Agent"] = "my-api" },
ResiliencePolicy = new ResiliencePolicy
{
Retry = new RetryResiliencePolicy
{
MaxRetryAttempts = 3,
DelayStrategy = RetryDelayStrategy.Linear,
DelayMilliseconds = 250,
DelayIncrementMilliseconds = 250
}
}
}
public sealed class GitHubClient(IHttpClientFactory factory)
{
private readonly HttpClient _http = factory.CreateClient("github");
public Task<string> GetRateLimitAsync(CancellationToken ct)
=> _http.GetStringAsync("rate_limit", ct);
}
Set ResiliencePolicy to non-null to enable Polly-backed resilience. Omit or set to null to disable.
HTTP resilience retries on: HttpRequestException, timeouts, 408, 429, 5xx.
Database resilience handles: DbException, timeouts, PostgreSQL transient errors, SQL Server deadlocks.
new ResiliencePolicy
{
Retry = new RetryResiliencePolicy // null = no retry
{
MaxRetryAttempts = 3, // default: 3
DelayStrategy = RetryDelayStrategy.Exponential, // Fixed | Linear | Exponential | CustomSchedule
DelayMilliseconds = 200, // base delay
DelayIncrementMilliseconds = 200, // for Linear
BackoffMultiplier = 2.0, // for Exponential
DelayScheduleMilliseconds = [200, 500, 1000] // for CustomSchedule
},
Timeout = new TimeoutResiliencePolicy // null = no timeout
{
TimeoutSeconds = 30
},
CircuitBreaker = new CircuitBreakerResiliencePolicy // null = no breaker
{
HandledEventsAllowedBeforeBreaking = 5,
DurationOfBreakSeconds = 30
}
}
new AuthManifest
{
EnableJwt = true,
EnableCookies = true,
EnableCsrfProtection = false,
EnableApiKeyAuth = true,
Policies =
[
new AuthPolicy { PolicyName = "AdminOnly", RequiredRoles = ["Admin"] },
new AuthPolicy { PolicyName = "PremiumUser", RequiredClaims = new() { ["subscription"] = "premium" } }
]
}
JWT: requires JWT_SECRET env var (min 32 chars). Defaults: issuer AbsoluteAlgorithm.Identity, audience AbsoluteAlgorithm.Apps.
Cookies: registers AbsoluteAuth cookie — HttpOnly, SameSite=Strict, Secure=Always, 7-day sliding expiry. Login redirects become 401.
Hybrid: when both JWT and cookies are enabled, a policy scheme (AbsoluteHybrid) picks JWT if Authorization: Bearer ... is present, cookies otherwise.
CSRF: only active when EnableCookies + EnableCsrfProtection are both true. Issues XSRF-TOKEN cookie on safe methods, validates x-csrf-token header on mutations. Bearer-only APIs don't need this.
[Authorize(Policy = "AdminOnly")]
[HttpGet("admin/report")]
public IActionResult GetReport() => Ok();
[AuthorizeKey("INTERNAL_API_KEY")] // reads env var, validates x-api-key header
[HttpPost("sync")]
public IActionResult Sync() => Ok();
[AuthorizeKey("PARTNER_KEY", "x-partner-key")] // custom header
Constant-time comparison. Returns 401 on failure. Respects [AllowAnonymous].
EnableRateLimit = true,
RateLimitPolicies =
[
new RateLimitPolicy
{
PolicyName = "login-limit",
Algorithm = RateLimitAlgorithm.FixedWindow, // FixedWindow | SlidingWindow | TokenBucket | Concurrency
Scope = RateLimitScope.IpAddress, // Global | IpAddress | User | Endpoint | ApiKey
PermitLimit = 5,
Window = TimeSpan.FromMinutes(1)
}
]
Additional properties for specific algorithms: SegmentsPerWindow (sliding), TokenLimit + TokensPerPeriod (token bucket).
Rejected requests get E429 with a standardized error response.
EnableIdempotency = true,
IdempotencyPolicy = new IdempotencyPolicy
{
HeaderName = "x-idempotency-key", // default
RequireHeader = true,
ReplayableMethods = ["POST", "PUT", "PATCH"],
ExpirationMinutes = 60,
MaximumResponseBodyBytes = 64 * 1024,
IncludeQueryStringInKey = false
}
Client sends x-idempotency-key: ord_001. If a matching successful response exists, it's replayed with x-idempotency-replayed: true. In-flight duplicates get E409.
Cache key = method + path + subject (user ID / IP) + idempotency key.
Default store: InMemoryIdempotencyStore. Implement IIdempotencyStore for distributed support.
EnableWebhookSignatureValidation = true,
WebhookSignaturePolicies =
[
new WebhookSignaturePolicy
{
Name = "stripe",
PathPrefix = "/webhooks/stripe",
SecretName = "STRIPE_WEBHOOK_SECRET",
SignatureHeaderName = "stripe-signature",
TimestampHeaderName = "x-signature-timestamp",
Algorithm = RequestSignatureAlgorithm.HmacSha256, // or HmacSha512
AllowedClockSkewSeconds = 300
}
]
Middleware validates signature + timestamp for matching path prefixes. Failures return E401.
RequestSignatureUtility exposes GenerateTimestamp, ComputeSignature, VerifySignature for manual use.
EnableApiVersioning = true,
ApiVersioningPolicy = new ApiVersioningPolicy
{
DefaultMajorVersion = 1,
DefaultMinorVersion = 0,
Readers = [ApiVersionReaderType.Header, ApiVersionReaderType.QueryString],
HeaderNames = ["x-api-version"],
QueryStringParameterName = "api-version",
AssumeDefaultVersionWhenUnspecified = true,
ReportApiVersions = true,
EnableApiExplorer = true,
GroupNameFormat = "'v'VVV",
SubstituteApiVersionInUrl = true
}
Reader types: QueryString, Header, MediaType, UrlSegment. Can be combined.
EnableSwagger = true,
SwaggerPolicy = new SwaggerPolicy
{
Title = "My API",
Description = "API documentation",
DocumentMode = SwaggerDocumentMode.Single, // or PerApiVersion
SingleDocumentName = "v1",
SingleDocumentVersion = "1.0",
OpenApiPath = "/swagger/{documentName}/swagger.json",
SwaggerUiPath = "/swagger",
UseSwaggerUi = true,
PersistAuthorization = true,
EnableTryItOut = true,
Headers =
[
new SwaggerHeaderDefinition
{
Name = "x-tenant-id",
Description = "Tenant key",
Required = true,
AuthorizedOnly = true
}
]
}
For per-version docs:
DocumentMode = SwaggerDocumentMode.PerApiVersion,
Documents =
[
new SwaggerDocumentDefinition { DocumentName = "v1", ApiGroupName = "v1", Version = "1.0", Title = "API v1" },
new SwaggerDocumentDefinition { DocumentName = "v2", ApiGroupName = "v2", Version = "2.0", Title = "API v2" }
]
Automatically adds bearer/cookie/API key security definitions based on your auth config. Lock icons only appear on endpoints that actually require auth.
Enabled by default (EnableHealthChecks = true). Default endpoint: /health.
Auto-registers checks for: self, PostgreSQL, SQL Server, MinIO, Azure Blob, S3, GCP Storage — based on your configured policies.
All errors use a standard envelope:
{
"isSuccess": false,
"error": {
"errorCode": "E422",
"errorMessage": "The Email field is required.",
"validationErrors": [
{ "field": "email", "messages": ["The Email field is required."] }
]
}
}
Successful responses:
{
"isSuccess": true,
"data": { ... }
}
throw ApiExceptions.Notfound("user");
throw ApiExceptions.Badrequest("Invalid input");
throw ApiExceptions.Conflict("Duplicate entry");
throw ApiExceptions.Unauthorized;
throw ApiExceptions.Forbidden;
throw ApiExceptions.PreconditionFailed("Version mismatch");
throw ApiExceptions.FromCode("E410", "Resource gone");
E400 bad request · E401 unauthorized · E403 forbidden · E404 not found · E409 conflict · E410 gone · E412 precondition failed · E422 unprocessable · E429 rate limited · E499 cancelled · E500 internal error
ValidateModelFilter runs globally. Returns E400 for malformed JSON, E422 for validation failures — using the standard envelope above.
UseAbsolutePipeline wires everything in this order:
GET / root endpointpublic interface ICurrentUserAccessor
{
ClaimsPrincipal? Principal { get; }
string? UserId { get; }
string? Email { get; }
bool IsAuthenticated { get; }
IReadOnlyList<string> Roles { get; }
}
Provides RequestMetadata with: CorrelationId, UserId, TenantId, IdempotencyKey, ClientIpAddress, UserAgent, Path, Method, IsAuthenticated.
Standalone helpers — usable even outside the pipeline.
| Utility | Purpose |
|---|---|
AuthUtility | Create claims/identities/principals, cookie sign-in/out, secure cookies |
ClaimUtility | Read user ID, email, roles from ClaimsPrincipal |
TokenUtility | Generate tokens, API keys, JWTs, numeric codes, constant-time compare |
HashingUtility | SHA-256/SHA-512 from strings, bytes, streams, base64 |
PasswordUtility | Hash and verify passwords |
EncryptionUtility | AES symmetric encrypt/decrypt |
AsymmetricKeyUtility | RSA/ECDsa key generation and digital signatures |
RequestSignatureUtility | HMAC request signing and verification |
ETagUtility | Strong/weak ETags, If-Match/If-None-Match |
OptimisticConcurrencyUtility | Version tokens, ETag matching, 304 Not Modified |
CsvUtility | Read/write CSV with spreadsheet-formula safety |
DateTimeUtility | UTC normalization, Unix time conversion |
FileUtility | Extensions, content types, file size formatting |
HttpUtility | Header extraction, bearer token, IP, correlation ID, query strings |
JsonUtility | Serialize/deserialize with consistent options |
ReflectionUtility | Property discovery helpers |
EnumUtility | Safe parsing, names, values, IsDefined |
CompressionUtility | GZip and Brotli compress/decompress |
SlugUtility | URL-safe slug generation |
SpreadsheetFormulaSanitizer — prefixes a single quote when strings start with =, +, -, @, tab, CR, or LF. Applied automatically to incoming JSON strings and model-bound values.
FileNameSanitizer — strips unsafe path/filename characters. Used automatically by StorageService.
ApplicationConfiguration in C#var appConfig = new ApplicationConfiguration
{
EnableRelationalDatabase = true,
DatabasePolicies =
[
new DatabasePolicy
{
Name = "primary",
DatabaseProvider = DatabaseProvider.PostgreSQL,
ConnectionStringName = "PRIMARY_DB_CONNECTION",
InitializeDatabase = false,
InitializeAuditTable = false,
CommandTimeoutSeconds = 30,
MaxPoolSize = 100,
MinPoolSize = 10,
ResiliencePolicy = new ResiliencePolicy
{
Retry = new RetryResiliencePolicy
{
MaxRetryAttempts = 3,
DelayStrategy = RetryDelayStrategy.Exponential,
DelayMilliseconds = 200,
BackoffMultiplier = 2
},
Timeout = new TimeoutResiliencePolicy { TimeoutSeconds = 30 },
CircuitBreaker = new CircuitBreakerResiliencePolicy
{
HandledEventsAllowedBeforeBreaking = 5,
DurationOfBreakSeconds = 30
}
}
}
],
EnableStorage = true,
StoragePolicies =
[
new StoragePolicy
{
Name = "files",
StorageProvider = StorageProvider.S3,
ConnectionStringName = "S3_CONNECTION",
BucketName = "my-app-files"
}
],
HttpClientPolicies =
[
new HttpClientPolicy
{
Name = "github",
BaseAddress = "https://api.github.com/",
TimeoutSeconds = 30,
DefaultHeaders = new Dictionary<string, string> { ["User-Agent"] = "my-api" },
ResiliencePolicy = new ResiliencePolicy
{
Retry = new RetryResiliencePolicy
{
MaxRetryAttempts = 3,
DelayStrategy = RetryDelayStrategy.Linear,
DelayMilliseconds = 250,
DelayIncrementMilliseconds = 250
}
}
}
],
ConfigureAuthentication = true,
ConfigureAuthorization = true,
AuthManifest = new AuthManifest
{
EnableJwt = true,
EnableCookies = false,
EnableCsrfProtection = false,
EnableApiKeyAuth = true,
Policies =
[
new AuthPolicy { PolicyName = "AdminOnly", RequiredRoles = ["Admin"] },
new AuthPolicy
{
PolicyName = "PremiumUser",
RequiredClaims = new Dictionary<string, string> { ["subscription"] = "premium" }
}
]
},
EnableRateLimit = true,
RateLimitPolicies =
[
new RateLimitPolicy
{
PolicyName = "default",
Algorithm = RateLimitAlgorithm.FixedWindow,
Scope = RateLimitScope.IpAddress,
PermitLimit = 100,
Window = TimeSpan.FromMinutes(1)
}
],
EnableIdempotency = true,
IdempotencyPolicy = new IdempotencyPolicy
{
RequireHeader = true,
ExpirationMinutes = 60
},
EnableApiVersioning = true,
ApiVersioningPolicy = new ApiVersioningPolicy
{
Readers = [ApiVersionReaderType.Header],
HeaderNames = ["x-api-version"],
DefaultMajorVersion = 1,
DefaultMinorVersion = 0,
EnableApiExplorer = true
},
EnableSwagger = true,
SwaggerPolicy = new SwaggerPolicy
{
Title = "My API",
Description = "Service API documentation",
Headers =
[
new SwaggerHeaderDefinition
{
Name = "x-tenant-id",
Description = "Tenant partition key",
Required = false,
AuthorizedOnly = false
}
]
},
EnableWebhookSignatureValidation = true,
WebhookSignaturePolicies =
[
new WebhookSignaturePolicy
{
Name = "stripe",
PathPrefix = "/webhooks/stripe",
SecretName = "STRIPE_WEBHOOK_SECRET"
}
]
};
appsettings.json{
"AbsoluteCommon": {
"enableRelationalDatabase": true,
"databasePolicies": [
{
"name": "primary",
"databaseProvider": "PostgreSQL",
"connectionStringName": "PRIMARY_DB_CONNECTION",
"maxPoolSize": 100,
"commandTimeoutSeconds": 30,
"resiliencePolicy": {
"retry": {
"maxRetryAttempts": 3,
"delayStrategy": "Exponential",
"delayMilliseconds": 200,
"backoffMultiplier": 2.0
},
"timeout": { "timeoutSeconds": 30 },
"circuitBreaker": {
"handledEventsAllowedBeforeBreaking": 5,
"durationOfBreakSeconds": 30
}
}
}
],
"enableStorage": true,
"storagePolicies": [
{
"name": "files",
"storageProvider": "S3",
"connectionStringName": "S3_CONNECTION",
"bucketName": "my-app-files"
}
],
"httpClientPolicies": [
{
"name": "github",
"baseAddress": "https://api.github.com/",
"timeoutSeconds": 30,
"defaultHeaders": { "User-Agent": "my-api" },
"resiliencePolicy": {
"retry": {
"maxRetryAttempts": 3,
"delayStrategy": "Linear",
"delayMilliseconds": 250,
"delayIncrementMilliseconds": 250
}
}
}
],
"configureAuthentication": true,
"configureAuthorization": true,
"authManifest": {
"enableJwt": true,
"enableCookies": false,
"enableApiKeyAuth": true,
"policies": [
{ "policyName": "AdminOnly", "requiredRoles": ["Admin"] }
]
},
"enableRateLimit": true,
"rateLimitPolicies": [
{
"policyName": "default",
"algorithm": "FixedWindow",
"scope": "IpAddress",
"permitLimit": 100,
"window": "00:01:00"
}
],
"enableIdempotency": true,
"idempotencyPolicy": {
"requireHeader": true,
"expirationMinutes": 60
},
"enableApiVersioning": true,
"apiVersioningPolicy": {
"readers": ["Header"],
"headerNames": ["x-api-version"],
"enableApiExplorer": true
},
"enableSwagger": true,
"swaggerPolicy": {
"title": "My API",
"description": "Service API documentation"
},
"enableWebhookSignatureValidation": true,
"webhookSignaturePolicies": [
{
"name": "stripe",
"pathPrefix": "/webhooks/stripe",
"secretName": "STRIPE_WEBHOOK_SECRET"
}
]
}
}
QueryInterpolatedAsync / ExecuteInterpolatedAsync over raw SQL for value safety.AuthorizeKeyAttribute for machine-to-machine endpoints.IIdempotencyStore.InitializeDatabase = false.JWT_SECRET strong and rotated.FAQs
Unknown package
We found that absolutealgorithm.api.common demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
GemStuffer abuses RubyGems as an exfiltration channel, packaging scraped UK council portal data into junk gems published from new accounts.

Company News
Socket was named to the Rising in Cyber 2026 list, recognizing 30 private cybersecurity startups selected by CISOs and security executives.

Research
Socket detected 84 compromised TanStack npm package artifacts modified with suspected CI credential-stealing malware.