Skip to content

v1.21.3

Latest

Choose a tag to compare

@github-actions github-actions released this 19 Oct 22:08
· 115 commits to main since this release
Immutable release. Only release title and notes can be modified.
fa9da82

v1.21.3

Bundle signature verification could be side-stepped (GHSA-g2pf-6v5v-qcc8)

An attacker able to alter bundle bytes could supply arbitrary policy and data to an OPA that was configured
to verify bundle signatures. This could happen if the attacker controls any of:

  • OPA bundle/discovery service (including an artifact store it uses)
  • MitM between OPA and bundle/discovery service
  • write access to a file:// bundle path or the bundle persistence directory

Two separate side-steps are fixed:

Issue 1. Signature verification keyed on keyid rather than on the signing block

OPA only required a .signatures.json file when signing.keyid was set, so a bundle stripped of its signature was
accepted if only e.g. bundles[_].signing was set instead of bundles[_].signing.keyid. Verification now depends on
the presence of a signing block, as documented; keyid only selects which key to use.

Affected:

  • bundles[_].signing or discovery.signing configured without keyid: an empty block, or one with only scope or
    exclude_files.
  • Embedders (SDK, custom plugins, v1/loader, v1/compile) calling bundle.NewVerificationConfig(keys, "", ...) with
    an empty key id.

Not affected:

  • Configurations with an explicit bundles[_].signing.keyid or discovery.signing.keyid.
  • opa run/opa eval/opa build with --verification-key, which defaults --verification-key-id to default.
    Passing --verification-key-id "" explicitly was affected.
  • Configurations with top-level keys but no signing block: not a verification opt-in before or after this fix.
    Unsigned bundles are still accepted, and OPA now logs a warning at startup for bundles in this state.

Workaround: on affected versions, set an explicit keyid on every bundle that must be signed:

bundles:
  authz:
    service: acmecorp
    resource: bundle.tar.gz
    signing:
      keyid: my_key # must name an entry under the top-level `keys`
discovery:
  resource: /discovery.tar.gz
  signing:
    keyid: my_discovery_key

keys:
  my_key:
    algorithm: RS256
    key: |
      -----BEGIN PUBLIC KEY-----
      ...

Further behaviour changes:

  • A signing block with no entries under the top-level keys is now a startup configuration error, rather than a
    configuration that rejects every signed bundle while accepting unsigned ones.
  • bundle.NewVerificationConfig now requires signatures by default. Embedders can opt out with
    WithSkipBundleVerification(true) or the new (*VerificationConfig).WithOptionalSignature().

Issue 2. Unsigned delta bundle downgrade

Delta bundles skipped verification entirely, so an attacker could replace a signed snapshot bundle with an unsigned
delta bundle on the same resource. The signed policy stays active while the attacker controls any data inside the
bundle's roots. Delta bundles not supporting signing
was documented, but unenforced. OPA now rejects them with delta bundles do not support signature verification.

Affected:

  • Any bundle or discovery configuration with a signing block, with or without keyid.
  • opa run/opa eval with --verification-key.

Not affected:

  • Configurations that don't verify signatures: no signing block, or --skip-verify. Nothing was verified to begin
    with.

Workaround: there is no configuration that makes affected versions reject delta bundles. Until upgrading, ensure
the integrity of the bundle bytes themselves: TLS terminated by OPA or a trusted hop, restricted write access to the
bundle service, artifact store and bundle persistence directory.

Bundle services that must keep serving unsigned delta bundles after upgrading can opt out per bundle with the new
bundles[_].signing.allow_unsigned_delta_bundles (or discovery.signing.allow_unsigned_delta_bundles) field.
Snapshot bundles must still be signed.

Reported by Brian Willows (@BrianWillows, Graith Internet, graith.co.uk), authored by @johanfylling.