| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Ecluse.Core.Cve.Internal
Description
The advisory lookup's internals: the hardened SQLite open and the raw queries Ecluse.Core.Cve curates into the public handle.
Importing this module opts out of the public surface's stability promises; it exists so tests can pin the hardening properties (the connection refuses writes, schema-borne SQL is distrusted) directly against the connection the handle actually uses.
Synopsis
- data AdvisoryRange = AdvisoryRange {
- arCveId :: Text
- arSeverity :: Maybe Double
- arIntroduced :: Maybe Text
- arFixed :: Maybe Text
- arLastAffected :: Maybe Text
- data CveDbRejected
- openHardenedConnection :: Ecosystem -> FilePath -> IO (Either CveDbRejected Connection)
- probeQuery :: Connection -> Text -> Text -> IO Bool
- advisoriesQuery :: Connection -> Text -> IO [AdvisoryRange]
- provenanceQuery :: Connection -> IO [(Text, Text)]
Documentation
data AdvisoryRange Source #
One advisory segment recorded against a package: the advisory's identifier,
its CVSS base score (0 to 10, Nothing when unscored), and the affected
interval's bounds as the artifact stores them (verbatim version text). The lower
bound arIntroduced is inclusive (Nothing == from the beginning); the upper
bound is (exclusive) or arFixed (inclusive) or neither
(open-ended). An exactly-enumerated affected version is a point segment
(arLastAffectedintroduced == last_affected).
Constructors
| AdvisoryRange | |
Fields
| |
Instances
| Show AdvisoryRange Source # | |
Defined in Ecluse.Core.Cve.Internal Methods showsPrec :: Int -> AdvisoryRange -> ShowS # show :: AdvisoryRange -> String # showList :: [AdvisoryRange] -> ShowS # | |
| Eq AdvisoryRange Source # | |
Defined in Ecluse.Core.Cve.Internal Methods (==) :: AdvisoryRange -> AdvisoryRange -> Bool # (/=) :: AdvisoryRange -> AdvisoryRange -> Bool # | |
data CveDbRejected Source #
Why a downloaded artifact was refused before a handle was built over it.
A rejection is a value, not an exception: the caller (the sync task, once it exists) has a real decision to make, keep the last known-good database and alarm, rather than a fault to unwind from.
Constructors
| CveDbWrongEpoch Int | The artifact's |
| CveDbIntegrityFailed [Text] | The artifact is not a usable SQLite database: either it is not a
database at all (absent or wrong header magic, which SQLite reports as
|
| CveDbSchemaNonConformant Text | A required relation (carried) does not conform to the epoch's schema
contract: absent, not a real |
| CveDbEcosystemMismatch (Maybe Text) | The artifact's |
Instances
| Show CveDbRejected Source # | |
Defined in Ecluse.Core.Cve.Internal Methods showsPrec :: Int -> CveDbRejected -> ShowS # show :: CveDbRejected -> String # showList :: [CveDbRejected] -> ShowS # | |
| Eq CveDbRejected Source # | |
Defined in Ecluse.Core.Cve.Internal Methods (==) :: CveDbRejected -> CveDbRejected -> Bool # (/=) :: CveDbRejected -> CveDbRejected -> Bool # | |
openHardenedConnection :: Ecosystem -> FilePath -> IO (Either CveDbRejected Connection) Source #
Open an artifact read-only-in-effect and accept or reject it.
Hardening order matters, and every pragma is applied before the first query.
trusted_schema = OFF distrusts schema-defined functions, views feeding
triggers, and virtual tables in the file; query_only = ON refuses every write,
so no trigger can ever fire through the connection; cell_size_check = ON
validates each b-tree cell against its page as pages are read, so a crafted
oversized cell becomes a clean error rather than an out-of-bounds access; and
mmap_size = 0 keeps reads on the bounds-checked pager instead of mapping
hostile file pages straight into the address space.
Acceptance then checks, cheapest and least trusting first: the osvSchemaEpoch
stamp (a header field, so a stale, substituted, or non-SQLite artifact is refused
before the file's interior is walked at all), a PRAGMA quick_check integrity
walk (a malformed or truncated b-tree is rejected before any lookup dereferences
it, and stored values are verified against each STRICT table's declared column
types), the required tables conforming to the epoch's schema contract
(osvTableSpecs: real STRICT tables carrying the required columns with their
declared types, which is what makes every later row decode total), and the
meta ecosystem matching the one asked for. A rejected artifact's connection is closed
before returning, and so is a connection whose hardening or acceptance throws
before it can return a rejection value: the whole phase runs under a
close-on-exception guard, so the just-opened connection is never leaked (the
"an exception never leaks it" contract openCveDb promises).
Read-only is enforced at the connection level: sqlite-simple's public API has
no way to pass SQLITE_OPEN_READONLY at open time, and query_only yields
the same guarantee for every statement this connection will run.
probeQuery :: Connection -> Text -> Text -> IO Bool Source #
Does any advisory for this package name this exact version string as a
fixed bound? One indexed probe (package_name, fixed_version); deliberately
string equality, per the artifact contract's canonical-semver expectation.
advisoriesQuery :: Connection -> Text -> IO [AdvisoryRange] Source #
Every advisory segment recorded against a package name.
provenanceQuery :: Connection -> IO [(Text, Text)] Source #
The artifact's meta provenance rows, key-sorted for a deterministic
snapshot. This only ever runs on an accepted connection, and acceptance has
confirmed meta is a STRICT table of NOT NULL TEXT whose stored values the
integrity walk verified, so the (Text, Text) decode is total here: no
artifact content can make it throw.