Reference

[ AxiomCore · Documentation ]

Security rules

The AXSEC rule catalog, finding statuses and severities, extractor evidence, and where audit and strict Security Mode are enforced.

Security Mode is an optional security(...) block in a backend contract. The compiler checks it and reports findings with stable AXSEC rule IDs. The same IDs appear in local checks, CI, signed releases, contract pull requests, contract pages, and trace context. A declaration is never presented as proof that arbitrary handler code is safe. For the declaration syntax, see Domain and security models; for every field, see the security schema.

Where AXSEC findings come from and where they are used
Where AXSEC findings come from and where they are used
Diagram source
flowchart LR
  DECL["security declarations in .acore"] --> AN["AXSEC analyzer"]
  EVID["Extractor evidence: Go, FastAPI"] --> AN
  AN --> CHECK["axiom security check"]
  AN --> MAN["Signed security manifest in .axiom"]
  MAN --> GATE["Build and release gate"]
  MAN --> SERVER["Axiom server admission"]
  MAN --> CLIENT["Client runtime trace attributes"]
  MAN --> DASH["Cloud Dashboard"]

Declarations and extractor evidence both feed the analyzer. axiom security check reports findings without writing an artifact. axiom build signs the result into the .axiom contract as an axiom-security-manifest/v1 manifest, which the build gate, the Axiom server, the client runtime, and the dashboard read.

Modes

Modeaxiom security checkaxiom build and releaseAxiom server
audit (default)Reports all findings; exits 0Builds and releasesAdvisory only; labeled auditOnly
strictExits non-zero on any error findingRejects the build with blocking findingsEnforces supported guards; refuses to start on unsupported declarations

Add --fail-on-warning to axiom security check to fail on warnings too, for example in a review-only CI job. Structural errors, such as a reference to an unknown policy, stop compilation in either mode.

Example

With no guard or policy for an endpoint, strict mode reports AXSEC-001:

axiom.acore
project(id: "notes-api", version: "1.0.0")
variant default(include: ["*"])

model Note { id: String }

endpoint GetNote(method: GET, path: "/notes/{id}") {
  request { path("id", type: String) }
  response(type: Models.Note)
}

security(mode: "strict")

The directory also needs an AxiomDeps.toml containing type = "backend".

Terminal
axiom security check axiom.acore
Output
Security Mode strict · 1 error(s), 0 warning(s) · 0 of 1 endpoints covered (0 direct, 0 default-policy)
AXSEC-001 ERROR [GetNote] `GetNote` is externally reachable but has no explicit public declaration or authorization policy.
  → Declare `security.endpoints[endpoint]` as public or bind it to a user-defined policy.
Error: security check found 1 error(s) and 0 warning(s)

Declaring the endpoint public clears the finding:

axiom.acore: changed line
security(mode: "strict", endpoints: { GetNote: EndpointGuard(public: true) })

axiom build on the first version fails with security strict mode rejected build: 1 blocking AXSEC finding(s). In audit mode the same finding is a warning and the build succeeds.

Finding statuses

StatusMeaning
invalidThe declaration itself is unsafe, such as credentialed wildcard CORS
uncoveredA required declaration is missing
declared_unprovenA declaration exists, but nothing proves it is enforced
observedAn extractor found the condition in source code

Severity

Most findings are mode-dependent: a warning in audit, an error in strict. The exceptions:

RuleSeverity in every mode
AXSEC-072, 131, 141, 161 for a declared effect with no matching service, path, process, or upload policyError
AXSEC-111 for declared credentialed wildcard CORSError
AXSEC-121Error
AXSEC-031 when the extracted authentication method is unknownWarning
AXSEC-041, AXSEC-151Warning
AXSEC-111 when only an extractor observed wildcard CORSWarning

An error in audit mode is still non-blocking unless you add --fail-on-warning or switch to strict.

Rule families

FamilyRisks coveredAXSEC rules
IdentityBroken authorization and IDOR; authentication001, 014, 031, 032
Output and dataXSS; secret leakage; data exposure; observability leaks041, 051, 081, 082, 151
Browser and networkSSRF; CSRF; rate limits and abuse; CORS061, 062, 072, 073, 091, 111
Stateful and OSMass assignment; uploads; paths; commands; cache101, 121, 131, 132, 141, 142, 161, 162
GlobalSecurity invariantsSigned requirements that reuse the rule families above

Rule catalog

RuleDetectsDeclaration or fix
AXSEC-001An endpoint with no public declaration or authorization policyEndpointGuard(public: true) or a policy
AXSEC-014A resource route with no resource binding (IDOR risk)EndpointGuard, policy resourceBinding, domain relationship
AXSEC-031, 032A missing or unsafe authentication profileAuthenticationPolicy transport safeguards
AXSEC-041HTML output not marked as escapedEscaped output boundary, or a reviewed unsafe exception
AXSEC-051Secret or sensitive data not marked for redactionSensitiveData(redact: true) plus adapter redaction
AXSEC-061, 062A required rate limit or idempotency key is missingRateLimit, idempotency declaration, adapter key enforcement
AXSEC-072, 073Dynamic, unallowlisted, or private-network egressFixed NetworkService origin; private networks denied by default
AXSEC-081, 082A classified field returned without a projection or audienceDomain response projection and an approved audience
AXSEC-091A cookie-authenticated mutation without CSRF protectionCsrfPolicy, or an explicit non-browser exemption
AXSEC-101A mutation without a writable-field allowlistwritableFields; the adapter rejects unknown fields
AXSEC-111Credentialed CORS with a wildcard originExplicit trusted origins; never credentials with *
AXSEC-121Shared caching of authenticated responses without principal variationDisable sharing, or require a principal vary key
AXSEC-131, 132Unrooted or dynamic filesystem accessRooted PathPolicy; deny external input
AXSEC-141, 142A process without a fixed executable, or with shell accessFixed executable and structured arguments
AXSEC-151Possible sensitive value written to logsClassify and redact; inspect the cited call site
AXSEC-161, 162An upload without a policy, or a policy missing safe defaultsSize and type limits, inspection, private non-executable storage

Extractor evidence without an SDK

The Go and Python (FastAPI) extractors record advisory facts in the signed manifest: dynamic network targets, process execution, filesystem paths, uploads, rate-limit signals, sensitive logging, and wildcard CORS. Each fact has a file, line, confidence, and short description. Rate-limit signals are recorded as evidence only and do not create a finding.

A fact can create a finding. It never grants access, marks a route public, or weakens a policy. Existing services therefore need no SDK; you declare or override a boundary in axiom.acore when the source evidence is incomplete.

Enforcement

BoundaryBehavior
CompilerValidates references and creates the canonical signed manifest
axiom security checkReports the same deterministic rules locally and in CI
Build and releasestrict rejects error findings; audit is non-blocking
Axiom serveraudit manifests stay advisory. strict manifests enforce supported guards (policies, a single role, bearer JWT profiles, writable fields, CORS, rate limits, ownership bindings) and fail startup on declarations that need an unsupported enforcement capability. See Identity and policies.
Client runtimeAdds the manifest hash, mode, declared policy, auth and permission, and endpoint finding count to an OpenTelemetry span (axiom.security.hash, .mode, .policy, .auth, .permission, .finding_count)
Cloud DashboardShows signed findings, coverage, the policy graph, diffs, and trace policy context
Existing Go or Python appUnchanged by extraction; its own middleware and handlers enforce security at runtime

The client runtime context is diagnostic only. Where no trusted server boundary evaluates the signed policy against a principal and resource, the dashboard labels the policy evidence declared_unproven instead of inventing a runtime decision.