Skip to content

observal: initial integration - #15991

Open
RAWx18 wants to merge 1 commit into
google:masterfrom
RAWx18:add-observal-project
Open

observal: initial integration#15991
RAWx18 wants to merge 1 commit into
google:masterfrom
RAWx18:add-observal-project

Conversation

@RAWx18

@RAWx18 RAWx18 commented Aug 13, 2026

Copy link
Copy Markdown

Summary

This PR integrates Observal into OSS-Fuzz.

Observal is an Apache-2.0 licensed registry and observability control plane for AI
coding agents. Its core job is to ingest, parse, redact and replay session
transcripts produced by ten different AI coding harnesses. That parsing surface is
fed entirely by data the project does not control, which is what we want fuzzed
continuously.

Four Atheris targets already exist and are maintained in the project's own
repository under fuzz/.
This PR adds only the three-file project configuration.

The project

Repository https://github.com/Observal/Observal
Homepage https://observal.io/
License Apache-2.0
Language Python (>=3.11)
Distribution PyPI observal-cli, GHCR container images, Helm chart

Adoption and project health

As of 2026-08-13:

  • 2,358 stars, 471 forks, 58 contributors
  • 46 releases published to PyPI, currently at v1.12.1; released roughly weekly
  • OpenSSF Best Practices: Gold (project 13472) — 100% of passing, silver and gold criteria
  • OpenSSF Scorecard: 9.5 (report), with Code-Review, Branch-Protection, Security-Policy, Pinned-Dependencies and SAST all at 9–10
  • Documented security policy with a private disclosure channel, 48-hour acknowledgement and 30-day resolution targets, plus a published security assurance case
  • Actively maintained: CodeQL, Gitleaks, dependency review, SBOM generation and signed release provenance all run in CI

Why this project should be fuzzed

Observal's largest untrusted input is the harness session transcript. The flow is:

  1. An AI coding harness (Claude Code, Cursor, Kiro, Copilot, Codex CLI, OpenCode,
    Goose, Antigravity, Pi, Copilot CLI) writes JSONL to disk.
  2. A session-push hook, or observal reconcile, uploads the raw lines to
    POST /api/v1/ingest/session.
  3. The server classifies each line and stores it verbatim.
  4. The line is decoded again on the read path every time the trace viewer opens
    a session.

That is ten independent per-harness parsers operating on attacker-influenced data,
with a write path and a read path that must agree.

The second reason is redaction. Observal handles authentication tokens, API
keys and enterprise telemetry. Two redaction layers are the single chokepoint that
strips credentials before anything is stored or bundled into a support archive. A
parsing or redaction bug there is a credential-disclosure bug, not just a crash.

Fuzz targets

Target Trust boundary
session_jsonl_fuzzer Session transcripts end to end: ingest classification on the write path, parse_raw_events on the read path. The first input byte selects which harness parser to drive, so one target covers all ten.
session_structure_fuzzer The same pipeline, driven by Hypothesis-generated transcript records rather than raw bytes, to reach handler branches that byte mutation rarely gets past the JSON decoder to hit. Polyglot: also runs under pytest for shrinking and replay.
secrets_redactor_fuzzer services.secrets_redactor.redact_secrets, applied to every line and preview before storage.
support_redaction_fuzzer observal_cli.support.redaction, the chokepoint for observal support bundle.

Harness design

  • Fully in-process. No target opens a socket, reads credentials, or touches
    PostgreSQL, ClickHouse or Redis. Nothing depends on the clock. A crash reproduces
    from its input alone.
  • Bounded inputs. Every target caps input size so slow units are not reported
    as timeouts.
  • Expected rejections return; anything else is a finding. A decode error on
    malformed input is not a bug; any other exception is.
  • Seed corpora and dictionaries live in the project repo under fuzz/corpus/
    and fuzz/dictionaries/ and are picked up automatically by build.sh. A repo
    test asserts every registered harness parser still has a seed reaching it.

What this PR adds

projects/observal/project.yaml     30 lines
projects/observal/Dockerfile       34 lines
projects/observal/build.sh         44 lines   (mode 755)

Nothing else is touched. build.sh globs fuzz/*_fuzzer.py, so new targets added
upstream are picked up without further changes here.

Build notes

  • Dependencies are resolved from the project's committed uv.lock, exported to a
    requirements file, and installed with --require-hashes, so the image build is
    reproducible and hash-verified.
  • They are installed into the system interpreter rather than a virtualenv,
    because compile_python_fuzzer runs the base image's PyInstaller, which resolves
    imports against /usr/local site-packages only. This is called out in a comment
    in the Dockerfile.
  • The base image is referenced by tag and digest. This is deliberate
    supply-chain pinning on our side; happy to drop the digest if you would rather
    projects always track the freshest base image.

Local validation

Everything below was run against the real base images before opening this PR:

Command Result
docker build --no-cache --pull -t gcr.io/oss-fuzz/observal projects/observal OK
infra/helper.py build_fuzzers observal OK
infra/helper.py check_build observal Check build passed (4/4)
infra/helper.py build_fuzzers --sanitizer undefined observal OK
infra/helper.py check_build --sanitizer undefined observal Check build passed (4/4)
infra/helper.py build_fuzzers --sanitizer coverage observal OK
infra/helper.py run_fuzzer observal <each target> -- -runs=3000 OK, no findings
infra/presubmit.py Success

The build was verified with a cold, cache-free image build to confirm it does not
depend on any local layer cache.

Maintenance

  • The three files here are mirrored in the project repo at fuzz/oss-fuzz/ and are
    currently byte-identical. The project's contributor docs require both copies to be
    updated in the same change, so they do not drift.
  • Confirmed builds succeed for both declared sanitizers before submission, and we
    will keep them building.
  • Reports will be triaged by the contacts below, with confirmed crashes turned into
    in-repo regression tests alongside the fix.

Observal is an agent-centric registry and observability platform for AI
coding agents (https://github.com/Observal/Observal).

Four Atheris targets are maintained in the project's own repository under
fuzz/ and cover its untrusted input boundaries:

  session_jsonl_fuzzer      harness session transcripts, ingest classification
                            and read-path parsing for every supported harness
  session_structure_fuzzer  the same pipeline driven by Hypothesis-generated
                            records rather than raw bytes
  secrets_redactor_fuzzer   server-side secret redaction applied before storage
  support_redaction_fuzzer  CLI support-bundle redaction

Every target runs in-process, opens no sockets and touches no databases, so
findings reproduce from their input alone. Seed corpora and dictionaries are
picked up automatically by build.sh.

Validated locally with build_image, build_fuzzers for the address, undefined
and coverage configurations, check_build for address and undefined, and
run_fuzzer over all four targets.
@google-cla

google-cla Bot commented Aug 13, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@github-actions

Copy link
Copy Markdown

RAWx18 is integrating a new project:
- Main repo: https://github.com/Observal/Observal.git
- Criticality score: 0.50372

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant