Skip to content

v0.23.0

Choose a tag to compare

@haksungjang haksungjang released this 15 Oct 15:13
· 33 commits to main since this release
b29d676

Highlights

  • Teams are now an unlimited-depth group hierarchy. Existing flat teams
    become top-level groups; access, visibility and administration follow the
    tree (#464).
  • BomLens can run as the scan engine (preview). With
    SCAN_ENGINE=bomlens source scans, and with SCAN_CONTAINER_ENGINE=bomlens
    container scans, run the pinned upstream BomLens 1.13.4 images through its
    execution plan instead of the in-process pipeline. The default engine is
    unchanged. See the administrator guide, "Dynamic scan executor".
  • Offline install bundle for air-gapped deployments (#477).

Added

  • Creative Commons ShareAlike licenses are now classified as weak copyleft.
    CC-BY-SA-* and CC-BY-NC-SA-* previously showed as "uncategorized". They
    now read as weak-copyleft, the same class as OFL and MPL, and a dependency
    under one gets a conditional license-compatibility verdict instead of
    unknown. CC-BY, CC-BY-NC and CC-BY-ND are unchanged.

  • Components found only under test, example or benchmark directories are
    no longer counted as shipped dependencies.
    A component is dropped when
    every manifest it was read from sits under a directory such as tests/,
    examples/ or __fixtures__/, matched as whole path segments regardless of
    case. The dropped package URLs are recorded on the scan and the Components
    summary shows them in its excluded count. Set
    SCAN_SCOPE_FILTER_NON_DEPLOYABLE_ENABLED=false to turn it off.

  • A vulnerability finding's ticket link can now be read back on demand. A
    finding whose ticket_url points at a Jira Cloud issue previously showed
    whatever status it was given at assignment time forever, even after the
    ticket closed. The drawer now has a "Refresh ticket status" button that
    makes one on-demand call to the tracker and records the answer
    (ticket_status, ticket_resolved, ticket_checked_at); a failed check
    (no credential configured, the tracker rejected the token, the issue does
    not exist) is recorded as ticket_check_error rather than clearing a
    previously-known status. A super-admin configures one Jira Cloud login per
    tracker host per organization via
    PUT /v1/admin/organizations/{id}/ticket-credentials, shared by every team
    the way container-registry credentials already are (#385).

  • The About screen and /metrics now show which image is actually
    running.
    Nothing published a build's commit or build timestamp
    before, so an operator had no way to tell how old a running image's
    security patches were beyond the release tag alone. Release images now
    carry TRUSTEDOSS_COMMIT and TRUSTEDOSS_BUILT_AT alongside the
    existing TRUSTEDOSS_VERSION, surfaced on the About screen and as a
    trusca_build_info / trusca_build_time_seconds metric pair for
    deployments that scrape /metrics (#441).

  • An opt-in gate axis fails builds on incomplete scans (#506), and a scan that
    finds no components despite declared dependencies now warns (#530).

  • CycloneDX exports carry the dependency graph and state its completeness
    (#505).

  • Scans record which optional stages degraded and when each stage ran; the
    project overview shows skipped license lookups and a skipped scancode stage
    (#495, #503).

  • Container scans store the full package inventory (#501).

  • Maven components inherit licenses from parent POMs, and more Maven license
    spellings map to SPDX ids (#493, #494).

  • Example Prometheus alerting rules, a backend HPA, measured backup RPO/RTO,
    and hardening and PostgreSQL tuning guides (#453, #459, #455, #469).

Changed

  • The public demo's shared account explore@ is now a super admin. In
    demo mode (DEMO_READ_ONLY) the admin API answers only an allow-list of
    read screens, scoped to the demo organization; backups, exports,
    credentials and anonymisation are refused, and a super admin's access is
    bounded to the demo organization.

Fixed

  • A compose deployment stored its backups inside the containers, so
    upgrading deleted them.
    BACKUPS_ROOT was set nowhere in
    docker-compose.yml, and with no value backups_root() resolves the
    relative default "backups" against the working directory, which in the
    published images is /app. Every nightly artifact therefore went to the
    writable layer of whichever container ran the task: invisible to docker system df, unreachable from the backend that lists them, and destroyed by
    the docker compose up -d that deploys a new tag, which is the moment a
    backup is worth the most. It also filled the host disk, since the artifact
    tars the scan workspace and is sized like it rather than like the database
    (7.6 GB in one night on a 2,089-project corpus, on a 26 GB root partition).
    The file now sets the path and mounts a shared backups-data volume there
    on the backend, both workers and beat, which is what docker-compose.dev.yml
    has done since the non-root switch. .env.example claimed the production
    file already mounted it; that is corrected too.

  • SCAN_SOURCE_RETENTION can now drop the preserved source tree while
    keeping the SBOM.
    A succeeded scan archives the scanned tree, the scancode
    result and the cdxgen SBOM, one archive per project. The tree is essentially
    all of the bytes: 13.8 MB per project measured across 559 of them, against
    tens of KB for the SBOM, which puts a 60,000-project corpus at roughly 830 GB
    of retained source. The setting existed but nothing read it, and only
    latest was ever implemented. It now takes latest (unchanged default),
    sbom-only and none.

    sbom-only is the one to reach for. The file tree is what the source buys,
    and it is not yet rendered anywhere; the SBOM is what the vulnerability
    rematch beat reads to re-check an already-scanned project against newly
    published advisories without re-running cdxgen. none drops that too, so a
    new advisory then reaches an old scan only by scanning it again from source,
    which on a large corpus is the difference between minutes and days. The
    retention beat reclaims what an earlier setting wrote when the policy is
    none, while still protecting a queued or running scan's archive.

    An unrecognised value falls back to latest rather than raising: this is
    read on the scan path, so a typo costs disk, never data. all, which
    .env.example offered and no code implemented, is one such value.

  • The worker image detects first-party licenses again. An unpinned
    dependency of scancode made every scancode call fail while the scan still
    reported success, so file-header licenses never reached the gate (#489).

  • helm install works on a fresh cluster. The pre-install Jobs ran
    before the ServiceAccounts, Secret and ConfigMap they need, and the chart
    never passed GITHUB_APP_ENCRYPTION_KEY, so stored-credential writes failed
    on chart installs (#509, #513).

  • A package-manager match and a fingerprint match for the same library are
    merged into one component (#499).

  • The license enrichment step is bounded per scan by a time budget and a
    circuit breaker (#491).

  • The deploy crash-recovery restart respects COMPOSE_FILE (#452).

Security

  • The worker image is rebuilt on upgraded bundled tools (Gradle, Go, Docker
    CLI, WeasyPrint, npm overrides) to clear newly reported fixable CVEs (#497,
    #515).
  • scanoss-py runs with --skip-snippets, so snippet fingerprints are not
    sent out (#478).