Security Surface and Penetration Tests
Penetration-style tests of the HTTP surface: identity, session handling, antiforgery, permissions and hostile-input hardening.
Identity
PenTestEntityAnalysisModelRole
Jube.Test.Security.Identity.PenTestEntityAnalysisModelRole — 6 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
CrossTenant_ListGrantAndRevoke_BehaveLikeNotFoundAsync |
Fact | Cross tenant list grant and revoke behave like not found. |
MassAssignment_OnCreate_IsIgnoredAsync |
Fact | Mass assignment on create is ignored. |
Lifecycle_DoubleRevoke_AndRegrant_AreOrderlyAsync |
Fact | Lifecycle double revoke and regrant are orderly. |
Injection_InGuidsAndRoutes_IsInertAsync |
Fact | Injection in guids and routes is inert. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
PenTestEntityAnalysisModelSynchronisationSchedule
Jube.Test.Security.Identity.PenTestEntityAnalysisModelSynchronisationSchedule — 7 tests. Category: PenTest.
Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
Schedules_AreScopedToTheCallersTenant_EvenWithForgedFieldsAsync |
Fact | Schedules are scoped to the callers tenant even with forged fields. |
ScheduleDates_AreBounded_AndNeverServerErrorAsync |
Fact | Schedule dates are bounded and never server error. |
RapidScheduling_IsBounded_AndEveryResponseIsPromptAsync |
Fact | Rapid scheduling is bounded and every response is prompt. |
ResponseShape_HasNoInternalsAsync |
Fact | Response shape has no internals. |
Injection_InQueryAndBody_IsInertAsync |
Fact | Injection in query and body is inert. |
TypeConfusion_AndMalformedBodies_NeverServerErrorAsync |
Fact | Type confusion and malformed bodies never server error. |
PenTestExhaustiveSearchInstancePromotedTrialInstance
Jube.Test.Security.Identity.PenTestExhaustiveSearchInstancePromotedTrialInstance — 5 tests. Category: PenTest.
Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Fact | Matrix is enforced per permission. |
CrossTenant_PromotionSwitch_BehavesLikeNotFoundAsync |
Fact | Cross tenant promotion switch behaves like not found. |
MassAssignment_OnlyTheActiveFlagChangesAsync |
Fact | Mass assignment only the active flag changes. |
InvalidIdsAndBodies_AreRejectedAsync |
Fact | Invalid ids and bodies are rejected. |
Injection_InRouteQueryAndBody_IsInertAsync |
Fact | Injection in route query and body is inert. |
PenTestPermissionSpecification
Jube.Test.Security.Identity.PenTestPermissionSpecification — 5 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Fact | Matrix is enforced per permission. |
Catalogue_ExposesOnlyIdAndName_AndTheSameCatalogueToEveryTenantAsync |
Fact | Catalogue exposes only id and name and the same catalogue to every tenant. |
WriteVerbs_AreNotSupported_AndTheCatalogueIsUnchangedAsync |
Fact | Write verbs are not supported and the catalogue is unchanged. |
Injection_InQueryString_IsInertAsync |
Fact | Injection in query string is inert. |
OddRequestShapes_AreOrderlyAsync |
Fact | Odd request shapes are orderly. |
PenTestPreservation
Jube.Test.Security.Identity.PenTestPreservation — 13 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_ExportRoutes_AreEnforcedPerPermissionAsync |
Theory | Matrix export routes are enforced per permission. |
Matrix_Import_IsRefusedForEveryoneWithoutPermission38Async |
Fact | Matrix import is refused for everyone without permission38. |
Export_ContainsOnlyTheCallersTenantAsync |
Fact | Export contains only the callers tenant. |
Export_UsesThePasswordAsTheKey_AndNeverContainsClearTextAsync |
Fact | Export uses the password as the key and never contains clear text. |
ExportPeek_IsScopedTextAndRejectsHostileQueriesAsync |
Fact | Export peek is scoped text and rejects hostile queries. |
Export_TypeConfusionAndInjection_AreRejectedOrInertAsync |
Fact | Export type confusion and injection are rejected or inert. |
Import_TamperedTruncatedAndGarbagePackages_AreRefusedWithoutChangingTheTenantAsync |
Fact | Import tampered truncated and garbage packages are refused without changing the tenant. |
Import_WrongMissingAndHostilePasswords_AreRefusedAsync |
Fact | Import wrong missing and hostile passwords are refused. |
Import_MultipartStructureAttacks_AreRefusedAsync |
Fact | Import multipart structure attacks are refused. |
Import_FileNames_AreNeverUsedAsPathsAsync |
Fact | Import file names are never used as paths. |
Import_OversizedUploads_AreBoundedAndRefusedAsync |
Fact | Import oversized uploads are bounded and refused. |
Import_CrossSitePosts_AreRefused_EvenWithValidCredentialsAsync |
Fact | Import cross site posts are refused even with valid credentials. |
Import_OfAnotherTenantsExport_CannotBeUsedToWriteIntoThisTenantAsync |
Fact | Import of another tenants export cannot be used to write into this tenant. |
PenTestRoleRegistry
Jube.Test.Security.Identity.PenTestRoleRegistry — 10 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
CrossTenant_ReadUpdateAndDelete_BehaveLikeNotFoundAsync |
Fact | Cross tenant read update and delete behave like not found. |
MassAssignment_OnCreateAndUpdate_IsIgnoredAsync |
Fact | Mass assignment on create and update is ignored. |
LockedRole_CannotBeUpdatedOrDeleted_AndDeletedRoleIsGoneAsync |
Fact | Locked role cannot be updated or deleted and deleted role is gone. |
DuplicateName_InSameTenant_IsRefused_ButAllowedAcrossTenantsAsync |
Fact | Duplicate name in same tenant is refused but allowed across tenants. |
Injection_InName_IsStoredAsDataOrRejectedAsync |
Fact | Injection in name is stored as data or rejected. |
Injection_InRouteAndQuery_IsInertAsync |
Fact | Injection in route and query is inert. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
DeletingARoleInUse_DoesNotBreakTheUserRoutes_AndIsNotServerErrorAsync |
Fact | Deleting a role in use does not break the user routes and is not server error. |
ConcurrentConflictingWrites_NeverServerErrorAsync |
Fact | Concurrent conflicting writes never server error. |
PenTestRoleRegistryPermission
Jube.Test.Security.Identity.PenTestRoleRegistryPermission — 9 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
OnlyPermission34_CannotGrantPermissions_AndOnlyPermission36_CannotManageUsersAsync |
Fact | Only permission34 cannot grant permissions and only permission36 cannot manage users. |
CrossTenant_ReadUpdateDeleteAndGrant_BehaveLikeNotFoundAsync |
Fact | Cross tenant read update delete and grant behave like not found. |
InvalidAndDuplicateSpecifications_AreRefusedAsync |
Fact | Invalid and duplicate specifications are refused. |
MassAssignment_OnCreateAndUpdate_IsIgnoredAsync |
Fact | Mass assignment on create and update is ignored. |
LockedPermission_CannotBeChangedOrDeleted_AndLifecycleIsOrderlyAsync |
Fact | Locked permission cannot be changed or deleted and lifecycle is orderly. |
GrantedPermission_TakesEffectOnlyForTheGrantedRolesUsersAsync |
Fact | Granted permission takes effect only for the granted roles users. |
Injection_InRouteQueryAndBodyNumbers_IsInertAsync |
Fact | Injection in route query and body numbers is inert. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
PenTestSanctionEntrySource
Jube.Test.Security.Identity.PenTestSanctionEntrySource — 4 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
List_IsLandlordOnlyAsync |
Fact | List is landlord only. |
Import_IsRefusedForEveryNonLandlord_AndWritesNothingAsync |
Fact | Import is refused for every non landlord and writes nothing. |
LandlordImport_WithInvalidInput_IsRefusedWithoutWritingAsync |
Fact | Landlord import with invalid input is refused without writing. |
VerbsAndQueries_AreInertAsync |
Fact | Verbs and queries are inert. |
PenTestSessionAndRequestHardening
Jube.Test.Security.Identity.PenTestSessionAndRequestHardening — 15 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
CR01_ChunkedBody_GetsTheSameNulAndNonFiniteInspectionAsAContentLengthBodyAsync |
Theory | CR 01 chunked body gets the same nul and non finite inspection as a content length body. |
CR01_ChunkedBodyOverTheCap_Is413_AndAnEmptyChunkedBodyIs400Async |
Fact | CR 01 chunked body over the cap is413 and an empty chunked body is400. |
CR01_ChunkedBody_IsStillRefusedToTheUnauthorised_BeforeAnythingIsBufferedAsync |
Fact | CR 01 chunked body is still refused to the unauthorised before anything is buffered. |
CR05_ASessionOlderThanTheAbsoluteLifetime_IsRefusedEvenWithAFreshExpiryAsync |
Fact | CR 05 a session older than the absolute lifetime is refused even with a fresh expiry. |
CR05_TheAbsoluteLifetime_IsConfigurable_AndTheSessionStartSurvivesRefresh |
Fact | CR 05 the absolute lifetime is configurable and the session start survives refresh. |
CR05_ARevokedCookie_IsNeverRefreshedIntoAFreshOneAsync |
Fact | CR 05 a revoked cookie is never refreshed into a fresh one. |
CR06_ALockedInactiveOrDeletedUser_LosesAnExistingSession_AndKeepsNoneAfterwardsAsync |
Theory | CR 06 a locked inactive or deleted user loses an existing session and keeps none afterwards. |
CR06_TheLandlordLookup_RespectsLockedAndDeletedUsersAsync |
Theory | CR 06 the landlord lookup respects locked and deleted users. |
CR13_OpenConnections_OfRevokedLockedAndExpiredSessions_AreClosed_OthersStayOpenAsync |
Fact | CR 13 open connections of revoked locked and expired sessions are closed others stay open. |
CR13_TheSweeperIsANoOp_WhenNothingIsConnectedAsync |
Fact | CR 13 the sweeper is a no op when nothing is connected. |
CR16_CredentialCookies_AreSecureWheneverTheRequestIsHttps |
Theory | CR 16 credential cookies are secure whenever the request is https. |
CR18_TheConnectionLimit_DefaultsSensibly_AndCanBeSwitchedOff |
Theory | CR 18 the connection limit defaults sensibly and can be switched off. |
CR18_TheSettingsAreRegisteredWithDefaults |
Fact | CR 18 the settings are registered with defaults. |
CR19_CookieAuthenticatedStateChange_NeedsSameOriginEvidence_WhenSecFetchSiteIsAbsentAsync |
Fact | CR 19 cookie authenticated state change needs same origin evidence when sec fetch site is absent. |
CR19_SideEffectingGets_AreRefusedWhenCrossSite_ButPlainGetsAreNotAsync |
Theory | CR 19 side effecting gets are refused when cross site but plain gets are not. |
PenTestSessionCaseJournal
Jube.Test.Security.Identity.PenTestSessionCaseJournal — 8 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
ForeignTenantWorkflow_CannotBeWrittenToOrProbedAsync |
Fact | Foreign tenant workflow cannot be written to or probed. |
Journals_ArePrivateToTheirOwnerAsync |
Fact | Journals are private to their owner. |
JsonContent_MustBeValidBoundedJsonAsync |
Fact | Json content must be valid bounded json. |
StoredJson_RoundTripsFaithfully_AndIsNeverExecutedAsMarkupAsync |
Fact | Stored json round trips faithfully and is never executed as markup. |
Injection_InRouteAndGuid_IsInertAsync |
Fact | Injection in route and guid is inert. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
ConcurrentSaves_KeepOneJournalPerUserAndWorkflowAsync |
Fact | Concurrent saves keep one journal per user and workflow. |
PenTestTenantRegistry
Jube.Test.Security.Identity.PenTestTenantRegistry — 8 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_OnlyALandlordIsAuthorisedAsync |
Theory | Matrix only a landlord is authorised. |
NoTenantAdministrator_EvenWithEveryPermission_CanReachAnyTenantRouteAsync |
Fact | No tenant administrator even with every permission can reach any tenant route. |
Landlord_MassAssignment_CannotCreateOrPromoteALandlordTenantAsync |
Fact | Landlord mass assignment cannot create or promote a landlord tenant. |
UpdatingALandlordTenant_KeepsItLandlordAsync |
Fact | Updating a landlord tenant keeps it landlord. |
LockedAndDeletedTenants_AreImmutable_AndLifecycleIsOrderlyAsync |
Fact | Locked and deleted tenants are immutable and lifecycle is orderly. |
Injection_InNameFilterAndRoute_IsInertAsync |
Fact | Injection in name filter and route is inert. |
ByFilter_ReturnsOnlyMatchingTenants_AndBoundsItsWorkAsync |
Fact | By filter returns only matching tenants and bounds its work. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
PenTestUserInTenant
Jube.Test.Security.Identity.PenTestUserInTenant — 7 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedAsync |
Theory | Matrix is enforced. |
NonLandlord_CannotMoveThemselvesOrAnyoneToAnotherTenantAsync |
Fact | Non landlord cannot move themselves or anyone to another tenant. |
Landlord_SwitchesOnlyToRealTenants_AndOnlyItselfAsync |
Fact | Landlord switches only to real tenants and only itself. |
SwitchTakesTheTenantFromTheBodyOnly_NotTheQueryStringAsync |
Fact | Switch takes the tenant from the body only not the query string. |
ReadRoutes_ReturnOnlyTheCallersTenantAsync |
Fact | Read routes return only the callers tenant. |
UserWithoutAMapping_IsRefusedEverywhereAsync |
Fact | User without a mapping is refused everywhere. |
Injection_InQueryParameters_IsInertAsync |
Fact | Injection in query parameters is inert. |
PenTestUserLogout
Jube.Test.Security.Identity.PenTestUserLogout — 5 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
AuthorisationMatrix_RefusesEveryoneButTheAdministratorsAsync |
Fact | Authorisation matrix refuses everyone but the administrators. |
Rows_AreTenantScoped_AndOnlyALandlordSeesEverythingAsync |
Fact | Rows are tenant scoped and only a landlord sees everything. |
ItIsReadOnly_EveryOtherVerbIsRefused_AndNothingIsWrittenAsync |
Fact | It is read only every other verb is refused and nothing is written. |
EveryQueryParameter_SurvivesHostileInputAsync |
Fact | Every query parameter survives hostile input. |
OnlyDocumentedColumnsAreExposed_AndNoSecretsLeakAsync |
Fact | Only documented columns are exposed and no secrets leak. |
PenTestUserRegistry
Jube.Test.Security.Identity.PenTestUserRegistry — 16 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_AnonymousGarbageNoPermissionAndOtherPermission_AreRefusedAsync |
Theory | Matrix anonymous garbage no permission and other permission are refused. |
Responses_NeverExposePasswordHashesOrLoginBookkeepingAsync |
Fact | Responses never expose password hashes or login bookkeeping. |
CrossTenant_ReadUpdateDeleteAndResetBehaveLikeNotFoundAsync |
Fact | Cross tenant read update delete and reset behave like not found. |
CrossTenantRole_CannotBeAssignedOnCreateOrUpdateAsync |
Fact | Cross tenant role cannot be assigned on create or update. |
UserNameCollision_WithAnotherTenantsUser_IsRefusedAsync |
Fact | User name collision with another tenants user is refused. |
MassAssignment_OnCreate_IsIgnoredAsync |
Fact | Mass assignment on create is ignored. |
MassAssignment_OnUpdate_IsIgnoredAndBookkeepingSurvivesAsync |
Fact | Mass assignment on update is ignored and bookkeeping survives. |
PasswordLockedInProfileUpdate_OnlyChangesWhenExplicitAsync |
Fact | Password locked in profile update only changes when explicit. |
SetPassword_IssuesFreshRandomSecretOnlyForOwnTenantAsync |
Fact | Set password issues fresh random secret only for own tenant. |
Lifecycle_DoubleDelete_UpdateAfterDelete_AndReset_AfterDeleteAsync |
Fact | Lifecycle double delete update after delete and reset after delete. |
Injection_InNameAndEmail_IsStoredAsDataOrRejectedAsync |
Fact | Injection in name and email is stored as data or rejected. |
Injection_InRouteAndQuery_IsInertAsync |
Fact | Injection in route and query is inert. |
TimeBlindInjection_DoesNotDelayTheResponseAsync |
Fact | Time blind injection does not delay the response. |
TypeConfusion_AndMalformedBodies_AreRejectedWithoutSideEffectsAsync |
Fact | Type confusion and malformed bodies are rejected without side effects. |
ListRoutes_ReturnOnlyTheCallersTenant_AndBoundedBodiesAsync |
Fact | List routes return only the callers tenant and bounded bodies. |
ConcurrentConflictingWrites_NeverServerErrorAsync |
Fact | Concurrent conflicting writes never server error. |
PenTestUserRegistryApiKey
Jube.Test.Security.Identity.PenTestUserRegistryApiKey — 9 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_IsEnforcedPerPermissionAsync |
Theory | Matrix is enforced per permission. |
KeyMaterial_IsShownOnceAndNeverStoredOrListedAsync |
Fact | Key material is shown once and never stored or listed. |
ADisabledUsersApiKeyIsExcludedFromTheValidationSetAsync |
Fact | A disabled users api key is excluded from the validation set. |
CrossTenant_ListIssueAndRevoke_BehaveLikeNotFoundAsync |
Fact | Cross tenant list issue and revoke behave like not found. |
MassAssignment_OnCreate_IsIgnoredAsync |
Fact | Mass assignment on create is ignored. |
Revocation_IsIdempotent_AndTakesEffectAsync |
Fact | Revocation is idempotent and takes effect. |
Injection_InNameDescriptionAndRoutes_IsInertAsync |
Fact | Injection in name description and routes is inert. |
TypeConfusion_AndMalformedBodies_AreRejectedAsync |
Fact | Type confusion and malformed bodies are rejected. |
IssuingManyKeys_IsBounded_AndConcurrencySafeAsync |
Fact | Issuing many keys is bounded and concurrency safe. |
PenTestUserRegistryRevokeTokens
Jube.Test.Security.Identity.PenTestUserRegistryRevokeTokens — 9 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
Matrix_UnauthorisedCallers_AreRefusedAndTheVictimKeepsTheSessionAsync |
Theory | Matrix unauthorised callers are refused and the victim keeps the session. |
Authorised_Revoke_Is204_AndEndsBothBearerAndCookieSessionsAsync |
Fact | Authorised revoke is204 and ends both bearer and cookie sessions. |
RealLoginAfterRevoke_Works_AndTheOldSessionStaysDeadAsync |
Fact | Real login after revoke works and the old session stays dead. |
OwnUser_CanRevokeOwnSessionsAsync |
Fact | Own user can revoke own sessions. |
TenantB_CannotRevokeTenantAUser_AndLearnsNothingAsync |
Fact | Tenant b cannot revoke tenant a user and learns nothing. |
VerbTamperingAndBadIds_NeverRevokeAsync |
Fact | Verb tampering and bad ids never revoke. |
Service_RequiresPermission_AndIsTenantScopedAsync |
Fact | Service requires permission and is tenant scoped. |
Service_SetsTimestamp_IsIdempotent_AndNeverMovesBackwardsAsync |
Fact | Service sets timestamp is idempotent and never moves backwards. |
Revoke_DoesNotTouchApiKeysAsync |
Fact | Revoke does not touch api keys. |
Pen test
PenTestAnonymousAllowListTests
Jube.Test.Security.PenTest.PenTestAnonymousAllowListTests — 2 tests.
| Test | Kind | Verifies |
|---|---|---|
Route_RejectsAnonymous_UnlessAllowListedAsync |
Theory | Route rejects anonymous unless allow listed. |
AnonymousSurface_HasNotDrifted |
Fact | Anonymous surface has not drifted. |
PenTestAuthorizationTests
Jube.Test.Security.PenTest.PenTestAuthorizationTests — 2 tests.
| Test | Kind | Verifies |
|---|---|---|
UserWithoutPermission_IsRefusedAsync |
Theory | User without permission is refused. |
OtherTenantAndUnknownUser_ReceiveNoForeignDataAsync |
Theory | Other tenant and unknown user receive no foreign data. |
PenTestCredentialTamperingTests
Jube.Test.Security.PenTest.PenTestCredentialTamperingTests — 7 tests.
| Test | Kind | Verifies |
|---|---|---|
GarbageAndMalformedCookies_AreRejectedAsync |
Fact | Garbage and malformed cookies are rejected. |
ExpiredToken_IsRejectedAsync |
Fact | Expired token is rejected. |
WrongSignature_IsRejectedAsync |
Fact | Wrong signature is rejected. |
AlgNone_IsRejectedAsync |
Fact | Alg none is rejected. |
ValidTokenForDeletedOrLockedUser_IsRejectedAsync |
Fact | Valid token for deleted or locked user is rejected. |
UnknownUser_TokenIsRejectedAsync |
Fact | Unknown user token is rejected. |
ProtectedRoute_RejectsHeadOptionsTraceAnonymouslyAsync |
Theory | Protected route rejects head options trace anonymously. |
PenTestCsrfAndHeadersTests
Jube.Test.Security.PenTest.PenTestCsrfAndHeadersTests — 11 tests.
| Test | Kind | Verifies |
|---|---|---|
CrossSiteRequestWithCookie_IsNeverAcceptedAsync |
Theory | Cross site request with cookie is never accepted. |
BearerAndApiKeyCallers_AreNotSubjectToTheSameSiteCheckAsync |
Fact | Bearer and api key callers are not subject to the same site check. |
Cors_NeverReflectsAnOriginOrAllowsCredentialsAsync |
Fact | Cors never reflects an origin or allows credentials. |
LoginPage_ForbidsFramingAsync |
Fact | Login page forbids framing. |
AccountRoutes_NeverCacheAndNeverSendAReferrerAsync |
Fact | Account routes never cache and never send a referrer. |
AccountCredentialContainers_AreNotFormsAndHaveNoPostTargetAsync |
Theory | Account credential containers are not forms and have no post target. |
ContentSecurityPolicy_ConstrainsTheDirectivesThatDoNotFallBackAsync |
Theory | Content security policy constrains the directives that do not fall back. |
SiteIsolationHeaders_ArePresentAndSpectreResistantAsync |
Fact | Site isolation headers are present and spectre resistant. |
TheRootRedirectsAnonymousCallersWithoutRenderingAPageAsync |
Fact | The root redirects anonymous callers without rendering a page. |
SecurityHeaders_AreObservedAndAnythingPresentIsSaneAsync |
Fact | Security headers are observed and anything present is sane. |
ApiResponses_SetTheAuthenticationCookiesSafelyAsync |
Fact | Api responses set the authentication cookies safely. |
PenTestInventoryTests
Jube.Test.Security.PenTest.PenTestInventoryTests — 5 tests.
| Test | Kind | Verifies |
|---|---|---|
Inventory_CoversEveryKindOfEndpoint |
Fact | Inventory covers every kind of endpoint. |
Inventory_DiscoveryMatchesRunningHost |
Fact | Inventory discovery matches running host. |
Host_RunsTheRealPipelineAsync |
Fact | Host runs the real pipeline. |
Cleanup_RunsWithoutErrorsAsync |
Fact | Cleanup runs without errors. |
DumpInventory_WhenRequested |
Fact | Dump inventory when requested. |
PenTestKnownFindingsTests
Jube.Test.Security.PenTest.PenTestKnownFindingsTests — 10 tests.
| Test | Kind | Verifies |
|---|---|---|
SF002_Swagger_IsNotServedToAnonymousCallersAsync |
Fact | SF 002 swagger is not served to anonymous callers. |
VA008_SwaggerUi_PointsAtJubesOwnSpecNotThePetstoreDemoAsync |
Fact | VA 008 swagger ui points at jubes own spec not the petstore demo. |
SF003_AuthenticationCookies_CarryExplicitSameSiteAsync |
Fact | SF 003 authentication cookies carry explicit same site. |
SF004_NegotiateRoutes_DoNotErrorWhenNegotiateIsDisabledAsync |
Fact | SF 004 negotiate routes do not error when negotiate is disabled. |
SF005_SF006_AdministrationPages_RejectAnonymousAndNonLandlordAsync |
Fact | SF 005 SF 006 administration pages reject anonymous and non landlord. |
SF007_NulByteInStringParameter_IsA400Async |
Fact | SF 007 nul byte in string parameter is a 400. |
SF008_RoleDelete_NonExistentId_Is404Async |
Fact | SF 008 role delete non existent id is404. |
SF009_LookupByNonExistentId_Is404Async |
Fact | SF 009 lookup by non existent id is404. |
SF011_EmptyJsonBody_IsA400Async |
Fact | SF 011 empty json body is a 400. |
SF012_SetPassword_UnknownUserId_Is404Async |
Fact | SF 012 set password unknown user id is404. |
PenTestLeakageTests
Jube.Test.Security.PenTest.PenTestLeakageTests — 5 tests.
| Test | Kind | Verifies |
|---|---|---|
ErrorPaths_LeakNothing_ForEveryUserAsync |
Fact | Error paths leak nothing for every user. |
ErrorPage_ShowsOnlyARequestIdAsync |
Fact | Error page shows only a request id. |
LoginRedirectUrl_IsNotAnOpenRedirectAsync |
Fact | Login redirect url is not an open redirect. |
ServerBanner_IsObservedNotVersionedAsync |
Fact | Server banner is observed not versioned. |
Observations_AreReportedAsync |
Fact | Observations are reported. |
PenTestMarkerTests
Jube.Test.Security.PenTest.PenTestMarkerTests — 10 tests. Category: Unit.
| Test | Kind | Verifies |
|---|---|---|
FractionalSecondsAreNotTheOtherTenantsNumber |
Theory | Fractional seconds are not the other tenants number. |
TheNumberTheRowActuallyCarriesIsFound |
Fact | The number the row actually carries is found. |
ALeakedNumberIsFoundWhereverItSitsInTheDocument |
Fact | A leaked number is found wherever it sits in the document. |
APrintedPrecisionShorterThanTheValueStillMatches |
Fact | A printed precision shorter than the value still matches. |
ALongerNumberThatMerelyEndsInTheMarkerIsNotTheMarker |
Fact | A longer number that merely ends in the marker is not the marker. |
AnIdentifierThatSharesTheMarkersDigitsIsNotTheMarker |
Fact | An identifier that shares the markers digits is not the marker. |
ANumberCarriedInsideAStringIsStillALeak |
Fact | A number carried inside a string is still a leak. |
ATextMarkerIsMatchedAsText |
Fact | A text marker is matched as text. |
ANumberInABodyThatIsNotJsonIsStillFoundButNotInsideATimestamp |
Fact | A number in a body that is not json is still found but not inside a timestamp. |
AnEmptyBodyOrMarkerCarriesNothing |
Fact | An empty body or marker carries nothing. |
PenTestRequestStructureTests
Jube.Test.Security.PenTest.PenTestRequestStructureTests — 5 tests.
| Test | Kind | Verifies |
|---|---|---|
HostileBodiesAndContentTypes_AreRejectedCleanlyAsync |
Theory | Hostile bodies and content types are rejected cleanly. |
OversizedJsonBody_IsRejectedWithoutServerErrorOrHangAsync |
Fact | Oversized json body is rejected without server error or hang. |
BodyBeyondKestrelLimit_IsRejectedWith413Async |
Fact | Body beyond kestrel limit is rejected with413. |
OversizedUpload_IsRejectedWithoutServerErrorOrHangAsync |
Fact | Oversized upload is rejected without server error or hang. |
OverlongHeadersAndTargets_AreRejectedAsync |
Fact | Overlong headers and targets are rejected. |
PenTestRouteParameterTests
Jube.Test.Security.PenTest.PenTestRouteParameterTests — 1 test.
| Test | Kind | Verifies |
|---|---|---|
EveryParameter_SurvivesHostilePayloadsAsync |
Theory | Every parameter survives hostile payloads. |
PenTestStaticAndSwaggerTests
Jube.Test.Security.PenTest.PenTestStaticAndSwaggerTests — 4 tests.
| Test | Kind | Verifies |
|---|---|---|
StaticFiles_PublicSurfaceIsPinnedAsync |
Fact | Static files public surface is pinned. |
StaticFiles_SampleServesWithoutErrorsAsync |
Fact | Static files sample serves without errors. |
StaticFiles_TraversalNeverYieldsContentAsync |
Fact | Static files traversal never yields content. |
Swagger_WhenAuthenticated_DoesNotLeakInternalsAsync |
Fact | Swagger when authenticated does not leak internals. |
PenTestVerbTamperingTests
Jube.Test.Security.PenTest.PenTestVerbTamperingTests — 2 tests.
| Test | Kind | Verifies |
|---|---|---|
UndeclaredVerbs_AreNotAcceptedAndNeverErrorAsync |
Theory | Undeclared verbs are not accepted and never error. |
MethodOverride_IsIgnoredAsync |
Theory | Method override is ignored. |
Permissions
PermissionParityTests
Jube.Test.Security.Permissions.PermissionParityTests — 8 tests. Category: PermissionParity. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
RoleAllocationPage_OnlyItsOwnPermission_CanOpenAndLoadRolesAsync |
Theory | Role allocation page only its own permission can open and load roles. |
AuditTrailPage_AndItsEndpoint_AreGatedByTheSamePermissionAsync |
Theory | Audit trail page and its endpoint are gated by the same permission. |
UserLogoutMenuEntry_IsShownOnlyToTheHoldersOfItsPermissionAsync |
Fact | User logout menu entry is shown only to the holders of its permission. |
ChangePasswordFrame_IsGatedByUserRegistryPermissionAsync |
Fact | Change password frame is gated by user registry permission. |
CasePage_CanLoadTheModelTagsItNeeds_ButNotManageTagsAsync |
Fact | Case page can load the model tags it needs but not manage tags. |
ModelSamplePage_CanListModels_ButNotChangeThemAsync |
Fact | Model sample page can list models but not change them. |
ExhaustivePage_ViewPermissionCannotPromote_ByDesignAsync |
Fact | Exhaustive page view permission cannot promote by design. |
EntityAnalysisInlineScript_IsSystemWideAndReadOnlyAsync |
Fact | Entity analysis inline script is system wide and read only. |
Surface
PenTestAuthenticationSurface
Jube.Test.Security.Surface.PenTestAuthenticationSurface — 35 tests.
| Test | Kind | Verifies |
|---|---|---|
Login_Success_IssuesHardenedCookiesAndEchoesNothingAsync |
Fact | Login success issues hardened cookies and echoes nothing. |
Login_FailureModes_AreUniformOnTheWireAsync |
Fact | Login failure modes are uniform on the wire. |
Login_MalformedBodies_NeverAuthenticateOrSetCookiesAsync |
Fact | Login malformed bodies never authenticate or set cookies. |
Login_ContentTypeAndFormConfusion_NeverAuthenticatesAsync |
Fact | Login content type and form confusion never authenticates. |
Login_VerbTunnelling_NeverAuthenticatesAsync |
Fact | Login verb tunnelling never authenticates. |
Login_HeaderAndFramingAbuse_IsRefusedCleanlyAsync |
Fact | Login header and framing abuse is refused cleanly. |
Login_InjectionInCredentialFields_NeverAuthenticatesAndNeverErrorsAsync |
Fact | Login injection in credential fields never authenticates and never errors. |
Login_OversizedCredentials_AreBoundedAsync |
Fact | Login oversized credentials are bounded. |
WirePasswordHash_ProbesAreUniformAndInertAsync |
Fact | Wire password hash probes are uniform and inert. |
NegotiateRoutes_AreAbsentWhenNegotiateIsOffAsync |
Fact | Negotiate routes are absent when negotiate is off. |
LoginPage_RedirectUrl_IsNeverAnOpenRedirectAsync |
Fact | Login page redirect url is never an open redirect. |
SessionFixation_LoginAlwaysIssuesAFreshTokenForTheLoggedInUserAsync |
Fact | Session fixation login always issues a fresh token for the logged in user. |
Logout_FreshSession_RevokesTheTokenAndClearsTheCookiesAsync |
Fact | Logout fresh session revokes the token and clears the cookies. |
Logout_AfterTheAccessTokenWasRefreshed_StillLogsOutAsync |
Fact | Logout after the access token was refreshed still logs out. |
Logout_MenuAndPage_CarryNoAntiforgeryFormAndCallTheEndpointAsync |
Fact | Logout menu and page carry no antiforgery form and call the endpoint. |
Logout_PageHasNoPostHandler_AndAGetNeverEndsTheSessionAsync |
Fact | Logout page has no post handler and a get never ends the session. |
Logout_WithNoValidSession_StillAnswers200AndClearsTheCookiesAsync |
Fact | Logout with no valid session still answers200 and clears the cookies. |
Logout_BearerOnly_RevokesTheUsersTokensAsync |
Fact | Logout bearer only revokes the users tokens. |
Logout_WithAnApiKeyHeader_EndsNoSessionAsync |
Fact | Logout with an api key header ends no session. |
Logout_OtherUsersSessions_AreUntouchedAsync |
Fact | Logout other users sessions are untouched. |
Logout_ClosesTheUsersStreamConnections_AndOnlyTheirsAsync |
Fact | Logout closes the users stream connections and only theirs. |
Logout_ConcurrentDoubleLogout_IsIdempotentAsync |
Fact | Logout concurrent double logout is idempotent. |
Logout_CrossSiteAndOriginlessCookiePosts_AreRefused_AndTheSessionSurvivesAsync |
Fact | Logout cross site and originless cookie posts are refused and the session survives. |
Logout_OtherVerbs_AreNotAllowed_AndNeverEndTheSessionAsync |
Fact | Logout other verbs are not allowed and never end the session. |
Logout_HostileBodiesAndHeaders_NeverErrorAndNeverLeakAsync |
Fact | Logout hostile bodies and headers never error and never leak. |
Logout_HostileUserAgentAndForwardedAddress_AreStoredAsInertBoundedDataAsync |
Fact | Logout hostile user agent and forwarded address are stored as inert bounded data. |
Logout_WritesTheAuditRowOfTheSessionThatWasCutAsync |
Fact | Logout writes the audit row of the session that was cut. |
Logout_WithNoSession_WritesAtMostOneRowPerAddressPerMinuteAsync |
Fact | Logout with no session writes at most one row per address per minute. |
ChangePassword_RevokesEarlierSessions_AndRecordsIt_InTheLogoutTrailAsync |
Fact | Change password revokes earlier sessions and records it in the logout trail. |
ChangePassword_RotatesTheSessionAndRevokesOldTokensAsync |
Fact | Change password rotates the session and revokes old tokens. |
Program_DoesNotDisableTheRequestBodyDataRate |
Fact | Program does not disable the request body data rate. |
PasswordChangedAtLogin_RevokesEarlierSessionsAsync |
Fact | Password changed at login revokes earlier sessions. |
ChangePassword_Abuse_IsRefusedCleanlyAsync |
Fact | Change password abuse is refused cleanly. |
UserLoginEndpoint_AuthorizationMatrix_AndParameterAbuseAsync |
Fact | User login endpoint authorization matrix and parameter abuse. |
UserLoginEndpoint_ListIsTenantScopedAsync |
Fact | User login endpoint list is tenant scoped. |
PenTestInvokeController
Jube.Test.Security.Surface.PenTestInvokeController — 8 tests.
| Test | Kind | Verifies |
|---|---|---|
Inventory_HasExactlyTheEightInvokeRoutes_AllMinimalApi_AllRequiringAuthorization |
Fact | Inventory has exactly the eight invoke routes all minimal api all requiring authorization. |
EveryRoute_RequiresAuthenticationAsync |
Fact | Every route requires authentication. |
AuthorisedCallersWithoutAnEngine_GetACleanRefusalOnEveryRouteAsync |
Fact | Authorised callers without an engine get a clean refusal on every route. |
VerbsAndContentTypes_AreBoundedAsync |
Fact | Verbs and content types are bounded. |
GuidAndAsyncRouteParameters_AreRefusedCleanlyAsync |
Fact | Guid and async route parameters are refused cleanly. |
QueryParameters_OfCallbackAndSanction_AreBoundedAsync |
Fact | Query parameters of callback and sanction are bounded. |
BodiesMalformedHugeAndHostile_AreRefusedWithoutDetailAsync |
Fact | Bodies malformed huge and hostile are refused without detail. |
ApiKeyAndBearerCredentials_OnlyAuthenticateRealCredentialsAsync |
Fact | Api key and bearer credentials only authenticate real credentials. |
PenTestMockEndpointsGate
Jube.Test.Security.Surface.PenTestMockEndpointsGate — 2 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
WithTheFlagOff_NoMockRouteIsMapped_AndTheRealSurfaceStillWorksAsync |
Fact | With the flag off no mock route is mapped and the real surface still works. |
TheFlagDefaultsOn_SoADeploymentKeepsTheDocumentedFixturesAsync |
Fact | The flag defaults on so a deployment keeps the documented fixtures. |
PenTestMocks
Jube.Test.Security.Surface.PenTestMocks — 6 tests.
| Test | Kind | Verifies |
|---|---|---|
Inventory_MockPrefixesHideNoOtherRoute |
Fact | Inventory mock prefixes hide no other route. |
MockRoute_DoesNotReflectStoreOrExecuteRequestContentAsync |
Theory | Mock route does not reflect store or execute request content. |
MockHttpAdaptation_ResponsesAreStableAsync |
Fact | Mock http adaptation responses are stable. |
MockHttpAdaptation_NoOtherRouteHidesBehindThePrefixAsync |
Fact | Mock http adaptation no other route hides behind the prefix. |
MockRsaMfa_IsStableBoundedAndSecretSafeAsync |
Fact | Mock rsa mfa is stable bounded and secret safe. |
MockHttpAdaptation_HugeBodiesAndFloodsAreBoundedAsync |
Fact | Mock http adaptation huge bodies and floods are bounded. |
PenTestRazorPageHandlers
Jube.Test.Security.Surface.PenTestRazorPageHandlers — 2 tests.
| Test | Kind | Verifies |
|---|---|---|
PageModelsDeclareNoStateChangingHandlers |
Fact | Page models declare no state changing handlers. |
NoPageOrControllerOptsOutOfAntiforgery |
Fact | No page or controller opts out of antiforgery. |
PenTestRazorPages
Jube.Test.Security.Surface.PenTestRazorPages — 8 tests.
| Test | Kind | Verifies |
|---|---|---|
Inventory_HasTheHundredAndOneRazorPages |
Fact | Inventory has the hundred and one razor pages. |
Page_AnonymousAndForgedCredentials_AreRedirectedOrDeniedAsync |
Theory | Page anonymous and forged credentials are redirected or denied. |
Page_PermissionMatrixAsync |
Theory | Page permission matrix. |
Page_ReflectedXss_ThroughQueryStringPathAndHandlersAsync |
Theory | Page reflected xss through query string path and handlers. |
Page_StateChangingVerbs_RequireAntiforgeryAndNeverSucceedAsync |
Theory | Page state changing verbs require antiforgery and never succeed. |
Page_PathCaseAndSuffixVariants_DoNotBypassProtectionOrDiscloseSourceAsync |
Theory | Page path case and suffix variants do not bypass protection or disclose source. |
ErrorPage_IsQuietAndNeverReflectsInputAsync |
Fact | Error page is quiet and never reflects input. |
UnknownPages_AreQuietAndProtectedWhenAnonymousAsync |
Fact | Unknown pages are quiet and protected when anonymous. |
PenTestServiceChangeStream
Jube.Test.Security.Surface.PenTestServiceChangeStream — 4 tests.
| Test | Kind | Verifies |
|---|---|---|
Unauthenticated_IsRejectedWithNoStreamOpenedAsync |
Fact | Unauthenticated is rejected with no stream opened. |
NoTenant_Gets403BeforeAnyStreamHeadersAreSentAsync |
Fact | No tenant gets403 before any stream headers are sent. |
CrossSiteRequest_IsRefusedAsync |
Fact | Cross site request is refused. |
HostileQueryStringAndHeaders_NeverProduceAServerErrorOrLeakDetailAsync |
Fact | Hostile query string and headers never produce a server error or leak detail. |
PenTestStaticAssetSurface
Jube.Test.Security.Surface.PenTestStaticAssetSurface — 2 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
TheVendoredDemoTree_IsNeitherShippedNorServedAsync |
Fact | The vendored demo tree is neither shipped nor served. |
TheAssetsTheLayoutLoads_AreStillServedAsync |
Fact | The assets the layout loads are still served. |
PenTestUploadAntiforgery
Jube.Test.Security.Surface.PenTestUploadAntiforgery — 5 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
ACookieSessionWithoutTheAntiforgeryTokenIsRejectedAsync |
Theory | A cookie session without the antiforgery token is rejected. |
ACookieSessionWithTheAntiforgeryTokenReachesTheEndpointAsync |
Theory | A cookie session with the antiforgery token reaches the endpoint. |
ABearerAuthenticatedRequestIsNotSubjectToAntiforgeryAsync |
Theory | A bearer authenticated request is not subject to antiforgery. |
AnAntiforgeryTokenSurvivesASessionTokenRefreshAsync |
Fact | An antiforgery token survives a session token refresh. |
ACookieSessionWithAGarbageAntiforgeryTokenIsRejectedAsync |
Theory | A cookie session with a garbage antiforgery token is rejected. |
PenTestWafSeededSignatures
Jube.Test.Security.Surface.PenTestWafSeededSignatures — 3 tests. Category: PenTest. Collection: Database.
| Test | Kind | Verifies |
|---|---|---|
SeededSignature_RefusesTheAttackBeforeItReachesTheEndpointAsync |
Theory | Seeded signature refuses the attack before it reaches the endpoint. |
SeededSignatures_DoNotRefuseLegitimateTextAsync |
Theory | Seeded signatures do not refuse legitimate text. |
ARefusedRequest_IsRecordedAsEvidenceAsync |
Fact | A refused request is recorded as evidence. |
PenTestWatcherStream
Jube.Test.Security.Surface.PenTestWatcherStream — 4 tests.
| Test | Kind | Verifies |
|---|---|---|
Unauthenticated_IsRejectedWithNoStreamOpenedAsync |
Fact | Unauthenticated is rejected with no stream opened. |
NoPermission_Gets403BeforeAnyStreamHeadersAreSentAsync |
Fact | No permission gets403 before any stream headers are sent. |
CrossSiteRequest_IsRefusedAsync |
Fact | Cross site request is refused. |
HostileQueryStringAndHeaders_NeverProduceAServerErrorOrLeakDetailAsync |
Fact | Hostile query string and headers never produce a server error or leak detail. |
